diff -Nru icu-64.2/APIChangeReport.html icu-65.1/APIChangeReport.html --- icu-64.2/APIChangeReport.html 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/APIChangeReport.html 2019-10-03 11:16:41.000000000 +0000 @@ -1,104 +1,100 @@ -ICU4C API Comparison: ICU 63 with ICU 64 (update #1: 64.2) +ICU4C API Comparison: ICU 64 (update #1: 64.2) with ICU 65 -

ICU4C API Comparison: ICU 63 with ICU 64 (update #1: 64.2)

+

ICU4C API Comparison: ICU 64 (update #1: 64.2) with ICU 65


-

Removed from ICU 63

+

Removed from ICU 64

- + - - - - - - - - - - - - - - - -
FileAPIICU 63ICU 64FileAPIICU 64ICU 65
localpointer.hLocalArray<T>& icu::LocalArray< T >::moveFrom(LocalArray< T >&)Draft
ICU 56
(missing)
+
decimfmt.hconst number::LocalizedNumberFormatter& icu::DecimalFormat::toNumberFormatter() constDeprecated
ICU 64
(missing)
localpointer.hLocalPointer<T>& icu::LocalPointer< T >::moveFrom(LocalPointer< T >&)Draft
ICU 56
(missing)
+
edits.hUBool icu::Edits::copyErrorTo(UErrorCode&)Stable
ICU 59
(missing)
numberformatter.hAppendable& icu::number::FormattedNumber::appendTo(Appendable&)Deprecated
ICU 62
(missing)
+
platform.h#define __has_attributeInternal(missing)
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::rounding(const Rounder&) const&Deprecated
ICU 62
(missing)
+
platform.h#define __has_builtinInternal(missing)
numberformatter.hPrecision icu::number::Precision::withMode(UNumberFormatRoundingMode) constDeprecated
ICU 62
(missing)
+
platform.h#define __has_cpp_attributeInternal(missing)
numberformatter.hUnicodeString icu::number::FormattedNumber::toString() constDeprecated
ICU 62
(missing)
+
platform.h#define __has_declspec_attributeInternal(missing)
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::fixedDigits(int32_t)Deprecated
ICU 62
(missing)
+
platform.h#define __has_extensionInternal(missing)
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::maxDigits(int32_t)Deprecated
ICU 62
(missing)
+
platform.h#define __has_featureInternal(missing)
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minDigits(int32_t)Deprecated
ICU 62
(missing)
+
platform.h#define __has_warningInternal(missing)
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minMaxDigits(int32_t, int32_t)Deprecated
ICU 62
(missing)
+
uversion.h#define U_NAMESPACE_BEGINStable
ICU 2.4
(missing)
numberformatter.hvoid icu::number::FormattedNumber::populateFieldPosition(FieldPosition&, UErrorCode&)Deprecated
ICU 62
(missing)
+
uversion.h#define U_NAMESPACE_ENDStable
ICU 2.4
(missing)
numberformatter.hvoid icu::number::FormattedNumber::populateFieldPositionIterator(FieldPositionIterator&, UErrorCode&)Deprecated
ICU 62
(missing)
+
uversion.h#define U_NAMESPACE_QUALIFIERStable
ICU 2.4
(missing)
numsys.h#define NUMSYS_NAME_CAPACITYInternal(missing)
-
unistr.hUnicodeString& icu::UnicodeString::moveFrom(UnicodeString&)Draft
ICU 56
(missing)
+
uversion.h#define U_NAMESPACE_USEStable
ICU 2.4
(missing)
@@ -106,2432 +102,3038 @@ (jump back to top)
-

Deprecated or Obsoleted in ICU 64

+

Deprecated or Obsoleted in ICU 65

- + - - - - - -
FileAPIICU 63ICU 64FileAPIICU 64ICU 65
brkiter.hstatic BreakIterator* icu::BreakIterator::createTitleInstance(const Locale&, UErrorCode&)Stable
ICU 2.1
Deprecated
-ICU 64
decimfmt.hconst number::LocalizedNumberFormatter& icu::DecimalFormat::toNumberFormatter() constDraft
ICU 62
Deprecated
-ICU 64

(jump back to top)
-

Changed in ICU 64 (old, new)

+

Changed in ICU 65 (old, new)

- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
FileAPIICU 63ICU 64FileAPIICU 64ICU 65
brkiter.hstatic BreakIterator* icu::BreakIterator::createTitleInstance(const Locale&, UErrorCode&)Stable
ICU 2.1
Deprecated
-ICU 64
decimfmt.hint32_t icu::DecimalFormat::getMultiplierScale() constDraft→Stable
ICU 62
decimfmt.hUBool icu::DecimalFormat::isFormatFailIfMoreThanMaxDigits() constInternalDraft
-ICU 64
decimfmt.hvoid icu::DecimalFormat::setMultiplierScale(int32_t)Draft→Stable
ICU 62
decimfmt.hUBool icu::DecimalFormat::isParseCaseSensitive() constInternalDraft
-ICU 64
locid.hLocale& icu::Locale::operator=(Locale&&)Draft→Stable
ICU 63
decimfmt.hUBool icu::DecimalFormat::isParseNoExponent() constInternalDraft
-ICU 64
locid.hStringClass icu::Locale::getKeywordValue(StringPiece, UErrorCode&) constDraft→Stable
ICU 63
decimfmt.hUBool icu::DecimalFormat::isSignAlwaysShown() constInternalDraft
-ICU 64
locid.hStringClass icu::Locale::getUnicodeKeywordValue(StringPiece, UErrorCode&) constDraft→Stable
ICU 63
decimfmt.hconst number::LocalizedNumberFormatter& icu::DecimalFormat::toNumberFormatter() constDraft
ICU 62
Deprecated
-ICU 64
locid.hStringClass icu::Locale::toLanguageTag(UErrorCode&) constDraft→Stable
ICU 63
decimfmt.hint32_t icu::DecimalFormat::getMinimumGroupingDigits() constInternalDraft
-ICU 64
locid.hStringEnumeration* icu::Locale::createUnicodeKeywords(UErrorCode&) constDraft→Stable
ICU 63
decimfmt.hvoid icu::DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool)InternalDraft
-ICU 64
locid.hicu::Locale::Locale(Locale&&)Draft→Stable
ICU 63
decimfmt.hvoid icu::DecimalFormat::setMinimumGroupingDigits(int32_t)InternalDraft
-ICU 64
locid.hstatic Locale icu::Locale::forLanguageTag(StringPiece, UErrorCode&)Draft→Stable
ICU 63
decimfmt.hvoid icu::DecimalFormat::setParseCaseSensitive(UBool)InternalDraft
-ICU 64
locid.hvoid icu::Locale::addLikelySubtags(UErrorCode&)Draft→Stable
ICU 63
decimfmt.hvoid icu::DecimalFormat::setParseNoExponent(UBool)InternalDraft
-ICU 64
locid.hvoid icu::Locale::getKeywordValue(StringPiece, ByteSink&, UErrorCode&) constDraft→Stable
ICU 63
decimfmt.hvoid icu::DecimalFormat::setSignAlwaysShown(UBool)InternalDraft
-ICU 64
locid.hvoid icu::Locale::getKeywords(OutputIterator, UErrorCode&) constDraft→Stable
ICU 63
dtptngen.hUnicodeString icu::DateTimePatternGenerator::getFieldDisplayName(UDateTimePatternField, UDateTimePGDisplayWidth) constDraft→Stable
ICU 61
locid.hvoid icu::Locale::getUnicodeKeywordValue(StringPiece, ByteSink&, UErrorCode&) constDraft→Stable
ICU 63
ucurr.henum UCurrNameStyle::UCURR_NARROW_SYMBOL_NAMEDraft→Stable
ICU 61
locid.hvoid icu::Locale::getUnicodeKeywords(OutputIterator, UErrorCode&) constDraft→Stable
ICU 63
udatpg.henum UDateTimePGDisplayWidth::UDATPG_ABBREVIATEDDraft→Stable
ICU 61
locid.hvoid icu::Locale::minimizeSubtags(UErrorCode&)Draft→Stable
ICU 63
udatpg.henum UDateTimePGDisplayWidth::UDATPG_NARROWDraft→Stable
ICU 61
locid.hvoid icu::Locale::setKeywordValue(StringPiece, StringPiece, UErrorCode&)Draft→Stable
ICU 63
udatpg.henum UDateTimePGDisplayWidth::UDATPG_WIDEDraft→Stable
ICU 61
locid.hvoid icu::Locale::setUnicodeKeywordValue(StringPiece, StringPiece, UErrorCode&)Draft→Stable
ICU 63
udatpg.hint32_t udatpg_getFieldDisplayName(const UDateTimePatternGenerator*, UDateTimePatternField, UDateTimePGDisplayWidth, UChar*, int32_t, UErrorCode*)Draft→Stable
ICU 61
locid.hvoid icu::Locale::toLanguageTag(ByteSink&, UErrorCode&) constDraft→Stable
ICU 63
unum.henum UNumberFormatAttribute::UNUM_MINIMUM_GROUPING_DIGITSInternalDraft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createAtmosphere(UErrorCode&)Draft→Stable
ICU 63
unum.henum UNumberFormatAttribute::UNUM_PARSE_CASE_SENSITIVEInternalDraft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPercent(UErrorCode&)Draft→Stable
ICU 63
unum.henum UNumberFormatAttribute::UNUM_SIGN_ALWAYS_SHOWNInternalDraft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPermille(UErrorCode&)Draft→Stable
ICU 63
unumberformatter.hUBool unumf_resultNextFieldPosition(const UFormattedNumber*, UFieldPosition*, UErrorCode*)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPetabyte(UErrorCode&)Draft→Stable
ICU 63
unumberformatter.hUFormattedNumber* unumf_openResult(UErrorCode*)Draft→Stable
ICU 62
numberformatter.hAppendable& icu::number::FormattedNumber::appendTo(Appendable&, UErrorCode&) constDraft→Stable
ICU 62
unumberformatter.hUNumberFormatter* unumf_openForSkeletonAndLocale(const UChar*, int32_t, const char*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*) const&Draft→Stable
ICU 61
unumberformatter.hint32_t unumf_resultToString(const UFormattedNumber*, UChar*, int32_t, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*)&&Draft→Stable
ICU 62
unumberformatter.hvoid unumf_close(UNumberFormatter*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*) const&Draft→Stable
ICU 60
unumberformatter.hvoid unumf_closeResult(UFormattedNumber*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*)&&Draft→Stable
ICU 62
unumberformatter.hvoid unumf_formatDecimal(const UNumberFormatter*, const char*, int32_t, UFormattedNumber*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*) const&Draft→Stable
ICU 60
unumberformatter.hvoid unumf_formatDouble(const UNumberFormatter*, double, UFormattedNumber*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*)&&Draft→Stable
ICU 62
unumberformatter.hvoid unumf_formatInt(const UNumberFormatter*, int64_t, UFormattedNumber*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay) const&Draft→Stable
ICU 60
unumberformatter.hvoid unumf_resultGetAllFieldPositions(const UFormattedNumber*, UFieldPositionIterator*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay)&&Draft→Stable
ICU 62
utf8.h#define U8_TRUNCATE_IF_INCOMPLETEDraft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy) const&Draft→Stable
ICU 61
-

-(jump back to top) -
- -

Promoted to stable in ICU 64

- - - - + + + + + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
FileAPIICU 63ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy)&&Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&) const&Draft→Stable
ICU 60
dtptngen.hUnicodeString icu::DateTimePatternGenerator::getFieldDisplayName(UDateTimePatternField, UDateTimePGDisplayWidth) constDraft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&)&&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&) const&Draft→Stable
ICU 60
uchar.henum UBlockCode::UBLOCK_ELYMAIC(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&)&&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_NANDINAGARI(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&) const&Draft→Stable
ICU 61
uchar.henum UBlockCode::UBLOCK_NYIAKENG_PUACHUE_HMONG(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&)&&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_OTTOMAN_SIYAQ_NUMBERS(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&) const&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_SMALL_KANA_EXTENSION(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&)&&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode) const&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_TAMIL_SUPPLEMENT(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode)&&Draft→Stable
ICU 62
uchar.henum UBlockCode::UBLOCK_WANCHO(missing)Stable
-ICU 64
(Born Stable)numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&) const&Draft→Stable
ICU 62
ucurr.henum UCurrNameStyle::UCURR_NARROW_SYMBOL_NAMEDraft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&)&&Draft→Stable
ICU 62
udatpg.henum UDateTimePGDisplayWidth::UDATPG_ABBREVIATEDDraft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay) const&Draft→Stable
ICU 60
udatpg.henum UDateTimePGDisplayWidth::UDATPG_NARROWDraft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay)&&Draft→Stable
ICU 62
udatpg.henum UDateTimePGDisplayWidth::UDATPG_WIDEDraft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&) const&Draft→Stable
ICU 60
udatpg.hint32_t udatpg_getFieldDisplayName(const UDateTimePatternGenerator*, UDateTimePatternField, UDateTimePGDisplayWidth, UChar*, int32_t, UErrorCode*)Draft→Stable
ICU 61
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&)&&Draft→Stable
ICU 62
unumberformatter.hUBool unumf_resultNextFieldPosition(const UFormattedNumber*, UFieldPosition*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&) const&Draft→Stable
ICU 60
unumberformatter.hUFormattedNumber* unumf_openResult(UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&)&&Draft→Stable
ICU 62
unumberformatter.hUNumberFormatter* unumf_openForSkeletonAndLocale(const UChar*, int32_t, const char*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth) const&Draft→Stable
ICU 60
unumberformatter.hint32_t unumf_resultToString(const UFormattedNumber*, UChar*, int32_t, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth)&&Draft→Stable
ICU 62
unumberformatter.hvoid unumf_close(UNumberFormatter*)Draft→Stable
ICU 62
numberformatter.hFormat* icu::number::LocalizedNumberFormatter::toFormat(UErrorCode&) constDraft→Stable
ICU 62
unumberformatter.hvoid unumf_closeResult(UFormattedNumber*)Draft→Stable
ICU 62
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatDecimal(StringPiece, UErrorCode&) constDraft→Stable
ICU 60
unumberformatter.hvoid unumf_formatDecimal(const UNumberFormatter*, const char*, int32_t, UFormattedNumber*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatDouble(double, UErrorCode&) constDraft→Stable
ICU 60
unumberformatter.hvoid unumf_formatDouble(const UNumberFormatter*, double, UFormattedNumber*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatInt(int64_t, UErrorCode&) constDraft→Stable
ICU 60
unumberformatter.hvoid unumf_formatInt(const UNumberFormatter*, int64_t, UFormattedNumber*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hFormattedNumber& icu::number::FormattedNumber::operator=(FormattedNumber&&)Draft→Stable
ICU 62
unumberformatter.hvoid unumf_resultGetAllFieldPositions(const UFormattedNumber*, UFieldPositionIterator*, UErrorCode*)Draft→Stable
ICU 62
numberformatter.hIntegerWidth icu::number::IntegerWidth::truncateAt(int32_t)Draft→Stable
ICU 60
uscript.henum UScriptCode::USCRIPT_ELYMAIC(missing)Stable
-ICU 64
(Born Stable)numberformatter.hLocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&) const&Draft→Stable
ICU 60
uscript.henum UScriptCode::USCRIPT_NANDINAGARI(missing)Stable
-ICU 64
(Born Stable)numberformatter.hLocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&)&&Draft→Stable
ICU 62
uscript.henum UScriptCode::USCRIPT_NYIAKENG_PUACHUE_HMONG(missing)Stable
-ICU 64
(Born Stable)numberformatter.hLocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(LocalizedNumberFormatter&&)Draft→Stable
ICU 62
uscript.henum UScriptCode::USCRIPT_WANCHO(missing)Stable
-ICU 64
(Born Stable)numberformatter.hLocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(const LocalizedNumberFormatter&)Draft→Stable
ICU 62
utf8.h#define U8_TRUNCATE_IF_INCOMPLETEDraft→Stable
ICU 61
numberformatter.hPrecision icu::number::CurrencyPrecision::withCurrency(const CurrencyUnit&) constDraft→Stable
ICU 60
utypes.henum UErrorCode::U_NUMBER_ARG_OUTOFBOUNDS_ERROR(missing)Stable
-ICU 61
numberformatter.hPrecision icu::number::FractionPrecision::withMaxDigits(int32_t) constDraft→Stable
ICU 60
utypes.henum UErrorCode::U_NUMBER_SKELETON_SYNTAX_ERROR(missing)Stable
-ICU 62
numberformatter.hPrecision icu::number::FractionPrecision::withMinDigits(int32_t) constDraft→Stable
ICU 60
-

-(jump back to top) -
- -

Added in ICU 64

- - - - + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + +
FileAPIICU 63ICU 64
numberformatter.hPrecision icu::number::IncrementPrecision::withMinFraction(int32_t) constDraft→Stable
ICU 60
numberformatter.hScale& icu::number::Scale::operator=(Scale&&)Draft→Stable
ICU 62
numberformatter.hScale& icu::number::Scale::operator=(const Scale&)Draft→Stable
ICU 62
numberformatter.hScientificNotation icu::number::ScientificNotation::withExponentSignDisplay(UNumberSignDisplay) constDraft→Stable
ICU 60
numberformatter.hScientificNotation icu::number::ScientificNotation::withMinExponentDigits(int32_t) constDraft→Stable
ICU 60
numberformatter.hUBool icu::number::NumberFormatterSettings< Derived >::copyErrorTo(UErrorCode&) constDraft→Stable
ICU 60
numberformatter.hUnicodeString icu::number::FormattedNumber::toString(UErrorCode&) constDraft→Stable
ICU 62
numberformatter.hUnicodeString icu::number::NumberFormatterSettings< Derived >::toSkeleton(UErrorCode&) constDraft→Stable
ICU 62
currunit.hicu::CurrencyUnit::CurrencyUnit(StringPiece, UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hUnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(UnlocalizedNumberFormatter&&)Draft→Stable
ICU 62
decimfmt.hconst number::LocalizedNumberFormatter* icu::DecimalFormat::toNumberFormatter(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hUnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(const UnlocalizedNumberFormatter&)Draft→Stable
ICU 62
dtitvfmt.hAppendable& icu::FormattedDateInterval::appendTo(Appendable&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hicu::number::FormattedNumber::FormattedNumber(FormattedNumber&&)Draft→Stable
ICU 62
dtitvfmt.hFormattedDateInterval icu::DateIntervalFormat::formatToValue(Calendar&, Calendar&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hicu::number::FormattedNumber::~FormattedNumber()Draft→Stable
ICU 60
dtitvfmt.hFormattedDateInterval icu::DateIntervalFormat::formatToValue(const DateInterval&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter()=defaultDraft→Stable
ICU 62
dtitvfmt.hFormattedDateInterval& icu::FormattedDateInterval::operator=(FormattedDateInterval&&)(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&&)Draft→Stable
ICU 62
dtitvfmt.hFormattedDateInterval& icu::FormattedDateInterval::operator=(const FormattedDateInterval&)=delete(missing) -
- -
-(untagged)
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(const LocalizedNumberFormatter&)Draft→Stable
ICU 60
dtitvfmt.hUBool icu::FormattedDateInterval::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::~LocalizedNumberFormatter()Draft→Stable
ICU 60
dtitvfmt.hUnicodeString icu::FormattedDateInterval::toString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hicu::number::Scale::Scale(Scale&&)Draft→Stable
ICU 62
dtitvfmt.hUnicodeString icu::FormattedDateInterval::toTempString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hicu::number::Scale::Scale(const Scale&)Draft→Stable
ICU 62
dtitvfmt.hicu::FormattedDateInterval::FormattedDateInterval()(missing)Draft
-ICU 64
numberformatter.hicu::number::Scale::~Scale()Draft→Stable
ICU 62
dtitvfmt.hicu::FormattedDateInterval::FormattedDateInterval(FormattedDateInterval&&)(missing)Draft
-ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter()=defaultDraft→Stable
ICU 62
dtitvfmt.hicu::FormattedDateInterval::FormattedDateInterval(const FormattedDateInterval&)=delete(missing) -
- -
-(untagged)
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&&)Draft→Stable
ICU 62
dtitvfmt.hicu::FormattedDateInterval::~FormattedDateInterval()(missing)Draft
-ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter&)Draft→Stable
ICU 60
formattedvalue.hAppendable& icu::FormattedValue::appendTo(Appendable&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic CompactNotation icu::number::Notation::compactLong()Draft→Stable
ICU 60
formattedvalue.hUBool icu::ConstrainedFieldPosition::matchesField(int32_t, int32_t) const(missing)Draft
-ICU 64
numberformatter.hstatic CompactNotation icu::number::Notation::compactShort()Draft→Stable
ICU 60
formattedvalue.hUBool icu::FormattedValue::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic CurrencyPrecision icu::number::Precision::currency(UCurrencyUsage)Draft→Stable
ICU 60
formattedvalue.hUnicodeString icu::FormattedValue::toString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::fixedFraction(int32_t)Draft→Stable
ICU 60
formattedvalue.hUnicodeString icu::FormattedValue::toTempString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::integer()Draft→Stable
ICU 60
formattedvalue.hicu::ConstrainedFieldPosition::ConstrainedFieldPosition()(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::maxFraction(int32_t)Draft→Stable
ICU 60
formattedvalue.hicu::ConstrainedFieldPosition::~ConstrainedFieldPosition()(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::minFraction(int32_t)Draft→Stable
ICU 60
formattedvalue.hicu::FormattedValue::~FormattedValue()(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::minMaxFraction(int32_t, int32_t)Draft→Stable
ICU 60
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getCategory() const(missing)Draft
-ICU 64
numberformatter.hstatic IncrementPrecision icu::number::Precision::increment(double)Draft→Stable
ICU 60
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getField() const(missing)Draft
-ICU 64
numberformatter.hstatic IntegerWidth icu::number::IntegerWidth::zeroFillTo(int32_t)Draft→Stable
ICU 60
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getLimit() const(missing)Draft
-ICU 64
numberformatter.hstatic LocalizedNumberFormatter icu::number::NumberFormatter::withLocale(const Locale&)Draft→Stable
ICU 60
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getStart() const(missing)Draft
-ICU 64
numberformatter.hstatic Precision icu::number::Precision::unlimited()Draft→Stable
ICU 60
formattedvalue.hint64_t icu::ConstrainedFieldPosition::getInt64IterationContext() const(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDecimal(StringPiece)Draft→Stable
ICU 62
formattedvalue.hvoid icu::ConstrainedFieldPosition::constrainCategory(int32_t)(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDouble(double)Draft→Stable
ICU 62
formattedvalue.hvoid icu::ConstrainedFieldPosition::constrainField(int32_t, int32_t)(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDoubleAndPowerOfTen(double, int32_t)Draft→Stable
ICU 62
formattedvalue.hvoid icu::ConstrainedFieldPosition::reset()(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::none()Draft→Stable
ICU 62
formattedvalue.hvoid icu::ConstrainedFieldPosition::setInt64IterationContext(int64_t)(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::powerOfTen(int32_t)Draft→Stable
ICU 62
formattedvalue.hvoid icu::ConstrainedFieldPosition::setState(int32_t, int32_t, int32_t, int32_t)(missing)Draft
-ICU 64
numberformatter.hstatic ScientificNotation icu::number::Notation::engineering()Draft→Stable
ICU 60
listformatter.hAppendable& icu::FormattedList::appendTo(Appendable&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic ScientificNotation icu::number::Notation::scientific()Draft→Stable
ICU 60
listformatter.hFormattedList icu::ListFormatter::formatStringsToValue(const UnicodeString items[], int32_t, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::fixedSignificantDigits(int32_t)Draft→Stable
ICU 62
listformatter.hFormattedList& icu::FormattedList::operator=(FormattedList&&)(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::maxSignificantDigits(int32_t)Draft→Stable
ICU 62
listformatter.hFormattedList& icu::FormattedList::operator=(const FormattedList&)=delete(missing) -
- -
-(untagged)
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minMaxSignificantDigits(int32_t, int32_t)Draft→Stable
ICU 62
listformatter.hUBool icu::FormattedList::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minSignificantDigits(int32_t)Draft→Stable
ICU 62
listformatter.hUnicodeString icu::FormattedList::toString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic SimpleNotation icu::number::Notation::simple()Draft→Stable
ICU 60
listformatter.hUnicodeString icu::FormattedList::toTempString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UErrorCode&)Draft→Stable
ICU 62
listformatter.hicu::FormattedList::FormattedList()(missing)Draft
-ICU 64
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::with()Draft→Stable
ICU 60
listformatter.hicu::FormattedList::FormattedList(FormattedList&&)(missing)Draft
-ICU 64
numberrangeformatter.hAppendable& icu::number::FormattedNumberRange::appendTo(Appendable&, UErrorCode&) constDraft→Stable
ICU 63
listformatter.hicu::FormattedList::FormattedList(const FormattedList&)=delete(missing) -
- -
-(untagged)
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse) const&Draft→Stable
ICU 63
listformatter.hicu::FormattedList::~FormattedList()(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse)&&Draft→Stable
ICU 63
localebuilder.hLocale icu::LocaleBuilder::build(UErrorCode&)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback) const&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::addUnicodeLocaleAttribute(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback)&&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::clear()(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&) const&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::clearExtensions()(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&)&&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::removeUnicodeLocaleAttribute(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&) const&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setExtension(char, StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&)&&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setLanguage(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&) const&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setLanguageTag(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&)&&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setLocale(const Locale&)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&) const&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setRegion(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&)&&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setScript(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&) const&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setUnicodeLocaleKeyword(StringPiece, StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&)&&Draft→Stable
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setVariant(StringPiece)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&) const&Draft→Stable
ICU 63
localebuilder.hicu::LocaleBuilder::LocaleBuilder()(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&)&&Draft→Stable
ICU 63
localebuilder.hicu::LocaleBuilder::~LocaleBuilder()(missing)Draft
-ICU 64
numberrangeformatter.hFormattedNumberRange icu::number::LocalizedNumberRangeFormatter::formatFormattableRange(const Formattable&, const Formattable&, UErrorCode&) constDraft→Stable
ICU 63
localpointer.hLocalArray<T>& icu::LocalArray< T >::operator=(std::unique_ptr< T[]>&&)(missing)Draft
-ICU 64
numberrangeformatter.hFormattedNumberRange& icu::number::FormattedNumberRange::operator=(FormattedNumberRange&&)Draft→Stable
ICU 63
localpointer.hLocalPointer<T>& icu::LocalPointer< T >::operator=(std::unique_ptr< T >&&)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&) const&Draft→Stable
ICU 63
localpointer.hicu::LocalArray< T >::LocalArray(std::unique_ptr< T[]>&&)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&)&&Draft→Stable
ICU 63
localpointer.hicu::LocalArray< T >::operator std::unique_ptr< T[]>() &&(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(LocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
localpointer.hicu::LocalPointer< T >::LocalPointer(std::unique_ptr< T >&&)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(const LocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
localpointer.hicu::LocalPointer< T >::operator std::unique_ptr< T >() &&(missing)Draft
-ICU 64
numberrangeformatter.hUBool icu::number::NumberRangeFormatterSettings< Derived >::copyErrorTo(UErrorCode&) constDraft→Stable
ICU 63
localpointer.hstatic void* icu::LocalPointerBase< T >::operator new(size_t)=delete(missing) -
- -
-(untagged)
numberrangeformatter.hUNumberRangeIdentityResult icu::number::FormattedNumberRange::getIdentityResult(UErrorCode&) constDraft→Stable
ICU 63
localpointer.hstatic void* icu::LocalPointerBase< T >::operator new[](size_t)=delete(missing) -
- -
-(untagged)
numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::toString(UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAcre()(missing)Draft
-ICU 64
numberrangeformatter.hUnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(UnlocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAcreFoot()(missing)Draft
-ICU 64
numberrangeformatter.hUnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(const UnlocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAmpere()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_ALLDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getArcMinute()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_AUTODraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getArcSecond()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_NONEDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAstronomicalUnit()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_UNITDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAtmosphere()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUEDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBarrel()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELYDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBit()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_RANGEDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBritishThermalUnit()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_SINGLE_VALUEDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBushel()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDINGDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getByte()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDINGDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCalorie()(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_NOT_EQUALDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCarat()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCelsius()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::FormattedNumberRange::~FormattedNumberRange()Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCentiliter()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter()=defaultDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCentimeter()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCentury()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicCentimeter()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter()Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicFoot()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter()=defaultDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicInch()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicKilometer()(missing)Draft
-ICU 64
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicMeter()(missing)Draft
-ICU 64
numberrangeformatter.hstatic LocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::withLocale(const Locale&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicMile()(missing)Draft
-ICU 64
numberrangeformatter.hstatic UnlocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::with()Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicYard()(missing)Draft
-ICU 64
reldatefmt.henum UDateAbsoluteUnit::UDAT_ABSOLUTE_QUARTERDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCup()(missing)Draft
-ICU 64
uchar.hconst UCPMap* u_getIntPropertyMap(UProperty, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCupMetric()(missing)Draft
-ICU 64
uchar.hconst USet* u_getBinaryPropertySet(UProperty, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDalton()(missing)Draft
-ICU 64
ucpmap.hUChar32 ucpmap_getRange(const UCPMap*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDay()(missing)Draft
-ICU 64
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_FIXED_ALL_SURROGATESDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDayPerson()(missing)Draft
-ICU 64
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_FIXED_LEAD_SURROGATESDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDeciliter()(missing)Draft
-ICU 64
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_NORMALDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDecimeter()(missing)Draft
-ICU 64
ucpmap.huint32_t ucpmap_get(const UCPMap*, UChar32)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDegree()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_16Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDunam()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_32Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getEarthMass()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_8Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getElectronvolt()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_ASCII_GETDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFahrenheit()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_BMP_GETDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFathom()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_GETDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFluidOunce()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_SUPP_GETDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFluidOunceImperial()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_U16_NEXTDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFoodcalorie()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_U16_PREVDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFoot()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_U8_NEXTDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFurlong()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_FAST_U8_PREVDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGForce()(missing)Draft
-ICU 64
ucptrie.h#define UCPTRIE_SMALL_GETDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGallon()(missing)Draft
-ICU 64
ucptrie.hUCPTrie* ucptrie_openFromBinary(UCPTrieType, UCPTrieValueWidth, const void*, int32_t, int32_t*, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGallonImperial()(missing)Draft
-ICU 64
ucptrie.hUCPTrieType ucptrie_getType(const UCPTrie*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGenericTemperature()(missing)Draft
-ICU 64
ucptrie.hUCPTrieValueWidth ucptrie_getValueWidth(const UCPTrie*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigabit()(missing)Draft
-ICU 64
ucptrie.hUChar32 ucptrie_getRange(const UCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigabyte()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_ANYDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigahertz()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_FASTDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigawatt()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_SMALLDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGram()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_16Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHectare()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_32Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHectoliter()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_8Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHectopascal()(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_ANYDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHertz()(missing)Draft
-ICU 64
ucptrie.hint32_t ucptrie_toBinary(const UCPTrie*, void*, int32_t, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHorsepower()(missing)Draft
-ICU 64
ucptrie.huint32_t ucptrie_get(const UCPTrie*, UChar32)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHour()(missing)Draft
-ICU 64
ucptrie.hvoid ucptrie_close(UCPTrie*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getInch()(missing)Draft
-ICU 64
umutablecptrie.hUCPTrie* umutablecptrie_buildImmutable(UMutableCPTrie*, UCPTrieType, UCPTrieValueWidth, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getInchHg()(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_clone(const UMutableCPTrie*, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getJoule()(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_fromUCPMap(const UCPMap*, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKarat()(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_fromUCPTrie(const UCPTrie*, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKelvin()(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_open(uint32_t, uint32_t, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilobit()(missing)Draft
-ICU 64
umutablecptrie.hUChar32 umutablecptrie_getRange(const UMutableCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilobyte()(missing)Draft
-ICU 64
umutablecptrie.huint32_t umutablecptrie_get(const UMutableCPTrie*, UChar32)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilocalorie()(missing)Draft
-ICU 64
umutablecptrie.hvoid umutablecptrie_close(UMutableCPTrie*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilogram()(missing)Draft
-ICU 64
umutablecptrie.hvoid umutablecptrie_set(UMutableCPTrie*, UChar32, uint32_t, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilohertz()(missing)Draft
-ICU 64
umutablecptrie.hvoid umutablecptrie_setRange(UMutableCPTrie*, UChar32, UChar32, uint32_t, UErrorCode*)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilojoule()(missing)Draft
-ICU 64
unumberformatter.henum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_ALWAYSDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilometer()(missing)Draft
-ICU 64
unumberformatter.henum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_AUTODraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilometerPerHour()(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_AUTODraft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilopascal()(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_MIN2Draft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilowatt()(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_OFFDraft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilowattHour()(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_ON_ALIGNEDDraft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKnot()(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_THOUSANDSDraft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getLightYear()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYSDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getLiter()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERODraft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getLiterPer100Kilometers()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTINGDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getLiterPerKilometer()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ALWAYSDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getLux()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_AUTODraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegabit()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERODraft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegabyte()(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_NEVERDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegahertz()(missing)Draft
-ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAMEDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegaliter()(missing)Draft
-ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDENDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegapascal()(missing)Draft
-ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODEDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegawatt()(missing)Draft
-ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROWDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMeter()(missing)Draft
-ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORTDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getMeterPerSecond()(missing)Draft
-ICU 64
uspoof.henum USpoofChecks::USPOOF_HIDDEN_OVERLAYDraft→Stable
ICU 62
utf_old.h#define U_HIDE_OBSOLETE_UTF_OLD_HDeprecated
ICU 2.4
Internal
+
+

+(jump back to top) +
+ +

Promoted to stable in ICU 65

+ + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
FileAPIICU 64ICU 65
measunit.hstatic MeasureUnit icu::MeasureUnit::getMeterPerSecondSquared()(missing)Draft
-ICU 64
basictz.hvoid* icu::BasicTimeZone::clone() const(missing)Stable
+ICU 3.8
measunit.hstatic MeasureUnit icu::MeasureUnit::getMetricTon()(missing)Draft
-ICU 64
datefmt.hvoid* icu::DateFormat::clone() const(missing)Stable
+ICU 2.0
measunit.hstatic MeasureUnit icu::MeasureUnit::getMicrogram()(missing)Draft
-ICU 64
decimfmt.hint32_t icu::DecimalFormat::getMultiplierScale() constDraft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getMicrometer()(missing)Draft
-ICU 64
decimfmt.hvoid icu::DecimalFormat::setMultiplierScale(int32_t)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getMicrosecond()(missing)Draft
-ICU 64
edits.hUBool icu::Edits::copyErrorTo(UErrorCode&) const(missing)Stable
+ICU 59
measunit.hstatic MeasureUnit icu::MeasureUnit::getMile()(missing)Draft
-ICU 64
locid.hLocale& icu::Locale::operator=(Locale&&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilePerGallon()(missing)Draft
-ICU 64
locid.hStringClass icu::Locale::getKeywordValue(StringPiece, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilePerGallonImperial()(missing)Draft
-ICU 64
locid.hStringClass icu::Locale::getUnicodeKeywordValue(StringPiece, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilePerHour()(missing)Draft
-ICU 64
locid.hStringClass icu::Locale::toLanguageTag(UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMileScandinavian()(missing)Draft
-ICU 64
locid.hStringEnumeration* icu::Locale::createUnicodeKeywords(UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilliampere()(missing)Draft
-ICU 64
locid.hicu::Locale::Locale(Locale&&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMillibar()(missing)Draft
-ICU 64
locid.hstatic Locale icu::Locale::forLanguageTag(StringPiece, UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilligram()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::addLikelySubtags(UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilligramPerDeciliter()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::getKeywordValue(StringPiece, ByteSink&, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilliliter()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::getKeywords(OutputIterator, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMillimeter()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::getUnicodeKeywordValue(StringPiece, ByteSink&, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMillimeterOfMercury()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::getUnicodeKeywords(OutputIterator, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMillimolePerLiter()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::minimizeSubtags(UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMillisecond()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::setKeywordValue(StringPiece, StringPiece, UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMilliwatt()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::setUnicodeKeywordValue(StringPiece, StringPiece, UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMinute()(missing)Draft
-ICU 64
locid.hvoid icu::Locale::toLanguageTag(ByteSink&, UErrorCode&) constDraft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMole()(missing)Draft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createAtmosphere(UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMonth()(missing)Draft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPercent(UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getMonthPerson()(missing)Draft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPermille(UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getNanometer()(missing)Draft
-ICU 64
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPetabyte(UErrorCode&)Draft→Stable
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getNanosecond()(missing)Draft
-ICU 64
numberformatter.hAppendable& icu::number::FormattedNumber::appendTo(Appendable&, UErrorCode&) constDraft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getNauticalMile()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*) const&Draft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getNewton()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getNewtonMeter()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getOhm()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getOunce()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getOunceTroy()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getParsec()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getPartPerMillion()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPercent()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy) const&Draft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getPermille()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPermyriad()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getPetabyte()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPicometer()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getPint()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPintMetric()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&) const&Draft→Stable
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getPoint()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPound()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&) const&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPoundFoot()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPoundForce()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode) const&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPoundPerSquareInch()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getQuart()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&) const&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getRadian()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getRevolutionAngle()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getSecond()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getSolarLuminosity()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getSolarMass()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getSolarRadius()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareCentimeter()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareFoot()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareInch()(missing)Draft
-ICU 64
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareKilometer()(missing)Draft
-ICU 64
numberformatter.hFormat* icu::number::LocalizedNumberFormatter::toFormat(UErrorCode&) constDraft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareMeter()(missing)Draft
-ICU 64
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatDecimal(StringPiece, UErrorCode&) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareMile()(missing)Draft
-ICU 64
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatDouble(double, UErrorCode&) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareYard()(missing)Draft
-ICU 64
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatInt(int64_t, UErrorCode&) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getStone()(missing)Draft
-ICU 64
numberformatter.hFormattedNumber& icu::number::FormattedNumber::operator=(FormattedNumber&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getTablespoon()(missing)Draft
-ICU 64
numberformatter.hIntegerWidth icu::number::IntegerWidth::truncateAt(int32_t)Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getTeaspoon()(missing)Draft
-ICU 64
numberformatter.hLocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&) const&Draft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getTerabit()(missing)Draft
-ICU 64
numberformatter.hLocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&)&&Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getTerabyte()(missing)Draft
-ICU 64
numberformatter.hLocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(LocalizedNumberFormatter&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getTon()(missing)Draft
-ICU 64
numberformatter.hLocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(const LocalizedNumberFormatter&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getVolt()(missing)Draft
-ICU 64
numberformatter.hPrecision icu::number::CurrencyPrecision::withCurrency(const CurrencyUnit&) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getWatt()(missing)Draft
-ICU 64
numberformatter.hPrecision icu::number::FractionPrecision::withMaxDigits(int32_t) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getWeek()(missing)Draft
-ICU 64
numberformatter.hPrecision icu::number::FractionPrecision::withMinDigits(int32_t) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getWeekPerson()(missing)Draft
-ICU 64
numberformatter.hPrecision icu::number::IncrementPrecision::withMinFraction(int32_t) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getYard()(missing)Draft
-ICU 64
numberformatter.hScale& icu::number::Scale::operator=(Scale&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getYear()(missing)Draft
-ICU 64
numberformatter.hScale& icu::number::Scale::operator=(const Scale&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getYearPerson()(missing)Draft
-ICU 64
numberformatter.hScientificNotation icu::number::ScientificNotation::withExponentSignDisplay(UNumberSignDisplay) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createBarrel(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hScientificNotation icu::number::ScientificNotation::withMinExponentDigits(int32_t) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createBritishThermalUnit(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hUBool icu::number::NumberFormatterSettings< Derived >::copyErrorTo(UErrorCode&) constDraft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createDalton(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hUnicodeString icu::number::FormattedNumber::toString(UErrorCode&) constDraft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createDayPerson(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hUnicodeString icu::number::NumberFormatterSettings< Derived >::toSkeleton(UErrorCode&) constDraft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createDunam(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hUnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(UnlocalizedNumberFormatter&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createEarthMass(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hUnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(const UnlocalizedNumberFormatter&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createElectronvolt(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::FormattedNumber::FormattedNumber(FormattedNumber&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createFluidOunceImperial(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::FormattedNumber::~FormattedNumber()Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createKilopascal(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter()=defaultDraft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createMegapascal(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createMole(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(const LocalizedNumberFormatter&)Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createMonthPerson(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::LocalizedNumberFormatter::~LocalizedNumberFormatter()Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createNewton(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::Scale::Scale(Scale&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createNewtonMeter(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::Scale::Scale(const Scale&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPermyriad(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::Scale::~Scale()Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPoundFoot(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter()=defaultDraft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPoundForce(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&&)Draft→Stable
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createSolarLuminosity(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter&)Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createSolarMass(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hstatic CompactNotation icu::number::Notation::compactLong()Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createSolarRadius(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hstatic CompactNotation icu::number::Notation::compactShort()Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createWeekPerson(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hstatic CurrencyPrecision icu::number::Precision::currency(UCurrencyUsage)Draft→Stable
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createYearPerson(UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::fixedFraction(int32_t)Draft→Stable
ICU 60
numberformatter.hLocalPointer<Derived> icu::number::NumberFormatterSettings< Derived >::clone() &&(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::integer()Draft→Stable
ICU 60
numberformatter.hLocalPointer<Derived> icu::number::NumberFormatterSettings< Derived >::clone() const &(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::maxFraction(int32_t)Draft→Stable
ICU 60
numberformatter.hUBool icu::number::FormattedNumber::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::minFraction(int32_t)Draft→Stable
ICU 60
numberformatter.hUnicodeString icu::number::FormattedNumber::toTempString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::minMaxFraction(int32_t, int32_t)Draft→Stable
ICU 60
numberformatter.hicu::number::FormattedNumber::FormattedNumber()(missing)Draft
-ICU 64
numberformatter.hstatic IncrementPrecision icu::number::Precision::increment(double)Draft→Stable
ICU 60
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UParseError&, UErrorCode&)(missing)Draft
-ICU 64
numberformatter.hstatic IntegerWidth icu::number::IntegerWidth::zeroFillTo(int32_t)Draft→Stable
ICU 60
numberrangeformatter.hLocalPointer<Derived> icu::number::NumberRangeFormatterSettings< Derived >::clone() &&(missing)Draft
-ICU 64
numberformatter.hstatic LocalizedNumberFormatter icu::number::NumberFormatter::withLocale(const Locale&)Draft→Stable
ICU 60
numberrangeformatter.hLocalPointer<Derived> icu::number::NumberRangeFormatterSettings< Derived >::clone() const &(missing)Draft
-ICU 64
numberformatter.hstatic Precision icu::number::Precision::unlimited()Draft→Stable
ICU 60
numberrangeformatter.hUBool icu::number::FormattedNumberRange::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDecimal(StringPiece)Draft→Stable
ICU 62
numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::toTempString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDouble(double)Draft→Stable
ICU 62
numfmt.henum - icu::NumberFormat::EAlignmentFields::kCompactField(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDoubleAndPowerOfTen(double, int32_t)Draft→Stable
ICU 62
numfmt.henum - icu::NumberFormat::EAlignmentFields::kMeasureUnitField(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::none()Draft→Stable
ICU 62
plurrule.hUnicodeString icu::PluralRules::select(const number::FormattedNumber&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic Scale icu::number::Scale::powerOfTen(int32_t)Draft→Stable
ICU 62
reldatefmt.hAppendable& icu::FormattedRelativeDateTime::appendTo(Appendable&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic ScientificNotation icu::number::Notation::engineering()Draft→Stable
ICU 60
reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatNumericToValue(double, URelativeDateTimeUnit, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic ScientificNotation icu::number::Notation::scientific()Draft→Stable
ICU 60
reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(UDateDirection, UDateAbsoluteUnit, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::fixedSignificantDigits(int32_t)Draft→Stable
ICU 62
reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(double, UDateDirection, UDateRelativeUnit, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::maxSignificantDigits(int32_t)Draft→Stable
ICU 62
reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(double, URelativeDateTimeUnit, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minMaxSignificantDigits(int32_t, int32_t)Draft→Stable
ICU 62
reldatefmt.hFormattedRelativeDateTime& icu::FormattedRelativeDateTime::operator=(FormattedRelativeDateTime&&)(missing)Draft
-ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minSignificantDigits(int32_t)Draft→Stable
ICU 62
reldatefmt.hFormattedRelativeDateTime& icu::FormattedRelativeDateTime::operator=(const FormattedRelativeDateTime&)=delete(missing) -
- -
-(untagged)
numberformatter.hstatic SimpleNotation icu::number::Notation::simple()Draft→Stable
ICU 60
reldatefmt.hUBool icu::FormattedRelativeDateTime::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UErrorCode&)Draft→Stable
ICU 62
reldatefmt.hUnicodeString icu::FormattedRelativeDateTime::toString(UErrorCode&) const(missing)Draft
-ICU 64
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::with()Draft→Stable
ICU 60
reldatefmt.hUnicodeString icu::FormattedRelativeDateTime::toTempString(UErrorCode&) const(missing)Draft
-ICU 64
numberrangeformatter.hAppendable& icu::number::FormattedNumberRange::appendTo(Appendable&, UErrorCode&) constDraft→Stable
ICU 63
reldatefmt.hicu::FormattedRelativeDateTime::FormattedRelativeDateTime()(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse) const&Draft→Stable
ICU 63
reldatefmt.hicu::FormattedRelativeDateTime::FormattedRelativeDateTime(FormattedRelativeDateTime&&)(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse)&&Draft→Stable
ICU 63
reldatefmt.hicu::FormattedRelativeDateTime::FormattedRelativeDateTime(const FormattedRelativeDateTime&)=delete(missing) -
- -
-(untagged)
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback) const&Draft→Stable
ICU 63
reldatefmt.hicu::FormattedRelativeDateTime::~FormattedRelativeDateTime()(missing)Draft
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback)&&Draft→Stable
ICU 63
simpleformatter.hUnicodeString icu::SimpleFormatter::getTextWithNoArguments(int32_t*, int32_t) const(missing)Internal
-
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&) const&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&)&&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_ELYMAIC(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&) const&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_NANDINAGARI(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&)&&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_NYIAKENG_PUACHUE_HMONG(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&) const&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_OTTOMAN_SIYAQ_NUMBERS(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&)&&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_SMALL_KANA_EXTENSION(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&) const&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&)&&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_TAMIL_SUPPLEMENT(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&) const&Draft→Stable
ICU 63
uchar.henum UBlockCode::UBLOCK_WANCHO(missing)Stable
-ICU 64
(Born Stable)numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&)&&Draft→Stable
ICU 63
uconfig.h#define UCONFIG_USE_WINDOWS_LCID_MAPPING_API(missing)Internal
-ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&) const&Draft→Stable
ICU 63
udat.h#define JP_ERA_2019_JA(missing)Internal
-
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&)&&Draft→Stable
ICU 63
udat.h#define JP_ERA_2019_NARROW(missing)Internal
-
numberrangeformatter.hFormattedNumberRange icu::number::LocalizedNumberRangeFormatter::formatFormattableRange(const Formattable&, const Formattable&, UErrorCode&) constDraft→Stable
ICU 63
udat.h#define JP_ERA_2019_ROOT(missing)Internal
-
numberrangeformatter.hFormattedNumberRange& icu::number::FormattedNumberRange::operator=(FormattedNumberRange&&)Draft→Stable
ICU 63
udateintervalformat.hUFormattedDateInterval* udtitvfmt_openResult(UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&) const&Draft→Stable
ICU 63
udateintervalformat.hconst UFormattedValue* udtitvfmt_resultAsValue(const UFormattedDateInterval*, UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&)&&Draft→Stable
ICU 63
udateintervalformat.hvoid udtitvfmt_closeResult(UFormattedDateInterval*)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(LocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
udateintervalformat.hvoid udtitvfmt_formatToResult(const UDateIntervalFormat*, UFormattedDateInterval*, UDate, UDate, UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(const LocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
uformattedvalue.hUBool ucfpos_matchesField(const UConstrainedFieldPosition*, int32_t, int32_t, UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hUBool icu::number::NumberRangeFormatterSettings< Derived >::copyErrorTo(UErrorCode&) constDraft→Stable
ICU 63
uformattedvalue.hUBool ufmtval_nextPosition(const UFormattedValue*, UConstrainedFieldPosition*, UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hUNumberRangeIdentityResult icu::number::FormattedNumberRange::getIdentityResult(UErrorCode&) constDraft→Stable
ICU 63
uformattedvalue.hUConstrainedFieldPosition* ucfpos_open(UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::toString(UErrorCode&) constDraft→Stable
ICU 63
uformattedvalue.hconst UChar* ufmtval_getString(const UFormattedValue*, int32_t*, UErrorCode*)(missing)Draft
-ICU 64
numberrangeformatter.hUnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(UnlocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_COUNT(missing)Internal
-
numberrangeformatter.hUnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(const UnlocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_DATE_INTERVAL_SPAN(missing)Draft
-ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_ALLDraft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_DATE_INTERVAL(missing)Internal
-
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_AUTODraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_NONEDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_UNITDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUEDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELYDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_RANGEDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_SINGLE_VALUEDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDINGDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDINGDraft→Stable
ICU 63
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_NOT_EQUALDraft→Stable
ICU 63
numberrangeformatter.hicu::number::FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&&)Draft→Stable
ICU 63
numberrangeformatter.hicu::number::FormattedNumberRange::~FormattedNumberRange()Draft→Stable
ICU 63
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter()=defaultDraft→Stable
ICU 63
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter()Draft→Stable
ICU 63
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter()=defaultDraft→Stable
ICU 63
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&&)Draft→Stable
ICU 63
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter&)Draft→Stable
ICU 63
numberrangeformatter.hstatic LocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::withLocale(const Locale&)Draft→Stable
ICU 63
numberrangeformatter.hstatic UnlocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::with()Draft→Stable
ICU 63
numfmt.hvoid* icu::NumberFormat::clone() const(missing)Stable
+ICU 2.0
reldatefmt.henum UDateAbsoluteUnit::UDAT_ABSOLUTE_QUARTERDraft→Stable
ICU 63
uchar.hconst UCPMap* u_getIntPropertyMap(UProperty, UErrorCode*)Draft→Stable
ICU 63
uchar.hconst USet* u_getBinaryPropertySet(UProperty, UErrorCode*)Draft→Stable
ICU 63
ucpmap.hUChar32 ucpmap_getRange(const UCPMap*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft→Stable
ICU 63
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_FIXED_ALL_SURROGATESDraft→Stable
ICU 63
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_FIXED_LEAD_SURROGATESDraft→Stable
ICU 63
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_NORMALDraft→Stable
ICU 63
ucpmap.huint32_t ucpmap_get(const UCPMap*, UChar32)Draft→Stable
ICU 63
ucptrie.h#define UCPTRIE_16Draft→Stable
ICU 63
ucptrie.h#define UCPTRIE_32Draft→Stable
ICU 63
ucptrie.h#define UCPTRIE_8Draft→Stable
ICU 63
ucptrie.h#define UCPTRIE_ASCII_GETDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_BMP_GETDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_GETDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_SUPP_GETDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_U16_NEXTDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_U16_PREVDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_U8_NEXTDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_FAST_U8_PREVDraft→Stable
ICU 63
ucptrie.h#define UCPTRIE_SMALL_GETDraft→Stable
ICU 63
ucptrie.hUCPTrie* ucptrie_openFromBinary(UCPTrieType, UCPTrieValueWidth, const void*, int32_t, int32_t*, UErrorCode*)Draft→Stable
ICU 63
ucptrie.hUCPTrieType ucptrie_getType(const UCPTrie*)Draft→Stable
ICU 63
ucptrie.hUCPTrieValueWidth ucptrie_getValueWidth(const UCPTrie*)Draft→Stable
ICU 63
ucptrie.hUChar32 ucptrie_getRange(const UCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft→Stable
ICU 63
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_ANYDraft→Stable
ICU 63
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_FASTDraft→Stable
ICU 63
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_SMALLDraft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_DATE(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_16Draft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_LIST_SPAN(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_32Draft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_LIST(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_8Draft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_NUMBER(missing)Draft
-ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_ANYDraft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_RELATIVE_DATETIME(missing)Draft
-ICU 64
ucptrie.hint32_t ucptrie_toBinary(const UCPTrie*, void*, int32_t, UErrorCode*)Draft→Stable
ICU 63
uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_UNDEFINED(missing)Draft
-ICU 64
ucptrie.huint32_t ucptrie_get(const UCPTrie*, UChar32)Draft→Stable
ICU 63
uformattedvalue.hint32_t ucfpos_getCategory(const UConstrainedFieldPosition*, UErrorCode*)(missing)Draft
-ICU 64
ucptrie.hvoid ucptrie_close(UCPTrie*)Draft→Stable
ICU 63
uformattedvalue.hint32_t ucfpos_getField(const UConstrainedFieldPosition*, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hUCPTrie* umutablecptrie_buildImmutable(UMutableCPTrie*, UCPTrieType, UCPTrieValueWidth, UErrorCode*)Draft→Stable
ICU 63
uformattedvalue.hint64_t ucfpos_getInt64IterationContext(const UConstrainedFieldPosition*, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_clone(const UMutableCPTrie*, UErrorCode*)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_close(UConstrainedFieldPosition*)(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_fromUCPMap(const UCPMap*, UErrorCode*)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_constrainCategory(UConstrainedFieldPosition*, int32_t, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_fromUCPTrie(const UCPTrie*, UErrorCode*)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_constrainField(UConstrainedFieldPosition*, int32_t, int32_t, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_open(uint32_t, uint32_t, UErrorCode*)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_getIndexes(const UConstrainedFieldPosition*, int32_t*, int32_t*, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hUChar32 umutablecptrie_getRange(const UMutableCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_reset(UConstrainedFieldPosition*, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.huint32_t umutablecptrie_get(const UMutableCPTrie*, UChar32)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_setInt64IterationContext(UConstrainedFieldPosition*, int64_t, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hvoid umutablecptrie_close(UMutableCPTrie*)Draft→Stable
ICU 63
uformattedvalue.hvoid ucfpos_setState(UConstrainedFieldPosition*, int32_t, int32_t, int32_t, int32_t, UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hvoid umutablecptrie_set(UMutableCPTrie*, UChar32, uint32_t, UErrorCode*)Draft→Stable
ICU 63
ulistformatter.hUFormattedList* ulistfmt_openResult(UErrorCode*)(missing)Draft
-ICU 64
umutablecptrie.hvoid umutablecptrie_setRange(UMutableCPTrie*, UChar32, UChar32, uint32_t, UErrorCode*)Draft→Stable
ICU 63
ulistformatter.hconst UFormattedValue* ulistfmt_resultAsValue(const UFormattedList*, UErrorCode*)(missing)Draft
-ICU 64
unifilt.hvoid* icu::UnicodeFilter::clone() const(missing)Stable
+ICU 2.4
ulistformatter.hvoid ulistfmt_closeResult(UFormattedList*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_ALWAYSDraft→Stable
ICU 60
ulistformatter.hvoid ulistfmt_formatStringsToResult(const UListFormatter*, const UChar* const strings[], const int32_t*, int32_t, UFormattedList*, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_AUTODraft→Stable
ICU 60
unum.henum UNumberFormatFields::UNUM_COMPACT_FIELD(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_AUTODraft→Stable
ICU 61
unum.henum UNumberFormatFields::UNUM_MEASURE_UNIT_FIELD(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_MIN2Draft→Stable
ICU 61
unumberformatter.hUNumberFormatter* unumf_openForSkeletonAndLocaleWithError(const UChar*, int32_t, const char*, UParseError*, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_OFFDraft→Stable
ICU 61
unumberformatter.hconst UFormattedValue* unumf_resultAsValue(const UFormattedNumber*, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_ON_ALIGNEDDraft→Stable
ICU 61
upluralrules.hint32_t uplrules_selectFormatted(const UPluralRules*, const struct UFormattedNumber*, UChar*, int32_t, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_THOUSANDSDraft→Stable
ICU 61
ureldatefmt.hUFormattedRelativeDateTime* ureldatefmt_openResult(UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYSDraft→Stable
ICU 60
ureldatefmt.hconst UFormattedValue* ureldatefmt_resultAsValue(const UFormattedRelativeDateTime*, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERODraft→Stable
ICU 61
ureldatefmt.henum URelativeDateTimeFormatterField::UDAT_REL_LITERAL_FIELD(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTINGDraft→Stable
ICU 60
ureldatefmt.henum URelativeDateTimeFormatterField::UDAT_REL_NUMERIC_FIELD(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ALWAYSDraft→Stable
ICU 60
ureldatefmt.hvoid ureldatefmt_closeResult(UFormattedRelativeDateTime*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_AUTODraft→Stable
ICU 60
ureldatefmt.hvoid ureldatefmt_formatNumericToResult(const URelativeDateTimeFormatter*, double, URelativeDateTimeUnit, UFormattedRelativeDateTime*, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERODraft→Stable
ICU 61
ureldatefmt.hvoid ureldatefmt_formatToResult(const URelativeDateTimeFormatter*, double, URelativeDateTimeUnit, UFormattedRelativeDateTime*, UErrorCode*)(missing)Draft
-ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_NEVERDraft→Stable
ICU 60
uscript.henum UScriptCode::USCRIPT_ELYMAIC(missing)Stable
-ICU 64
(Born Stable)unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAMEDraft→Stable
ICU 60
uscript.henum UScriptCode::USCRIPT_NANDINAGARI(missing)Stable
-ICU 64
(Born Stable)unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDENDraft→Stable
ICU 60
uscript.henum UScriptCode::USCRIPT_NYIAKENG_PUACHUE_HMONG(missing)Stable
-ICU 64
(Born Stable)unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODEDraft→Stable
ICU 60
uscript.henum UScriptCode::USCRIPT_WANCHO(missing)Stable
-ICU 64
(Born Stable)unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROWDraft→Stable
ICU 60
utypes.henum UErrorCode::U_NUMBER_ARG_OUTOFBOUNDS_ERROR(missing)Stable
-ICU 61
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORTDraft→Stable
ICU 60
utypes.henum UErrorCode::U_NUMBER_SKELETON_SYNTAX_ERROR(missing)Stable
-ICU 62
uspoof.henum USpoofChecks::USPOOF_HIDDEN_OVERLAYDraft→Stable
ICU 62

(jump back to top)
- -

Other existing drafts in ICU 64

-
+ +

Added in ICU 65

- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + +
FileAPIICU 63ICU 64FileAPIICU 64ICU 65
decimfmt.hint32_t icu::DecimalFormat::getMultiplierScale() constDraft
ICU 62
basictz.hvoid* icu::BasicTimeZone::clone() const(missing)Stable
+ICU 3.8
decimfmt.hvoid icu::DecimalFormat::setMultiplierScale(int32_t)Draft
ICU 62
bytestrie.hBytesTrie& icu::BytesTrie::resetToState64(uint64_t)(missing)Draft
+ICU 65
listformatter.hUnicodeString& icu::ListFormatter::format(const UnicodeString items[], int32_t, UnicodeString&, FieldPositionIterator*, UErrorCode&) constDraft
ICU 63
bytestrie.huint64_t icu::BytesTrie::getState64() const(missing)Draft
+ICU 65
locid.hLocale& icu::Locale::operator=(Locale&&)Draft
ICU 63
datefmt.hvoid* icu::DateFormat::clone() const(missing)Stable
+ICU 2.0
locid.hStringClass icu::Locale::getKeywordValue(StringPiece, UErrorCode&) constDraft
ICU 63
edits.hUBool icu::Edits::copyErrorTo(UErrorCode&) const(missing)Stable
+ICU 59
locid.hStringClass icu::Locale::getUnicodeKeywordValue(StringPiece, UErrorCode&) constDraft
ICU 63
localebuilder.hUBool icu::LocaleBuilder::copyErrorTo(UErrorCode&) const(missing)Draft
+ICU 65
locid.hStringClass icu::Locale::toLanguageTag(UErrorCode&) constDraft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&)(missing)Draft
+ICU 65
locid.hStringEnumeration* icu::Locale::createUnicodeKeywords(UErrorCode&) constDraft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::operator=(Builder&&)(missing)Draft
+ICU 65
locid.hicu::Locale::Locale(Locale&&)Draft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setDefaultLocale(const Locale*)(missing)Draft
+ICU 65
locid.hstatic Locale icu::Locale::forLanguageTag(StringPiece, UErrorCode&)Draft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::addLikelySubtags(UErrorCode&)Draft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::getKeywordValue(StringPiece, ByteSink&, UErrorCode&) constDraft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setSupportedLocales(Iter, Iter)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::getKeywords(OutputIterator, UErrorCode&) constDraft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator&)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::getUnicodeKeywordValue(StringPiece, ByteSink&, UErrorCode&) constDraft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setSupportedLocalesFromListString(StringPiece)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::getUnicodeKeywords(OutputIterator, UErrorCode&) constDraft
ICU 63
localematcher.hBuilder& icu::LocaleMatcher::Builder::setSupportedLocalesViaConverter(Iter, Iter, Conv)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::minimizeSubtags(UErrorCode&)Draft
ICU 63
localematcher.hLocale icu::LocaleMatcher::Result::makeResolvedLocale(UErrorCode&) const(missing)Draft
+ICU 65
locid.hvoid icu::Locale::setKeywordValue(StringPiece, StringPiece, UErrorCode&)Draft
ICU 63
localematcher.hLocaleMatcher icu::LocaleMatcher::Builder::build(UErrorCode&) const(missing)Draft
+ICU 65
locid.hvoid icu::Locale::setUnicodeKeywordValue(StringPiece, StringPiece, UErrorCode&)Draft
ICU 63
localematcher.hLocaleMatcher& icu::LocaleMatcher::operator=(LocaleMatcher&&)(missing)Draft
+ICU 65
locid.hvoid icu::Locale::toLanguageTag(ByteSink&, UErrorCode&) constDraft
ICU 63
localematcher.hResult icu::LocaleMatcher::getBestMatchResult(Locale::Iterator&, UErrorCode&) const(missing)Draft
+ICU 65
measfmt.hvoid icu::MeasureFormat::parseObject(const UnicodeString&, Formattable&, ParsePosition&) constDraft
ICU 53
localematcher.hResult icu::LocaleMatcher::getBestMatchResult(const Locale&, UErrorCode&) const(missing)Draft
+ICU 65
measunit.hstatic MeasureUnit* icu::MeasureUnit::createAtmosphere(UErrorCode&)Draft
ICU 63
localematcher.hResult& icu::LocaleMatcher::Result::operator=(Result&&)(missing)Draft
+ICU 65
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPercent(UErrorCode&)Draft
ICU 63
localematcher.hUBool icu::LocaleMatcher::Builder::copyErrorTo(UErrorCode&) const(missing)Draft
+ICU 65
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPermille(UErrorCode&)Draft
ICU 63
localematcher.hconst Locale* icu::LocaleMatcher::Result::getDesiredLocale() const(missing)Draft
+ICU 65
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPetabyte(UErrorCode&)Draft
ICU 63
localematcher.hconst Locale* icu::LocaleMatcher::Result::getSupportedLocale() const(missing)Draft
+ICU 65
nounit.hUClassID icu::NoUnit::getDynamicClassID() constDraft
ICU 60
localematcher.hconst Locale* icu::LocaleMatcher::getBestMatch(Locale::Iterator&, UErrorCode&) const(missing)Draft
+ICU 65
nounit.hUObject* icu::NoUnit::clone() constDraft
ICU 60
localematcher.hconst Locale* icu::LocaleMatcher::getBestMatch(const Locale&, UErrorCode&) const(missing)Draft
+ICU 65
nounit.hicu::NoUnit::NoUnit(const NoUnit&)Draft
ICU 60
localematcher.hconst Locale* icu::LocaleMatcher::getBestMatchForListString(StringPiece, UErrorCode&) const(missing)Draft
+ICU 65
nounit.hicu::NoUnit::~NoUnit()Draft
ICU 60
localematcher.hdouble icu::LocaleMatcher::internalMatch(const Locale&, const Locale&, UErrorCode&) const(missing)Internal
+
nounit.hstatic NoUnit icu::NoUnit::base()Draft
ICU 60
localematcher.henum ULocMatchDemotion::ULOCMATCH_DEMOTION_NONE(missing)Draft
+ICU 65
nounit.hstatic NoUnit icu::NoUnit::percent()Draft
ICU 60
localematcher.henum ULocMatchDemotion::ULOCMATCH_DEMOTION_REGION(missing)Draft
+ICU 65
nounit.hstatic NoUnit icu::NoUnit::permille()Draft
ICU 60
localematcher.henum ULocMatchFavorSubtag::ULOCMATCH_FAVOR_LANGUAGE(missing)Draft
+ICU 65
nounit.hstatic UClassID icu::NoUnit::getStaticClassID()Draft
ICU 60
localematcher.henum ULocMatchFavorSubtag::ULOCMATCH_FAVOR_SCRIPT(missing)Draft
+ICU 65
localematcher.hicu::LocaleMatcher::Builder::Builder()(missing)Draft
+ICU 65
localematcher.hicu::LocaleMatcher::Builder::Builder(Builder&&)(missing)Draft
+ICU 65
localematcher.hicu::LocaleMatcher::Builder::~Builder()(missing)Draft
+ICU 65
localematcher.hicu::LocaleMatcher::LocaleMatcher(LocaleMatcher&&)(missing)Draft
+ICU 65
localematcher.hicu::LocaleMatcher::Result::Result(Result&&)(missing)Draft
+ICU 65
localematcher.hicu::LocaleMatcher::Result::~Result()(missing)Draft
+ICU 65
numberformatter.hAppendable& icu::number::FormattedNumber::appendTo(Appendable&, UErrorCode&) constDraft
ICU 62
localematcher.hicu::LocaleMatcher::~LocaleMatcher()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*) const&Draft
ICU 61
localematcher.hint32_t icu::LocaleMatcher::Result::getDesiredIndex() const(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*)&&Draft
ICU 62
localematcher.hint32_t icu::LocaleMatcher::Result::getSupportedIndex() const(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*) const&Draft
ICU 60
locid.hUBool icu::Locale::ConvertingIterator< Iter, Conv >::hasNext() const override(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*)&&Draft
ICU 62
locid.hUBool icu::Locale::Iterator::hasNext() const(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*) const&Draft
ICU 60
locid.hUBool icu::Locale::RangeIterator< Iter >::hasNext() const override(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*)&&Draft
ICU 62
locid.hconst Locale& icu::Locale::ConvertingIterator< Iter, Conv >::next() override(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay) const&Draft
ICU 60
locid.hconst Locale& icu::Locale::Iterator::next()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay)&&Draft
ICU 62
locid.hconst Locale& icu::Locale::RangeIterator< Iter >::next() override(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy) const&Draft
ICU 61
locid.hicu::Locale::ConvertingIterator< Iter, Conv >::ConvertingIterator(Iter, Iter, Conv)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy)&&Draft
ICU 62
locid.hicu::Locale::Iterator::~Iterator()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&) const&Draft
ICU 60
locid.hicu::Locale::RangeIterator< Iter >::RangeIterator(Iter, Iter)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&)&&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getBar()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&) const&Draft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getDecade()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&)&&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getDotPerCentimeter()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&) const&Draft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getDotPerInch()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&)&&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getEm()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&) const&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getMegapixel()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&)&&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPascal()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode) const&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPixel()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode)&&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPixelPerCentimeter()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&) const&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getPixelPerInch()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&)&&Draft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getThermUs()(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay) const&Draft
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createBar(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay)&&Draft
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createDecade(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&) const&Draft
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createDotPerCentimeter(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&)&&Draft
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createDotPerInch(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&) const&Draft
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createEm(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&)&&Draft
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createMegapixel(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth) const&Draft
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPascal(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hDerived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth)&&Draft
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPixel(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hFormat* icu::number::LocalizedNumberFormatter::toFormat(UErrorCode&) constDraft
ICU 62
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPixelPerCentimeter(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatDecimal(StringPiece, UErrorCode&) constDraft
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createPixelPerInch(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatDouble(double, UErrorCode&) constDraft
ICU 60
measunit.hstatic MeasureUnit* icu::MeasureUnit::createThermUs(UErrorCode&)(missing)Draft
+ICU 65
numberformatter.hFormattedNumber icu::number::LocalizedNumberFormatter::formatInt(int64_t, UErrorCode&) constDraft
ICU 60
numberformatter.hStringClass icu::number::FormattedNumber::toDecimalNumber(UErrorCode&) const(missing)Draft
+ICU 65
numberformatter.hFormattedNumber& icu::number::FormattedNumber::operator=(FormattedNumber&&)Draft
ICU 62
numfmt.hvoid* icu::NumberFormat::clone() const(missing)Stable
+ICU 2.0
numberformatter.hIntegerWidth icu::number::IntegerWidth::truncateAt(int32_t)Draft
ICU 60
platform.h#define UPRV_HAS_ATTRIBUTE(missing)Internal
+
numberformatter.hLocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&) const&Draft
ICU 60
platform.h#define UPRV_HAS_BUILTIN(missing)Internal
+
numberformatter.hLocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&)&&Draft
ICU 62
platform.h#define UPRV_HAS_CPP_ATTRIBUTE(missing)Internal
+
numberformatter.hLocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(LocalizedNumberFormatter&&)Draft
ICU 62
platform.h#define UPRV_HAS_DECLSPEC_ATTRIBUTE(missing)Internal
+
numberformatter.hLocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(const LocalizedNumberFormatter&)Draft
ICU 62
platform.h#define UPRV_HAS_EXTENSION(missing)Internal
+
numberformatter.hPrecision icu::number::CurrencyPrecision::withCurrency(const CurrencyUnit&) constDraft
ICU 60
platform.h#define UPRV_HAS_FEATURE(missing)Internal
+
numberformatter.hPrecision icu::number::FractionPrecision::withMaxDigits(int32_t) constDraft
ICU 60
platform.h#define UPRV_HAS_WARNING(missing)Internal
+
numberformatter.hPrecision icu::number::FractionPrecision::withMinDigits(int32_t) constDraft
ICU 60
platform.h#define U_PF_EMSCRIPTEN(missing)Internal
+
numberformatter.hPrecision icu::number::IncrementPrecision::withMinFraction(int32_t) constDraft
ICU 60
reldatefmt.henum UDateAbsoluteUnit::UDAT_ABSOLUTE_HOUR(missing)Draft
+ICU 65
numberformatter.hScale& icu::number::Scale::operator=(Scale&&)Draft
ICU 62
reldatefmt.henum UDateAbsoluteUnit::UDAT_ABSOLUTE_MINUTE(missing)Draft
+ICU 65
numberformatter.hScale& icu::number::Scale::operator=(const Scale&)Draft
ICU 62
stringpiece.hicu::StringPiece::StringPiece(T)(missing)Draft
+ICU 65
numberformatter.hScientificNotation icu::number::ScientificNotation::withExponentSignDisplay(UNumberSignDisplay) constDraft
ICU 60
ucal.hint32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*)(missing)Draft
+ICU 65
numberformatter.hScientificNotation icu::number::ScientificNotation::withMinExponentDigits(int32_t) constDraft
ICU 60
ucharstrie.hUCharsTrie& icu::UCharsTrie::resetToState64(uint64_t)(missing)Draft
+ICU 65
numberformatter.hUBool icu::number::FormattedNumber::nextFieldPosition(FieldPosition&, UErrorCode&) constDraft
ICU 62
ucharstrie.huint64_t icu::UCharsTrie::getState64() const(missing)Draft
+ICU 65
numberformatter.hUBool icu::number::NumberFormatterSettings< Derived >::copyErrorTo(UErrorCode&) constDraft
ICU 60
uloc.hUEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*)(missing)Draft
+ICU 65
numberformatter.hUnicodeString icu::number::FormattedNumber::toString(UErrorCode&) constDraft
ICU 62
uloc.henum ULocAvailableType::ULOC_AVAILABLE_COUNT(missing)Internal
+
numberformatter.hUnicodeString icu::number::NumberFormatterSettings< Derived >::toSkeleton(UErrorCode&) constDraft
ICU 62
uloc.henum ULocAvailableType::ULOC_AVAILABLE_DEFAULT(missing)Draft
+ICU 65
numberformatter.hUnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(UnlocalizedNumberFormatter&&)Draft
ICU 62
uloc.henum ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES(missing)Draft
+ICU 65
numberformatter.hUnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(const UnlocalizedNumberFormatter&)Draft
ICU 62
uloc.henum ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES(missing)Draft
+ICU 65
numberformatter.hicu::number::FormattedNumber::FormattedNumber(FormattedNumber&&)Draft
ICU 62
umachine.h#define UPRV_BLOCK_MACRO_BEGIN(missing)Internal
+
numberformatter.hicu::number::FormattedNumber::~FormattedNumber()Draft
ICU 60
umachine.h#define UPRV_BLOCK_MACRO_END(missing)Internal
+
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter()=defaultDraft
ICU 62
unifilt.hvoid* icu::UnicodeFilter::clone() const(missing)Stable
+ICU 2.4
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&&)Draft
ICU 62
utrace.henum UTraceFunctionNumber::UTRACE_RES_DATA_LIMIT(missing)Internal
+
numberformatter.hicu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(const LocalizedNumberFormatter&)Draft
ICU 60
utrace.henum UTraceFunctionNumber::UTRACE_UDATA_BUNDLE(missing)Draft
+ICU 65
numberformatter.hicu::number::LocalizedNumberFormatter::~LocalizedNumberFormatter()Draft
ICU 60
utrace.henum UTraceFunctionNumber::UTRACE_UDATA_DATA_FILE(missing)Draft
+ICU 65
numberformatter.hicu::number::Scale::Scale(Scale&&)Draft
ICU 62
utrace.henum UTraceFunctionNumber::UTRACE_UDATA_RESOURCE(missing)Draft
+ICU 65
numberformatter.hicu::number::Scale::Scale(const Scale&)Draft
ICU 62
utrace.henum UTraceFunctionNumber::UTRACE_UDATA_RES_FILE(missing)Draft
+ICU 65
numberformatter.hicu::number::Scale::~Scale()Draft
ICU 62
utrace.henum UTraceFunctionNumber::UTRACE_UDATA_START(missing)Draft
+ICU 65
+

+(jump back to top) +
+ +

Other existing drafts in ICU 65

+
+ + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
FileAPIICU 64ICU 65
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter()=defaultDraft
ICU 62
currunit.hicu::CurrencyUnit::CurrencyUnit(StringPiece, UErrorCode&)Draft
ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&&)Draft
ICU 62
decimfmt.hUBool icu::DecimalFormat::isFormatFailIfMoreThanMaxDigits() constDraft
ICU 64
numberformatter.hicu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter&)Draft
ICU 60
decimfmt.hUBool icu::DecimalFormat::isParseCaseSensitive() constDraft
ICU 64
numberformatter.hstatic CompactNotation icu::number::Notation::compactLong()Draft
ICU 60
decimfmt.hUBool icu::DecimalFormat::isParseNoExponent() constDraft
ICU 64
numberformatter.hstatic CompactNotation icu::number::Notation::compactShort()Draft
ICU 60
decimfmt.hUBool icu::DecimalFormat::isSignAlwaysShown() constDraft
ICU 64
numberformatter.hstatic CurrencyPrecision icu::number::Precision::currency(UCurrencyUsage)Draft
ICU 60
decimfmt.hconst number::LocalizedNumberFormatter* icu::DecimalFormat::toNumberFormatter(UErrorCode&) constDraft
ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::fixedFraction(int32_t)Draft
ICU 60
decimfmt.hint32_t icu::DecimalFormat::getMinimumGroupingDigits() constDraft
ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::integer()Draft
ICU 60
decimfmt.hvoid icu::DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool)Draft
ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::maxFraction(int32_t)Draft
ICU 60
decimfmt.hvoid icu::DecimalFormat::setMinimumGroupingDigits(int32_t)Draft
ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::minFraction(int32_t)Draft
ICU 60
decimfmt.hvoid icu::DecimalFormat::setParseCaseSensitive(UBool)Draft
ICU 64
numberformatter.hstatic FractionPrecision icu::number::Precision::minMaxFraction(int32_t, int32_t)Draft
ICU 60
decimfmt.hvoid icu::DecimalFormat::setParseNoExponent(UBool)Draft
ICU 64
numberformatter.hstatic IncrementPrecision icu::number::Precision::increment(double)Draft
ICU 60
decimfmt.hvoid icu::DecimalFormat::setSignAlwaysShown(UBool)Draft
ICU 64
numberformatter.hstatic IntegerWidth icu::number::IntegerWidth::zeroFillTo(int32_t)Draft
ICU 60
dtitvfmt.hAppendable& icu::FormattedDateInterval::appendTo(Appendable&, UErrorCode&) constDraft
ICU 64
numberformatter.hstatic LocalizedNumberFormatter icu::number::NumberFormatter::withLocale(const Locale&)Draft
ICU 60
dtitvfmt.hFormattedDateInterval icu::DateIntervalFormat::formatToValue(Calendar&, Calendar&, UErrorCode&) constDraft
ICU 64
numberformatter.hstatic Precision icu::number::Precision::unlimited()Draft
ICU 60
dtitvfmt.hFormattedDateInterval icu::DateIntervalFormat::formatToValue(const DateInterval&, UErrorCode&) constDraft
ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDecimal(StringPiece)Draft
ICU 62
dtitvfmt.hFormattedDateInterval& icu::FormattedDateInterval::operator=(FormattedDateInterval&&)Draft
ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDouble(double)Draft
ICU 62
dtitvfmt.hUBool icu::FormattedDateInterval::nextPosition(ConstrainedFieldPosition&, UErrorCode&) constDraft
ICU 64
numberformatter.hstatic Scale icu::number::Scale::byDoubleAndPowerOfTen(double, int32_t)Draft
ICU 62
dtitvfmt.hUnicodeString icu::FormattedDateInterval::toString(UErrorCode&) constDraft
ICU 64
numberformatter.hstatic Scale icu::number::Scale::none()Draft
ICU 62
dtitvfmt.hUnicodeString icu::FormattedDateInterval::toTempString(UErrorCode&) constDraft
ICU 64
numberformatter.hstatic Scale icu::number::Scale::powerOfTen(int32_t)Draft
ICU 62
dtitvfmt.hicu::FormattedDateInterval::FormattedDateInterval()Draft
ICU 64
numberformatter.hstatic ScientificNotation icu::number::Notation::engineering()Draft
ICU 60
dtitvfmt.hicu::FormattedDateInterval::FormattedDateInterval(FormattedDateInterval&&)Draft
ICU 64
numberformatter.hstatic ScientificNotation icu::number::Notation::scientific()Draft
ICU 60
dtitvfmt.hicu::FormattedDateInterval::~FormattedDateInterval()Draft
ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::fixedSignificantDigits(int32_t)Draft
ICU 62
formattedvalue.hAppendable& icu::FormattedValue::appendTo(Appendable&, UErrorCode&) constDraft
ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::maxSignificantDigits(int32_t)Draft
ICU 62
formattedvalue.hUBool icu::ConstrainedFieldPosition::matchesField(int32_t, int32_t) constDraft
ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minMaxSignificantDigits(int32_t, int32_t)Draft
ICU 62
formattedvalue.hUBool icu::FormattedValue::nextPosition(ConstrainedFieldPosition&, UErrorCode&) constDraft
ICU 64
numberformatter.hstatic SignificantDigitsPrecision icu::number::Precision::minSignificantDigits(int32_t)Draft
ICU 62
formattedvalue.hUnicodeString icu::FormattedValue::toString(UErrorCode&) constDraft
ICU 64
numberformatter.hstatic SimpleNotation icu::number::Notation::simple()Draft
ICU 60
formattedvalue.hUnicodeString icu::FormattedValue::toTempString(UErrorCode&) constDraft
ICU 64
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UErrorCode&)Draft
ICU 62
formattedvalue.hicu::ConstrainedFieldPosition::ConstrainedFieldPosition()Draft
ICU 64
numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::with()Draft
ICU 60
formattedvalue.hicu::ConstrainedFieldPosition::~ConstrainedFieldPosition()Draft
ICU 64
numberformatter.hvoid icu::number::FormattedNumber::getAllFieldPositions(FieldPositionIterator&, UErrorCode&) constDraft
ICU 62
formattedvalue.hicu::FormattedValue::~FormattedValue()Draft
ICU 64
numberrangeformatter.hAppendable& icu::number::FormattedNumberRange::appendTo(Appendable&, UErrorCode&) constDraft
ICU 63
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getCategory() constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse) const&Draft
ICU 63
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getField() constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse)&&Draft
ICU 63
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getLimit() constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback) const&Draft
ICU 63
formattedvalue.hint32_t icu::ConstrainedFieldPosition::getStart() constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback)&&Draft
ICU 63
formattedvalue.hint64_t icu::ConstrainedFieldPosition::getInt64IterationContext() constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&) const&Draft
ICU 63
formattedvalue.hvoid icu::ConstrainedFieldPosition::constrainCategory(int32_t)Draft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&)&&Draft
ICU 63
formattedvalue.hvoid icu::ConstrainedFieldPosition::constrainField(int32_t, int32_t)Draft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&) const&Draft
ICU 63
formattedvalue.hvoid icu::ConstrainedFieldPosition::reset()Draft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&)&&Draft
ICU 63
formattedvalue.hvoid icu::ConstrainedFieldPosition::setInt64IterationContext(int64_t)Draft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&) const&Draft
ICU 63
formattedvalue.hvoid icu::ConstrainedFieldPosition::setState(int32_t, int32_t, int32_t, int32_t)Draft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&)&&Draft
ICU 63
listformatter.hAppendable& icu::FormattedList::appendTo(Appendable&, UErrorCode&) constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&) const&Draft
ICU 63
listformatter.hFormattedList icu::ListFormatter::formatStringsToValue(const UnicodeString items[], int32_t, UErrorCode&) constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&)&&Draft
ICU 63
listformatter.hFormattedList& icu::FormattedList::operator=(FormattedList&&)Draft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&) const&Draft
ICU 63
listformatter.hUBool icu::FormattedList::nextPosition(ConstrainedFieldPosition&, UErrorCode&) constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&)&&Draft
ICU 63
listformatter.hUnicodeString icu::FormattedList::toString(UErrorCode&) constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&) const&Draft
ICU 63
listformatter.hUnicodeString icu::FormattedList::toTempString(UErrorCode&) constDraft
ICU 64
numberrangeformatter.hDerived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&)&&Draft
ICU 63
listformatter.hUnicodeString& icu::ListFormatter::format(const UnicodeString items[], int32_t, UnicodeString&, FieldPositionIterator*, UErrorCode&) constDraft
ICU 63
numberrangeformatter.hFormattedNumberRange icu::number::LocalizedNumberRangeFormatter::formatFormattableRange(const Formattable&, const Formattable&, UErrorCode&) constDraft
ICU 63
listformatter.hicu::FormattedList::FormattedList()Draft
ICU 64
numberrangeformatter.hFormattedNumberRange& icu::number::FormattedNumberRange::operator=(FormattedNumberRange&&)Draft
ICU 63
listformatter.hicu::FormattedList::FormattedList(FormattedList&&)Draft
ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&) const&Draft
ICU 63
listformatter.hicu::FormattedList::~FormattedList()Draft
ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&)&&Draft
ICU 63
localebuilder.hLocale icu::LocaleBuilder::build(UErrorCode&)Draft
ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(LocalizedNumberRangeFormatter&&)Draft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::addUnicodeLocaleAttribute(StringPiece)Draft
ICU 64
numberrangeformatter.hLocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(const LocalizedNumberRangeFormatter&)Draft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::clear()Draft
ICU 64
numberrangeformatter.hUBool icu::number::FormattedNumberRange::nextFieldPosition(FieldPosition&, UErrorCode&) constDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::clearExtensions()Draft
ICU 64
numberrangeformatter.hUBool icu::number::NumberRangeFormatterSettings< Derived >::copyErrorTo(UErrorCode&) constDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::removeUnicodeLocaleAttribute(StringPiece)Draft
ICU 64
numberrangeformatter.hUNumberRangeIdentityResult icu::number::FormattedNumberRange::getIdentityResult(UErrorCode&) constDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setExtension(char, StringPiece)Draft
ICU 64
numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::getFirstDecimal(UErrorCode&) constDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setLanguage(StringPiece)Draft
ICU 64
numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::getSecondDecimal(UErrorCode&) constDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setLanguageTag(StringPiece)Draft
ICU 64
numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::toString(UErrorCode&) constDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setLocale(const Locale&)Draft
ICU 64
numberrangeformatter.hUnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(UnlocalizedNumberRangeFormatter&&)Draft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setRegion(StringPiece)Draft
ICU 64
numberrangeformatter.hUnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(const UnlocalizedNumberRangeFormatter&)Draft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setScript(StringPiece)Draft
ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_ALLDraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setUnicodeLocaleKeyword(StringPiece, StringPiece)Draft
ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_AUTODraft
ICU 63
localebuilder.hLocaleBuilder& icu::LocaleBuilder::setVariant(StringPiece)Draft
ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_NONEDraft
ICU 63
localebuilder.hicu::LocaleBuilder::LocaleBuilder()Draft
ICU 64
numberrangeformatter.henum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_UNITDraft
ICU 63
localebuilder.hicu::LocaleBuilder::~LocaleBuilder()Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUEDraft
ICU 63
localpointer.hLocalArray<T>& icu::LocalArray< T >::operator=(std::unique_ptr< T[]>&&)Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELYDraft
ICU 63
localpointer.hLocalPointer<T>& icu::LocalPointer< T >::operator=(std::unique_ptr< T >&&)Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_RANGEDraft
ICU 63
localpointer.hicu::LocalArray< T >::LocalArray(std::unique_ptr< T[]>&&)Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_SINGLE_VALUEDraft
ICU 63
localpointer.hicu::LocalArray< T >::operator std::unique_ptr< T[]>() &&Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDINGDraft
ICU 63
localpointer.hicu::LocalPointer< T >::LocalPointer(std::unique_ptr< T >&&)Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDINGDraft
ICU 63
localpointer.hicu::LocalPointer< T >::operator std::unique_ptr< T >() &&Draft
ICU 64
numberrangeformatter.henum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_NOT_EQUALDraft
ICU 63
measfmt.hvoid icu::MeasureFormat::parseObject(const UnicodeString&, Formattable&, ParsePosition&) constDraft
ICU 53
numberrangeformatter.hicu::number::FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&&)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAcre()Draft
ICU 64
numberrangeformatter.hicu::number::FormattedNumberRange::~FormattedNumberRange()Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAcreFoot()Draft
ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter()=defaultDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAmpere()Draft
ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&&)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getArcMinute()Draft
ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter&)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getArcSecond()Draft
ICU 64
numberrangeformatter.hicu::number::LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter()Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAstronomicalUnit()Draft
ICU 64
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter()=defaultDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getAtmosphere()Draft
ICU 64
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&&)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBarrel()Draft
ICU 64
numberrangeformatter.hicu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter&)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBit()Draft
ICU 64
numberrangeformatter.hstatic LocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::withLocale(const Locale&)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBritishThermalUnit()Draft
ICU 64
numberrangeformatter.hstatic UnlocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::with()Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getBushel()Draft
ICU 64
numberrangeformatter.hvoid icu::number::FormattedNumberRange::getAllFieldPositions(FieldPositionIterator&, UErrorCode&) constDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getByte()Draft
ICU 64
reldatefmt.henum UDateAbsoluteUnit::UDAT_ABSOLUTE_QUARTERDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCalorie()Draft
ICU 64
uchar.hconst UCPMap* u_getIntPropertyMap(UProperty, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCarat()Draft
ICU 64
uchar.hconst USet* u_getBinaryPropertySet(UProperty, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCelsius()Draft
ICU 64
ucpmap.hUChar32 ucpmap_getRange(const UCPMap*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCentiliter()Draft
ICU 64
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_FIXED_ALL_SURROGATESDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCentimeter()Draft
ICU 64
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_FIXED_LEAD_SURROGATESDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCentury()Draft
ICU 64
ucpmap.henum UCPMapRangeOption::UCPMAP_RANGE_NORMALDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicCentimeter()Draft
ICU 64
ucpmap.huint32_t ucpmap_get(const UCPMap*, UChar32)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicFoot()Draft
ICU 64
ucptrie.h#define UCPTRIE_16Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicInch()Draft
ICU 64
ucptrie.h#define UCPTRIE_32Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicKilometer()Draft
ICU 64
ucptrie.h#define UCPTRIE_8Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicMeter()Draft
ICU 64
ucptrie.h#define UCPTRIE_ASCII_GETDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicMile()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_BMP_GETDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCubicYard()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_GETDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCup()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_SUPP_GETDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getCupMetric()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_U16_NEXTDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDalton()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_U16_PREVDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDay()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_U8_NEXTDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDayPerson()Draft
ICU 64
ucptrie.h#define UCPTRIE_FAST_U8_PREVDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDeciliter()Draft
ICU 64
ucptrie.h#define UCPTRIE_SMALL_GETDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDecimeter()Draft
ICU 64
ucptrie.hUCPTrie* ucptrie_openFromBinary(UCPTrieType, UCPTrieValueWidth, const void*, int32_t, int32_t*, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDegree()Draft
ICU 64
ucptrie.hUCPTrieType ucptrie_getType(const UCPTrie*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getDunam()Draft
ICU 64
ucptrie.hUCPTrieValueWidth ucptrie_getValueWidth(const UCPTrie*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getEarthMass()Draft
ICU 64
ucptrie.hUChar32 ucptrie_getRange(const UCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getElectronvolt()Draft
ICU 64
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_ANYDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFahrenheit()Draft
ICU 64
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_FASTDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFathom()Draft
ICU 64
ucptrie.henum UCPTrieType::UCPTRIE_TYPE_SMALLDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFluidOunce()Draft
ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_16Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFluidOunceImperial()Draft
ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_32Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFoodcalorie()Draft
ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_8Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFoot()Draft
ICU 64
ucptrie.henum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_ANYDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getFurlong()Draft
ICU 64
ucptrie.hint32_t ucptrie_toBinary(const UCPTrie*, void*, int32_t, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGForce()Draft
ICU 64
ucptrie.huint32_t ucptrie_get(const UCPTrie*, UChar32)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGallon()Draft
ICU 64
ucptrie.hvoid ucptrie_close(UCPTrie*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGallonImperial()Draft
ICU 64
ulistformatter.henum UListFormatterField::ULISTFMT_ELEMENT_FIELDDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGenericTemperature()Draft
ICU 64
ulistformatter.henum UListFormatterField::ULISTFMT_LITERAL_FIELDDraft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigabit()Draft
ICU 64
umutablecptrie.hUCPTrie* umutablecptrie_buildImmutable(UMutableCPTrie*, UCPTrieType, UCPTrieValueWidth, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigabyte()Draft
ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_clone(const UMutableCPTrie*, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigahertz()Draft
ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_fromUCPMap(const UCPMap*, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGigawatt()Draft
ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_fromUCPTrie(const UCPTrie*, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getGram()Draft
ICU 64
umutablecptrie.hUMutableCPTrie* umutablecptrie_open(uint32_t, uint32_t, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHectare()Draft
ICU 64
umutablecptrie.hUChar32 umutablecptrie_getRange(const UMutableCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHectoliter()Draft
ICU 64
umutablecptrie.huint32_t umutablecptrie_get(const UMutableCPTrie*, UChar32)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHectopascal()Draft
ICU 64
umutablecptrie.hvoid umutablecptrie_close(UMutableCPTrie*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHertz()Draft
ICU 64
umutablecptrie.hvoid umutablecptrie_set(UMutableCPTrie*, UChar32, uint32_t, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHorsepower()Draft
ICU 64
umutablecptrie.hvoid umutablecptrie_setRange(UMutableCPTrie*, UChar32, UChar32, uint32_t, UErrorCode*)Draft
ICU 63
measunit.hstatic MeasureUnit icu::MeasureUnit::getHour()Draft
ICU 64
unumberformatter.henum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_ALWAYSDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getInch()Draft
ICU 64
unumberformatter.henum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_AUTODraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getInchHg()Draft
ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_AUTODraft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getJoule()Draft
ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_MIN2Draft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKarat()Draft
ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_OFFDraft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKelvin()Draft
ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_ON_ALIGNEDDraft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilobit()Draft
ICU 64
unumberformatter.henum UNumberGroupingStrategy::UNUM_GROUPING_THOUSANDSDraft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilobyte()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYSDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilocalorie()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERODraft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilogram()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ACCOUNTINGDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilohertz()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_ALWAYSDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilojoule()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_AUTODraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilometer()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERODraft
ICU 61
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilometerPerHour()Draft
ICU 64
unumberformatter.henum UNumberSignDisplay::UNUM_SIGN_NEVERDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilopascal()Draft
ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAMEDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilowatt()Draft
ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDENDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKilowattHour()Draft
ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODEDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getKnot()Draft
ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROWDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getLightYear()Draft
ICU 64
unumberformatter.henum UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORTDraft
ICU 60
measunit.hstatic MeasureUnit icu::MeasureUnit::getLiter()Draft
ICU 64
uregex.henum URegexpFlag::UREGEX_CANON_EQDraft
ICU 2.4
measunit.hstatic MeasureUnit icu::MeasureUnit::getLiterPer100Kilometers()Draft
ICU 64
uspoof.henum USpoofChecks::USPOOF_HIDDEN_OVERLAYDraft
ICU 62
measunit.hstatic MeasureUnit icu::MeasureUnit::getLiterPerKilometer()Draft
ICU 64
-
-

-(jump back to top) -
- -

Signature Simplifications

-This section shows cases where the signature was "simplified" for the sake of comparison. The simplified form is in bold, followed by - all possible variations in "original" form. -
- + +measunit.hstatic MeasureUnit icu::MeasureUnit::getLux()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMegabit()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMegabyte()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMegahertz()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMegaliter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMegapascal()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMegawatt()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMeter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMeterPerSecond()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMeterPerSecondSquared()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMetricTon()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMicrogram()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMicrometer()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMicrosecond()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMile()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilePerGallon()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilePerGallonImperial()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilePerHour()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMileScandinavian()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilliampere()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMillibar()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilligram()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilligramPerDeciliter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilliliter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMillimeter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMillimeterOfMercury()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMillimolePerLiter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMillisecond()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMilliwatt()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMinute()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMole()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMonth()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getMonthPerson()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getNanometer()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getNanosecond()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getNauticalMile()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getNewton()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getNewtonMeter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getOhm()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getOunce()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getOunceTroy()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getParsec()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPartPerMillion()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPercent()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPermille()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPermyriad()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPetabyte()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPicometer()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPint()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPintMetric()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPoint()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPound()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPoundFoot()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPoundForce()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getPoundPerSquareInch()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getQuart()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getRadian()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getRevolutionAngle()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSecond()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSolarLuminosity()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSolarMass()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSolarRadius()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareCentimeter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareFoot()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareInch()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareKilometer()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareMeter()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareMile()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getSquareYard()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getStone()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getTablespoon()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getTeaspoon()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getTerabit()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getTerabyte()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getTon()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getVolt()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getWatt()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getWeek()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getWeekPerson()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getYard()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getYear()Draft
ICU 64 + + +measunit.hstatic MeasureUnit icu::MeasureUnit::getYearPerson()Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createBarrel(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createBritishThermalUnit(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createDalton(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createDayPerson(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createDunam(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createEarthMass(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createElectronvolt(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createFluidOunceImperial(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createKilopascal(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createMegapascal(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createMole(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createMonthPerson(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createNewton(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createNewtonMeter(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createPermyriad(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createPoundFoot(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createPoundForce(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createSolarLuminosity(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createSolarMass(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createSolarRadius(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createWeekPerson(UErrorCode&)Draft
ICU 64 + + +measunit.hstatic MeasureUnit* icu::MeasureUnit::createYearPerson(UErrorCode&)Draft
ICU 64 + + +nounit.hUClassID icu::NoUnit::getDynamicClassID() constDraft
ICU 60 + + +nounit.hicu::NoUnit::NoUnit(const NoUnit&)Draft
ICU 60 + + +nounit.hicu::NoUnit::~NoUnit()Draft
ICU 60 + + +nounit.hstatic NoUnit icu::NoUnit::base()Draft
ICU 60 + + +nounit.hstatic NoUnit icu::NoUnit::percent()Draft
ICU 60 + + +nounit.hstatic NoUnit icu::NoUnit::permille()Draft
ICU 60 + + +nounit.hstatic UClassID icu::NoUnit::getStaticClassID()Draft
ICU 60 + + +nounit.hvoid* icu::NoUnit::clone() constDraft
ICU 60 + + +numberformatter.hLocalPointer<Derived> icu::number::NumberFormatterSettings< Derived >::clone() &&Draft
ICU 64 + + +numberformatter.hLocalPointer<Derived> icu::number::NumberFormatterSettings< Derived >::clone() const &Draft
ICU 64 + + +numberformatter.hUBool icu::number::FormattedNumber::nextFieldPosition(FieldPosition&, UErrorCode&) constDraft
ICU 62 + + +numberformatter.hUBool icu::number::FormattedNumber::nextPosition(ConstrainedFieldPosition&, UErrorCode&) constDraft
ICU 64 + + +numberformatter.hUnicodeString icu::number::FormattedNumber::toTempString(UErrorCode&) constDraft
ICU 64 + + +numberformatter.hicu::number::FormattedNumber::FormattedNumber()Draft
ICU 64 + + +numberformatter.hstatic UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UParseError&, UErrorCode&)Draft
ICU 64 + + +numberformatter.hvoid icu::number::FormattedNumber::getAllFieldPositions(FieldPositionIterator&, UErrorCode&) constDraft
ICU 62 + + +numberrangeformatter.hLocalPointer<Derived> icu::number::NumberRangeFormatterSettings< Derived >::clone() &&Draft
ICU 64 + + +numberrangeformatter.hLocalPointer<Derived> icu::number::NumberRangeFormatterSettings< Derived >::clone() const &Draft
ICU 64 + + +numberrangeformatter.hUBool icu::number::FormattedNumberRange::nextFieldPosition(FieldPosition&, UErrorCode&) constDraft
ICU 63 + + +numberrangeformatter.hUBool icu::number::FormattedNumberRange::nextPosition(ConstrainedFieldPosition&, UErrorCode&) constDraft
ICU 64 + + +numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::getFirstDecimal(UErrorCode&) constDraft
ICU 63 + + +numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::getSecondDecimal(UErrorCode&) constDraft
ICU 63 + + +numberrangeformatter.hUnicodeString icu::number::FormattedNumberRange::toTempString(UErrorCode&) constDraft
ICU 64 + + +numberrangeformatter.hvoid icu::number::FormattedNumberRange::getAllFieldPositions(FieldPositionIterator&, UErrorCode&) constDraft
ICU 63 + + +numfmt.henum icu::NumberFormat::EAlignmentFields::kCompactFieldDraft
ICU 64 + + +numfmt.henum icu::NumberFormat::EAlignmentFields::kMeasureUnitFieldDraft
ICU 64 + + +plurrule.hUnicodeString icu::PluralRules::select(const number::FormattedNumber&, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hAppendable& icu::FormattedRelativeDateTime::appendTo(Appendable&, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatNumericToValue(double, URelativeDateTimeUnit, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(UDateDirection, UDateAbsoluteUnit, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(double, UDateDirection, UDateRelativeUnit, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hFormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(double, URelativeDateTimeUnit, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hFormattedRelativeDateTime& icu::FormattedRelativeDateTime::operator=(FormattedRelativeDateTime&&)Draft
ICU 64 + + +reldatefmt.hUBool icu::FormattedRelativeDateTime::nextPosition(ConstrainedFieldPosition&, UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hUnicodeString icu::FormattedRelativeDateTime::toString(UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hUnicodeString icu::FormattedRelativeDateTime::toTempString(UErrorCode&) constDraft
ICU 64 + + +reldatefmt.hicu::FormattedRelativeDateTime::FormattedRelativeDateTime()Draft
ICU 64 + + +reldatefmt.hicu::FormattedRelativeDateTime::FormattedRelativeDateTime(FormattedRelativeDateTime&&)Draft
ICU 64 + + +reldatefmt.hicu::FormattedRelativeDateTime::~FormattedRelativeDateTime()Draft
ICU 64 + + +udateintervalformat.hUFormattedDateInterval* udtitvfmt_openResult(UErrorCode*)Draft
ICU 64 + + +udateintervalformat.hconst UFormattedValue* udtitvfmt_resultAsValue(const UFormattedDateInterval*, UErrorCode*)Draft
ICU 64 + + +udateintervalformat.hvoid udtitvfmt_closeResult(UFormattedDateInterval*)Draft
ICU 64 + + +udateintervalformat.hvoid udtitvfmt_formatToResult(const UDateIntervalFormat*, UFormattedDateInterval*, UDate, UDate, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hUBool ucfpos_matchesField(const UConstrainedFieldPosition*, int32_t, int32_t, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hUBool ufmtval_nextPosition(const UFormattedValue*, UConstrainedFieldPosition*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hUConstrainedFieldPosition* ucfpos_open(UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hconst UChar* ufmtval_getString(const UFormattedValue*, int32_t*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_DATE_INTERVAL_SPANDraft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_DATEDraft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_LIST_SPANDraft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_LISTDraft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_NUMBERDraft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_RELATIVE_DATETIMEDraft
ICU 64 + + +uformattedvalue.henum UFieldCategory::UFIELD_CATEGORY_UNDEFINEDDraft
ICU 64 + + +uformattedvalue.hint32_t ucfpos_getCategory(const UConstrainedFieldPosition*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hint32_t ucfpos_getField(const UConstrainedFieldPosition*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hint64_t ucfpos_getInt64IterationContext(const UConstrainedFieldPosition*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_close(UConstrainedFieldPosition*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_constrainCategory(UConstrainedFieldPosition*, int32_t, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_constrainField(UConstrainedFieldPosition*, int32_t, int32_t, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_getIndexes(const UConstrainedFieldPosition*, int32_t*, int32_t*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_reset(UConstrainedFieldPosition*, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_setInt64IterationContext(UConstrainedFieldPosition*, int64_t, UErrorCode*)Draft
ICU 64 + + +uformattedvalue.hvoid ucfpos_setState(UConstrainedFieldPosition*, int32_t, int32_t, int32_t, int32_t, UErrorCode*)Draft
ICU 64 + + +ulistformatter.hUFormattedList* ulistfmt_openResult(UErrorCode*)Draft
ICU 64 + + +ulistformatter.hconst UFormattedValue* ulistfmt_resultAsValue(const UFormattedList*, UErrorCode*)Draft
ICU 64 + + +ulistformatter.henum UListFormatterField::ULISTFMT_ELEMENT_FIELDDraft
ICU 63 + + +ulistformatter.henum UListFormatterField::ULISTFMT_LITERAL_FIELDDraft
ICU 63 + + +ulistformatter.hvoid ulistfmt_closeResult(UFormattedList*)Draft
ICU 64 + + +ulistformatter.hvoid ulistfmt_formatStringsToResult(const UListFormatter*, const UChar* const strings[], const int32_t*, int32_t, UFormattedList*, UErrorCode*)Draft
ICU 64 + + +unum.henum UNumberFormatAttribute::UNUM_MINIMUM_GROUPING_DIGITSDraft
ICU 64 + + +unum.henum UNumberFormatAttribute::UNUM_PARSE_CASE_SENSITIVEDraft
ICU 64 + + +unum.henum UNumberFormatAttribute::UNUM_SIGN_ALWAYS_SHOWNDraft
ICU 64 + + +unum.henum UNumberFormatFields::UNUM_COMPACT_FIELDDraft
ICU 64 + + +unum.henum UNumberFormatFields::UNUM_MEASURE_UNIT_FIELDDraft
ICU 64 + + +unumberformatter.hUNumberFormatter* unumf_openForSkeletonAndLocaleWithError(const UChar*, int32_t, const char*, UParseError*, UErrorCode*)Draft
ICU 64 + + +unumberformatter.hconst UFormattedValue* unumf_resultAsValue(const UFormattedNumber*, UErrorCode*)Draft
ICU 64 + + +upluralrules.hint32_t uplrules_selectFormatted(const UPluralRules*, const struct UFormattedNumber*, UChar*, int32_t, UErrorCode*)Draft
ICU 64 + + +uregex.henum URegexpFlag::UREGEX_CANON_EQDraft
ICU 2.4 + + +ureldatefmt.hUFormattedRelativeDateTime* ureldatefmt_openResult(UErrorCode*)Draft
ICU 64 + + +ureldatefmt.hconst UFormattedValue* ureldatefmt_resultAsValue(const UFormattedRelativeDateTime*, UErrorCode*)Draft
ICU 64 + + +ureldatefmt.henum URelativeDateTimeFormatterField::UDAT_REL_LITERAL_FIELDDraft
ICU 64 + + +ureldatefmt.henum URelativeDateTimeFormatterField::UDAT_REL_NUMERIC_FIELDDraft
ICU 64 + + +ureldatefmt.hvoid ureldatefmt_closeResult(UFormattedRelativeDateTime*)Draft
ICU 64 + + +ureldatefmt.hvoid ureldatefmt_formatNumericToResult(const URelativeDateTimeFormatter*, double, URelativeDateTimeUnit, UFormattedRelativeDateTime*, UErrorCode*)Draft
ICU 64 + + +ureldatefmt.hvoid ureldatefmt_formatToResult(const URelativeDateTimeFormatter*, double, URelativeDateTimeUnit, UFormattedRelativeDateTime*, UErrorCode*)Draft
ICU 64 + + +
+

+(jump back to top) +
+ +

Signature Simplifications

+This section shows cases where the signature was "simplified" for the sake of comparison. The simplified form is in bold, followed by + all possible variations in "original" form. +
+

(jump back to top)

-Contents generated by StableAPI tool on Fri Apr 05 10:36:27 PDT 2019
Copyright (C) 2019, International Business Machines Corporation, All Rights Reserved.
+Contents generated by StableAPI tool on Wed Oct 02 10:22:29 PDT 2019
+ Copyright © 2017 and later: Unicode, Inc. and others.
+ License & terms of use: http://www.unicode.org/copyright.html +

diff -Nru icu-64.2/APIChangeReport.md icu-65.1/APIChangeReport.md --- icu-64.2/APIChangeReport.md 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/APIChangeReport.md 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,1093 @@ + + + + +# ICU4C API Comparison: ICU 64 (update #1: 64.2) with ICU 65 + +> _Note_ Markdown format of this document is new for ICU 65. + +- [Removed from ICU 64](#removed) +- [Deprecated or Obsoleted in ICU 65](#deprecated) +- [Changed in ICU 65](#changed) +- [Promoted to stable in ICU 65](#promoted) +- [Added in ICU 65](#added) +- [Other existing drafts in ICU 65](#other) +- [Signature Simplifications](#simplifications) + +## Removed + +Removed from ICU 64 + +| File | API | ICU 64 | ICU 65 | +|---|---|---|---| +| decimfmt.h | const number::LocalizedNumberFormatter& icu::DecimalFormat::toNumberFormatter() const | DeprecatedICU 64 | (missing) +| edits.h | UBool icu::Edits::copyErrorTo(UErrorCode&) | StableICU 59 | (missing) +| platform.h | #define __has_attribute | Internal | (missing) +| platform.h | #define __has_builtin | Internal | (missing) +| platform.h | #define __has_cpp_attribute | Internal | (missing) +| platform.h | #define __has_declspec_attribute | Internal | (missing) +| platform.h | #define __has_extension | Internal | (missing) +| platform.h | #define __has_feature | Internal | (missing) +| platform.h | #define __has_warning | Internal | (missing) +| uversion.h | #define U_NAMESPACE_BEGIN | StableICU 2.4 | (missing) +| uversion.h | #define U_NAMESPACE_END | StableICU 2.4 | (missing) +| uversion.h | #define U_NAMESPACE_QUALIFIER | StableICU 2.4 | (missing) +| uversion.h | #define U_NAMESPACE_USE | StableICU 2.4 | (missing) + +## Deprecated + +Deprecated or Obsoleted in ICU 65 + +| File | API | ICU 64 | ICU 65 | +|---|---|---|---| + +## Changed + +Changed in ICU 65 (old, new) + + + +| File | API | ICU 64 | ICU 65 | +|---|---|---|---| +| decimfmt.h | int32_t icu::DecimalFormat::getMultiplierScale() const | Draft→StableICU 62 +| decimfmt.h | void icu::DecimalFormat::setMultiplierScale(int32_t) | Draft→StableICU 62 +| locid.h | Locale& icu::Locale::operator=(Locale&&) | Draft→StableICU 63 +| locid.h | StringClass icu::Locale::getKeywordValue(StringPiece, UErrorCode&) const | Draft→StableICU 63 +| locid.h | StringClass icu::Locale::getUnicodeKeywordValue(StringPiece, UErrorCode&) const | Draft→StableICU 63 +| locid.h | StringClass icu::Locale::toLanguageTag(UErrorCode&) const | Draft→StableICU 63 +| locid.h | StringEnumeration* icu::Locale::createUnicodeKeywords(UErrorCode&) const | Draft→StableICU 63 +| locid.h | icu::Locale::Locale(Locale&&) | Draft→StableICU 63 +| locid.h | static Locale icu::Locale::forLanguageTag(StringPiece, UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::addLikelySubtags(UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::getKeywordValue(StringPiece, ByteSink&, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::getKeywords(OutputIterator, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::getUnicodeKeywordValue(StringPiece, ByteSink&, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::getUnicodeKeywords(OutputIterator, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::minimizeSubtags(UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::setKeywordValue(StringPiece, StringPiece, UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::setUnicodeKeywordValue(StringPiece, StringPiece, UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::toLanguageTag(ByteSink&, UErrorCode&) const | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createAtmosphere(UErrorCode&) | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPercent(UErrorCode&) | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPermille(UErrorCode&) | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPetabyte(UErrorCode&) | Draft→StableICU 63 +| numberformatter.h | Appendable& icu::number::FormattedNumber::appendTo(Appendable&, UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*) const& | Draft→StableICU 61 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy) const& | Draft→StableICU 61 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&) const& | Draft→StableICU 61 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&) const& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode) const& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&) const& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth)&& | Draft→StableICU 62 +| numberformatter.h | Format* icu::number::LocalizedNumberFormatter::toFormat(UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | FormattedNumber icu::number::LocalizedNumberFormatter::formatDecimal(StringPiece, UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | FormattedNumber icu::number::LocalizedNumberFormatter::formatDouble(double, UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | FormattedNumber icu::number::LocalizedNumberFormatter::formatInt(int64_t, UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | FormattedNumber& icu::number::FormattedNumber::operator=(FormattedNumber&&) | Draft→StableICU 62 +| numberformatter.h | IntegerWidth icu::number::IntegerWidth::truncateAt(int32_t) | Draft→StableICU 60 +| numberformatter.h | LocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&) const& | Draft→StableICU 60 +| numberformatter.h | LocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&)&& | Draft→StableICU 62 +| numberformatter.h | LocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(LocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | LocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(const LocalizedNumberFormatter&) | Draft→StableICU 62 +| numberformatter.h | Precision icu::number::CurrencyPrecision::withCurrency(const CurrencyUnit&) const | Draft→StableICU 60 +| numberformatter.h | Precision icu::number::FractionPrecision::withMaxDigits(int32_t) const | Draft→StableICU 60 +| numberformatter.h | Precision icu::number::FractionPrecision::withMinDigits(int32_t) const | Draft→StableICU 60 +| numberformatter.h | Precision icu::number::IncrementPrecision::withMinFraction(int32_t) const | Draft→StableICU 60 +| numberformatter.h | Scale& icu::number::Scale::operator=(Scale&&) | Draft→StableICU 62 +| numberformatter.h | Scale& icu::number::Scale::operator=(const Scale&) | Draft→StableICU 62 +| numberformatter.h | ScientificNotation icu::number::ScientificNotation::withExponentSignDisplay(UNumberSignDisplay) const | Draft→StableICU 60 +| numberformatter.h | ScientificNotation icu::number::ScientificNotation::withMinExponentDigits(int32_t) const | Draft→StableICU 60 +| numberformatter.h | UBool icu::number::NumberFormatterSettings< Derived >::copyErrorTo(UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | UnicodeString icu::number::FormattedNumber::toString(UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | UnicodeString icu::number::NumberFormatterSettings< Derived >::toSkeleton(UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | UnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(UnlocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | UnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(const UnlocalizedNumberFormatter&) | Draft→StableICU 62 +| numberformatter.h | icu::number::FormattedNumber::FormattedNumber(FormattedNumber&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::FormattedNumber::~FormattedNumber() | Draft→StableICU 60 +| numberformatter.h | icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter()=default | Draft→StableICU 62 +| numberformatter.h | icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(const LocalizedNumberFormatter&) | Draft→StableICU 60 +| numberformatter.h | icu::number::LocalizedNumberFormatter::~LocalizedNumberFormatter() | Draft→StableICU 60 +| numberformatter.h | icu::number::Scale::Scale(Scale&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::Scale::Scale(const Scale&) | Draft→StableICU 62 +| numberformatter.h | icu::number::Scale::~Scale() | Draft→StableICU 62 +| numberformatter.h | icu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter()=default | Draft→StableICU 62 +| numberformatter.h | icu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter&) | Draft→StableICU 60 +| numberformatter.h | static CompactNotation icu::number::Notation::compactLong() | Draft→StableICU 60 +| numberformatter.h | static CompactNotation icu::number::Notation::compactShort() | Draft→StableICU 60 +| numberformatter.h | static CurrencyPrecision icu::number::Precision::currency(UCurrencyUsage) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::fixedFraction(int32_t) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::integer() | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::maxFraction(int32_t) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::minFraction(int32_t) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::minMaxFraction(int32_t, int32_t) | Draft→StableICU 60 +| numberformatter.h | static IncrementPrecision icu::number::Precision::increment(double) | Draft→StableICU 60 +| numberformatter.h | static IntegerWidth icu::number::IntegerWidth::zeroFillTo(int32_t) | Draft→StableICU 60 +| numberformatter.h | static LocalizedNumberFormatter icu::number::NumberFormatter::withLocale(const Locale&) | Draft→StableICU 60 +| numberformatter.h | static Precision icu::number::Precision::unlimited() | Draft→StableICU 60 +| numberformatter.h | static Scale icu::number::Scale::byDecimal(StringPiece) | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::byDouble(double) | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::byDoubleAndPowerOfTen(double, int32_t) | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::none() | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::powerOfTen(int32_t) | Draft→StableICU 62 +| numberformatter.h | static ScientificNotation icu::number::Notation::engineering() | Draft→StableICU 60 +| numberformatter.h | static ScientificNotation icu::number::Notation::scientific() | Draft→StableICU 60 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::fixedSignificantDigits(int32_t) | Draft→StableICU 62 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::maxSignificantDigits(int32_t) | Draft→StableICU 62 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::minMaxSignificantDigits(int32_t, int32_t) | Draft→StableICU 62 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::minSignificantDigits(int32_t) | Draft→StableICU 62 +| numberformatter.h | static SimpleNotation icu::number::Notation::simple() | Draft→StableICU 60 +| numberformatter.h | static UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UErrorCode&) | Draft→StableICU 62 +| numberformatter.h | static UnlocalizedNumberFormatter icu::number::NumberFormatter::with() | Draft→StableICU 60 +| numberrangeformatter.h | Appendable& icu::number::FormattedNumberRange::appendTo(Appendable&, UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&)&& | Draft→StableICU 63 +| numberrangeformatter.h | FormattedNumberRange icu::number::LocalizedNumberRangeFormatter::formatFormattableRange(const Formattable&, const Formattable&, UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | FormattedNumberRange& icu::number::FormattedNumberRange::operator=(FormattedNumberRange&&) | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&) const& | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&)&& | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(LocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(const LocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | UBool icu::number::NumberRangeFormatterSettings< Derived >::copyErrorTo(UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | UNumberRangeIdentityResult icu::number::FormattedNumberRange::getIdentityResult(UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::toString(UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | UnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(UnlocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | UnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(const UnlocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_ALL | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_AUTO | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_NONE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_UNIT | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_RANGE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_SINGLE_VALUE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_NOT_EQUAL | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::FormattedNumberRange::~FormattedNumberRange() | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter()=default | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter() | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter()=default | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | static LocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::withLocale(const Locale&) | Draft→StableICU 63 +| numberrangeformatter.h | static UnlocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::with() | Draft→StableICU 63 +| reldatefmt.h | enum UDateAbsoluteUnit::UDAT_ABSOLUTE_QUARTER | Draft→StableICU 63 +| uchar.h | const UCPMap* u_getIntPropertyMap(UProperty, UErrorCode*) | Draft→StableICU 63 +| uchar.h | const USet* u_getBinaryPropertySet(UProperty, UErrorCode*) | Draft→StableICU 63 +| ucpmap.h | UChar32 ucpmap_getRange(const UCPMap*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*) | Draft→StableICU 63 +| ucpmap.h | enum UCPMapRangeOption::UCPMAP_RANGE_FIXED_ALL_SURROGATES | Draft→StableICU 63 +| ucpmap.h | enum UCPMapRangeOption::UCPMAP_RANGE_FIXED_LEAD_SURROGATES | Draft→StableICU 63 +| ucpmap.h | enum UCPMapRangeOption::UCPMAP_RANGE_NORMAL | Draft→StableICU 63 +| ucpmap.h | uint32_t ucpmap_get(const UCPMap*, UChar32) | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_16 | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_32 | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_8 | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_ASCII_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_BMP_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_SUPP_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U16_NEXT | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U16_PREV | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U8_NEXT | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U8_PREV | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_SMALL_GET | Draft→StableICU 63 +| ucptrie.h | UCPTrie* ucptrie_openFromBinary(UCPTrieType, UCPTrieValueWidth, const void*, int32_t, int32_t*, UErrorCode*) | Draft→StableICU 63 +| ucptrie.h | UCPTrieType ucptrie_getType(const UCPTrie*) | Draft→StableICU 63 +| ucptrie.h | UCPTrieValueWidth ucptrie_getValueWidth(const UCPTrie*) | Draft→StableICU 63 +| ucptrie.h | UChar32 ucptrie_getRange(const UCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*) | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieType::UCPTRIE_TYPE_ANY | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieType::UCPTRIE_TYPE_FAST | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieType::UCPTRIE_TYPE_SMALL | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_16 | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_32 | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_8 | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_ANY | Draft→StableICU 63 +| ucptrie.h | int32_t ucptrie_toBinary(const UCPTrie*, void*, int32_t, UErrorCode*) | Draft→StableICU 63 +| ucptrie.h | uint32_t ucptrie_get(const UCPTrie*, UChar32) | Draft→StableICU 63 +| ucptrie.h | void ucptrie_close(UCPTrie*) | Draft→StableICU 63 +| umutablecptrie.h | UCPTrie* umutablecptrie_buildImmutable(UMutableCPTrie*, UCPTrieType, UCPTrieValueWidth, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_clone(const UMutableCPTrie*, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_fromUCPMap(const UCPMap*, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_fromUCPTrie(const UCPTrie*, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_open(uint32_t, uint32_t, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UChar32 umutablecptrie_getRange(const UMutableCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*) | Draft→StableICU 63 +| umutablecptrie.h | uint32_t umutablecptrie_get(const UMutableCPTrie*, UChar32) | Draft→StableICU 63 +| umutablecptrie.h | void umutablecptrie_close(UMutableCPTrie*) | Draft→StableICU 63 +| umutablecptrie.h | void umutablecptrie_set(UMutableCPTrie*, UChar32, uint32_t, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | void umutablecptrie_setRange(UMutableCPTrie*, UChar32, UChar32, uint32_t, UErrorCode*) | Draft→StableICU 63 +| unumberformatter.h | enum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_ALWAYS | Draft→StableICU 60 +| unumberformatter.h | enum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_AUTO | Draft→StableICU 60 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_AUTO | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_MIN2 | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_OFF | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_ON_ALIGNED | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_THOUSANDS | Draft→StableICU 61 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO | Draft→StableICU 61 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ALWAYS | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_AUTO | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO | Draft→StableICU 61 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_NEVER | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT | Draft→StableICU 60 +| uspoof.h | enum USpoofChecks::USPOOF_HIDDEN_OVERLAY | Draft→StableICU 62 +| utf_old.h | #define U_HIDE_OBSOLETE_UTF_OLD_H | DeprecatedICU 2.4 | Internal + +## Promoted + +Promoted to stable in ICU 65 + +| File | API | ICU 64 | ICU 65 | +|---|---|---|---| +| basictz.h | void* icu::BasicTimeZone::clone() const | (missing) | StableICU 3.8 +| datefmt.h | void* icu::DateFormat::clone() const | (missing) | StableICU 2.0 +| decimfmt.h | int32_t icu::DecimalFormat::getMultiplierScale() const | Draft→StableICU 62 +| decimfmt.h | void icu::DecimalFormat::setMultiplierScale(int32_t) | Draft→StableICU 62 +| edits.h | UBool icu::Edits::copyErrorTo(UErrorCode&) const | (missing) | StableICU 59 +| locid.h | Locale& icu::Locale::operator=(Locale&&) | Draft→StableICU 63 +| locid.h | StringClass icu::Locale::getKeywordValue(StringPiece, UErrorCode&) const | Draft→StableICU 63 +| locid.h | StringClass icu::Locale::getUnicodeKeywordValue(StringPiece, UErrorCode&) const | Draft→StableICU 63 +| locid.h | StringClass icu::Locale::toLanguageTag(UErrorCode&) const | Draft→StableICU 63 +| locid.h | StringEnumeration* icu::Locale::createUnicodeKeywords(UErrorCode&) const | Draft→StableICU 63 +| locid.h | icu::Locale::Locale(Locale&&) | Draft→StableICU 63 +| locid.h | static Locale icu::Locale::forLanguageTag(StringPiece, UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::addLikelySubtags(UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::getKeywordValue(StringPiece, ByteSink&, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::getKeywords(OutputIterator, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::getUnicodeKeywordValue(StringPiece, ByteSink&, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::getUnicodeKeywords(OutputIterator, UErrorCode&) const | Draft→StableICU 63 +| locid.h | void icu::Locale::minimizeSubtags(UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::setKeywordValue(StringPiece, StringPiece, UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::setUnicodeKeywordValue(StringPiece, StringPiece, UErrorCode&) | Draft→StableICU 63 +| locid.h | void icu::Locale::toLanguageTag(ByteSink&, UErrorCode&) const | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createAtmosphere(UErrorCode&) | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPercent(UErrorCode&) | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPermille(UErrorCode&) | Draft→StableICU 63 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPetabyte(UErrorCode&) | Draft→StableICU 63 +| numberformatter.h | Appendable& icu::number::FormattedNumber::appendTo(Appendable&, UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*) const& | Draft→StableICU 61 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptPerUnit(icu::MeasureUnit*)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptSymbols(NumberingSystem*)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::adoptUnit(icu::MeasureUnit*)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::decimal(UNumberDecimalSeparatorDisplay)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy) const& | Draft→StableICU 61 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::grouping(UNumberGroupingStrategy)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::integerWidth(const IntegerWidth&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::notation(const Notation&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&) const& | Draft→StableICU 61 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::perUnit(const icu::MeasureUnit&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&) const& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::precision(const Precision&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode) const& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::roundingMode(UNumberFormatRoundingMode)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&) const& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::scale(const Scale&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::sign(UNumberSignDisplay)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::symbols(const DecimalFormatSymbols&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unit(const icu::MeasureUnit&)&& | Draft→StableICU 62 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth) const& | Draft→StableICU 60 +| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::unitWidth(UNumberUnitWidth)&& | Draft→StableICU 62 +| numberformatter.h | Format* icu::number::LocalizedNumberFormatter::toFormat(UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | FormattedNumber icu::number::LocalizedNumberFormatter::formatDecimal(StringPiece, UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | FormattedNumber icu::number::LocalizedNumberFormatter::formatDouble(double, UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | FormattedNumber icu::number::LocalizedNumberFormatter::formatInt(int64_t, UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | FormattedNumber& icu::number::FormattedNumber::operator=(FormattedNumber&&) | Draft→StableICU 62 +| numberformatter.h | IntegerWidth icu::number::IntegerWidth::truncateAt(int32_t) | Draft→StableICU 60 +| numberformatter.h | LocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&) const& | Draft→StableICU 60 +| numberformatter.h | LocalizedNumberFormatter icu::number::UnlocalizedNumberFormatter::locale(const icu::Locale&)&& | Draft→StableICU 62 +| numberformatter.h | LocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(LocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | LocalizedNumberFormatter& icu::number::LocalizedNumberFormatter::operator=(const LocalizedNumberFormatter&) | Draft→StableICU 62 +| numberformatter.h | Precision icu::number::CurrencyPrecision::withCurrency(const CurrencyUnit&) const | Draft→StableICU 60 +| numberformatter.h | Precision icu::number::FractionPrecision::withMaxDigits(int32_t) const | Draft→StableICU 60 +| numberformatter.h | Precision icu::number::FractionPrecision::withMinDigits(int32_t) const | Draft→StableICU 60 +| numberformatter.h | Precision icu::number::IncrementPrecision::withMinFraction(int32_t) const | Draft→StableICU 60 +| numberformatter.h | Scale& icu::number::Scale::operator=(Scale&&) | Draft→StableICU 62 +| numberformatter.h | Scale& icu::number::Scale::operator=(const Scale&) | Draft→StableICU 62 +| numberformatter.h | ScientificNotation icu::number::ScientificNotation::withExponentSignDisplay(UNumberSignDisplay) const | Draft→StableICU 60 +| numberformatter.h | ScientificNotation icu::number::ScientificNotation::withMinExponentDigits(int32_t) const | Draft→StableICU 60 +| numberformatter.h | UBool icu::number::NumberFormatterSettings< Derived >::copyErrorTo(UErrorCode&) const | Draft→StableICU 60 +| numberformatter.h | UnicodeString icu::number::FormattedNumber::toString(UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | UnicodeString icu::number::NumberFormatterSettings< Derived >::toSkeleton(UErrorCode&) const | Draft→StableICU 62 +| numberformatter.h | UnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(UnlocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | UnlocalizedNumberFormatter& icu::number::UnlocalizedNumberFormatter::operator=(const UnlocalizedNumberFormatter&) | Draft→StableICU 62 +| numberformatter.h | icu::number::FormattedNumber::FormattedNumber(FormattedNumber&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::FormattedNumber::~FormattedNumber() | Draft→StableICU 60 +| numberformatter.h | icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter()=default | Draft→StableICU 62 +| numberformatter.h | icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::LocalizedNumberFormatter::LocalizedNumberFormatter(const LocalizedNumberFormatter&) | Draft→StableICU 60 +| numberformatter.h | icu::number::LocalizedNumberFormatter::~LocalizedNumberFormatter() | Draft→StableICU 60 +| numberformatter.h | icu::number::Scale::Scale(Scale&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::Scale::Scale(const Scale&) | Draft→StableICU 62 +| numberformatter.h | icu::number::Scale::~Scale() | Draft→StableICU 62 +| numberformatter.h | icu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter()=default | Draft→StableICU 62 +| numberformatter.h | icu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&&) | Draft→StableICU 62 +| numberformatter.h | icu::number::UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter&) | Draft→StableICU 60 +| numberformatter.h | static CompactNotation icu::number::Notation::compactLong() | Draft→StableICU 60 +| numberformatter.h | static CompactNotation icu::number::Notation::compactShort() | Draft→StableICU 60 +| numberformatter.h | static CurrencyPrecision icu::number::Precision::currency(UCurrencyUsage) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::fixedFraction(int32_t) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::integer() | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::maxFraction(int32_t) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::minFraction(int32_t) | Draft→StableICU 60 +| numberformatter.h | static FractionPrecision icu::number::Precision::minMaxFraction(int32_t, int32_t) | Draft→StableICU 60 +| numberformatter.h | static IncrementPrecision icu::number::Precision::increment(double) | Draft→StableICU 60 +| numberformatter.h | static IntegerWidth icu::number::IntegerWidth::zeroFillTo(int32_t) | Draft→StableICU 60 +| numberformatter.h | static LocalizedNumberFormatter icu::number::NumberFormatter::withLocale(const Locale&) | Draft→StableICU 60 +| numberformatter.h | static Precision icu::number::Precision::unlimited() | Draft→StableICU 60 +| numberformatter.h | static Scale icu::number::Scale::byDecimal(StringPiece) | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::byDouble(double) | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::byDoubleAndPowerOfTen(double, int32_t) | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::none() | Draft→StableICU 62 +| numberformatter.h | static Scale icu::number::Scale::powerOfTen(int32_t) | Draft→StableICU 62 +| numberformatter.h | static ScientificNotation icu::number::Notation::engineering() | Draft→StableICU 60 +| numberformatter.h | static ScientificNotation icu::number::Notation::scientific() | Draft→StableICU 60 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::fixedSignificantDigits(int32_t) | Draft→StableICU 62 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::maxSignificantDigits(int32_t) | Draft→StableICU 62 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::minMaxSignificantDigits(int32_t, int32_t) | Draft→StableICU 62 +| numberformatter.h | static SignificantDigitsPrecision icu::number::Precision::minSignificantDigits(int32_t) | Draft→StableICU 62 +| numberformatter.h | static SimpleNotation icu::number::Notation::simple() | Draft→StableICU 60 +| numberformatter.h | static UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UErrorCode&) | Draft→StableICU 62 +| numberformatter.h | static UnlocalizedNumberFormatter icu::number::NumberFormatter::with() | Draft→StableICU 60 +| numberrangeformatter.h | Appendable& icu::number::FormattedNumberRange::appendTo(Appendable&, UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::collapse(UNumberRangeCollapse)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::identityFallback(UNumberRangeIdentityFallback)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(UnlocalizedNumberFormatter&&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterBoth(const UnlocalizedNumberFormatter&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(UnlocalizedNumberFormatter&&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterFirst(const UnlocalizedNumberFormatter&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(UnlocalizedNumberFormatter&&)&& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&) const& | Draft→StableICU 63 +| numberrangeformatter.h | Derived icu::number::NumberRangeFormatterSettings< Derived >::numberFormatterSecond(const UnlocalizedNumberFormatter&)&& | Draft→StableICU 63 +| numberrangeformatter.h | FormattedNumberRange icu::number::LocalizedNumberRangeFormatter::formatFormattableRange(const Formattable&, const Formattable&, UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | FormattedNumberRange& icu::number::FormattedNumberRange::operator=(FormattedNumberRange&&) | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&) const& | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter icu::number::UnlocalizedNumberRangeFormatter::locale(const icu::Locale&)&& | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(LocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | LocalizedNumberRangeFormatter& icu::number::LocalizedNumberRangeFormatter::operator=(const LocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | UBool icu::number::NumberRangeFormatterSettings< Derived >::copyErrorTo(UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | UNumberRangeIdentityResult icu::number::FormattedNumberRange::getIdentityResult(UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::toString(UErrorCode&) const | Draft→StableICU 63 +| numberrangeformatter.h | UnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(UnlocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | UnlocalizedNumberRangeFormatter& icu::number::UnlocalizedNumberRangeFormatter::operator=(const UnlocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_ALL | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_AUTO | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_NONE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeCollapse::UNUM_RANGE_COLLAPSE_UNIT | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_APPROXIMATELY | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_RANGE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityFallback::UNUM_IDENTITY_FALLBACK_SINGLE_VALUE | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING | Draft→StableICU 63 +| numberrangeformatter.h | enum UNumberRangeIdentityResult::UNUM_IDENTITY_RESULT_NOT_EQUAL | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::FormattedNumberRange::~FormattedNumberRange() | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter()=default | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter() | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter()=default | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&&) | Draft→StableICU 63 +| numberrangeformatter.h | icu::number::UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter&) | Draft→StableICU 63 +| numberrangeformatter.h | static LocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::withLocale(const Locale&) | Draft→StableICU 63 +| numberrangeformatter.h | static UnlocalizedNumberRangeFormatter icu::number::NumberRangeFormatter::with() | Draft→StableICU 63 +| numfmt.h | void* icu::NumberFormat::clone() const | (missing) | StableICU 2.0 +| reldatefmt.h | enum UDateAbsoluteUnit::UDAT_ABSOLUTE_QUARTER | Draft→StableICU 63 +| uchar.h | const UCPMap* u_getIntPropertyMap(UProperty, UErrorCode*) | Draft→StableICU 63 +| uchar.h | const USet* u_getBinaryPropertySet(UProperty, UErrorCode*) | Draft→StableICU 63 +| ucpmap.h | UChar32 ucpmap_getRange(const UCPMap*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*) | Draft→StableICU 63 +| ucpmap.h | enum UCPMapRangeOption::UCPMAP_RANGE_FIXED_ALL_SURROGATES | Draft→StableICU 63 +| ucpmap.h | enum UCPMapRangeOption::UCPMAP_RANGE_FIXED_LEAD_SURROGATES | Draft→StableICU 63 +| ucpmap.h | enum UCPMapRangeOption::UCPMAP_RANGE_NORMAL | Draft→StableICU 63 +| ucpmap.h | uint32_t ucpmap_get(const UCPMap*, UChar32) | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_16 | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_32 | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_8 | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_ASCII_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_BMP_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_SUPP_GET | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U16_NEXT | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U16_PREV | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U8_NEXT | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_FAST_U8_PREV | Draft→StableICU 63 +| ucptrie.h | #define UCPTRIE_SMALL_GET | Draft→StableICU 63 +| ucptrie.h | UCPTrie* ucptrie_openFromBinary(UCPTrieType, UCPTrieValueWidth, const void*, int32_t, int32_t*, UErrorCode*) | Draft→StableICU 63 +| ucptrie.h | UCPTrieType ucptrie_getType(const UCPTrie*) | Draft→StableICU 63 +| ucptrie.h | UCPTrieValueWidth ucptrie_getValueWidth(const UCPTrie*) | Draft→StableICU 63 +| ucptrie.h | UChar32 ucptrie_getRange(const UCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*) | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieType::UCPTRIE_TYPE_ANY | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieType::UCPTRIE_TYPE_FAST | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieType::UCPTRIE_TYPE_SMALL | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_16 | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_32 | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_8 | Draft→StableICU 63 +| ucptrie.h | enum UCPTrieValueWidth::UCPTRIE_VALUE_BITS_ANY | Draft→StableICU 63 +| ucptrie.h | int32_t ucptrie_toBinary(const UCPTrie*, void*, int32_t, UErrorCode*) | Draft→StableICU 63 +| ucptrie.h | uint32_t ucptrie_get(const UCPTrie*, UChar32) | Draft→StableICU 63 +| ucptrie.h | void ucptrie_close(UCPTrie*) | Draft→StableICU 63 +| umutablecptrie.h | UCPTrie* umutablecptrie_buildImmutable(UMutableCPTrie*, UCPTrieType, UCPTrieValueWidth, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_clone(const UMutableCPTrie*, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_fromUCPMap(const UCPMap*, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_fromUCPTrie(const UCPTrie*, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UMutableCPTrie* umutablecptrie_open(uint32_t, uint32_t, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | UChar32 umutablecptrie_getRange(const UMutableCPTrie*, UChar32, UCPMapRangeOption, uint32_t, UCPMapValueFilter*, const void*, uint32_t*) | Draft→StableICU 63 +| umutablecptrie.h | uint32_t umutablecptrie_get(const UMutableCPTrie*, UChar32) | Draft→StableICU 63 +| umutablecptrie.h | void umutablecptrie_close(UMutableCPTrie*) | Draft→StableICU 63 +| umutablecptrie.h | void umutablecptrie_set(UMutableCPTrie*, UChar32, uint32_t, UErrorCode*) | Draft→StableICU 63 +| umutablecptrie.h | void umutablecptrie_setRange(UMutableCPTrie*, UChar32, UChar32, uint32_t, UErrorCode*) | Draft→StableICU 63 +| unifilt.h | void* icu::UnicodeFilter::clone() const | (missing) | StableICU 2.4 +| unumberformatter.h | enum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_ALWAYS | Draft→StableICU 60 +| unumberformatter.h | enum UNumberDecimalSeparatorDisplay::UNUM_DECIMAL_SEPARATOR_AUTO | Draft→StableICU 60 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_AUTO | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_MIN2 | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_OFF | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_ON_ALIGNED | Draft→StableICU 61 +| unumberformatter.h | enum UNumberGroupingStrategy::UNUM_GROUPING_THOUSANDS | Draft→StableICU 61 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO | Draft→StableICU 61 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ACCOUNTING | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_ALWAYS | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_AUTO | Draft→StableICU 60 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO | Draft→StableICU 61 +| unumberformatter.h | enum UNumberSignDisplay::UNUM_SIGN_NEVER | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW | Draft→StableICU 60 +| unumberformatter.h | enum UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT | Draft→StableICU 60 +| uspoof.h | enum USpoofChecks::USPOOF_HIDDEN_OVERLAY | Draft→StableICU 62 + +## Added + +Added in ICU 65 + +| File | API | ICU 64 | ICU 65 | +|---|---|---|---| +| basictz.h | void* icu::BasicTimeZone::clone() const | (missing) | StableICU 3.8 +| bytestrie.h | BytesTrie& icu::BytesTrie::resetToState64(uint64_t) | (missing) | DraftICU 65 +| bytestrie.h | uint64_t icu::BytesTrie::getState64() const | (missing) | DraftICU 65 +| datefmt.h | void* icu::DateFormat::clone() const | (missing) | StableICU 2.0 +| edits.h | UBool icu::Edits::copyErrorTo(UErrorCode&) const | (missing) | StableICU 59 +| localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::operator=(Builder&&) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDefaultLocale(const Locale*) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocales(Iter, Iter) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator&) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocalesFromListString(StringPiece) | (missing) | DraftICU 65 +| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocalesViaConverter(Iter, Iter, Conv) | (missing) | DraftICU 65 +| localematcher.h | Locale icu::LocaleMatcher::Result::makeResolvedLocale(UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | LocaleMatcher icu::LocaleMatcher::Builder::build(UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | LocaleMatcher& icu::LocaleMatcher::operator=(LocaleMatcher&&) | (missing) | DraftICU 65 +| localematcher.h | Result icu::LocaleMatcher::getBestMatchResult(Locale::Iterator&, UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | Result icu::LocaleMatcher::getBestMatchResult(const Locale&, UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | Result& icu::LocaleMatcher::Result::operator=(Result&&) | (missing) | DraftICU 65 +| localematcher.h | UBool icu::LocaleMatcher::Builder::copyErrorTo(UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | const Locale* icu::LocaleMatcher::Result::getDesiredLocale() const | (missing) | DraftICU 65 +| localematcher.h | const Locale* icu::LocaleMatcher::Result::getSupportedLocale() const | (missing) | DraftICU 65 +| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatch(Locale::Iterator&, UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatch(const Locale&, UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatchForListString(StringPiece, UErrorCode&) const | (missing) | DraftICU 65 +| localematcher.h | double icu::LocaleMatcher::internalMatch(const Locale&, const Locale&, UErrorCode&) const | (missing) | Internal +| localematcher.h | enum ULocMatchDemotion::ULOCMATCH_DEMOTION_NONE | (missing) | DraftICU 65 +| localematcher.h | enum ULocMatchDemotion::ULOCMATCH_DEMOTION_REGION | (missing) | DraftICU 65 +| localematcher.h | enum ULocMatchFavorSubtag::ULOCMATCH_FAVOR_LANGUAGE | (missing) | DraftICU 65 +| localematcher.h | enum ULocMatchFavorSubtag::ULOCMATCH_FAVOR_SCRIPT | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::Builder::Builder() | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::Builder::Builder(Builder&&) | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::Builder::~Builder() | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::LocaleMatcher(LocaleMatcher&&) | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::Result::Result(Result&&) | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::Result::~Result() | (missing) | DraftICU 65 +| localematcher.h | icu::LocaleMatcher::~LocaleMatcher() | (missing) | DraftICU 65 +| localematcher.h | int32_t icu::LocaleMatcher::Result::getDesiredIndex() const | (missing) | DraftICU 65 +| localematcher.h | int32_t icu::LocaleMatcher::Result::getSupportedIndex() const | (missing) | DraftICU 65 +| locid.h | UBool icu::Locale::ConvertingIterator< Iter, Conv >::hasNext() const override | (missing) | DraftICU 65 +| locid.h | UBool icu::Locale::Iterator::hasNext() const | (missing) | DraftICU 65 +| locid.h | UBool icu::Locale::RangeIterator< Iter >::hasNext() const override | (missing) | DraftICU 65 +| locid.h | const Locale& icu::Locale::ConvertingIterator< Iter, Conv >::next() override | (missing) | DraftICU 65 +| locid.h | const Locale& icu::Locale::Iterator::next() | (missing) | DraftICU 65 +| locid.h | const Locale& icu::Locale::RangeIterator< Iter >::next() override | (missing) | DraftICU 65 +| locid.h | icu::Locale::ConvertingIterator< Iter, Conv >::ConvertingIterator(Iter, Iter, Conv) | (missing) | DraftICU 65 +| locid.h | icu::Locale::Iterator::~Iterator() | (missing) | DraftICU 65 +| locid.h | icu::Locale::RangeIterator< Iter >::RangeIterator(Iter, Iter) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getBar() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getDecade() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getDotPerCentimeter() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getDotPerInch() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getEm() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegapixel() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getPascal() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getPixel() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getPixelPerCentimeter() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getPixelPerInch() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit icu::MeasureUnit::getThermUs() | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createBar(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createDecade(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createDotPerCentimeter(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createDotPerInch(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createEm(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createMegapixel(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPascal(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPixel(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPixelPerCentimeter(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPixelPerInch(UErrorCode&) | (missing) | DraftICU 65 +| measunit.h | static MeasureUnit* icu::MeasureUnit::createThermUs(UErrorCode&) | (missing) | DraftICU 65 +| numberformatter.h | StringClass icu::number::FormattedNumber::toDecimalNumber(UErrorCode&) const | (missing) | DraftICU 65 +| numfmt.h | void* icu::NumberFormat::clone() const | (missing) | StableICU 2.0 +| platform.h | #define UPRV_HAS_ATTRIBUTE | (missing) | Internal +| platform.h | #define UPRV_HAS_BUILTIN | (missing) | Internal +| platform.h | #define UPRV_HAS_CPP_ATTRIBUTE | (missing) | Internal +| platform.h | #define UPRV_HAS_DECLSPEC_ATTRIBUTE | (missing) | Internal +| platform.h | #define UPRV_HAS_EXTENSION | (missing) | Internal +| platform.h | #define UPRV_HAS_FEATURE | (missing) | Internal +| platform.h | #define UPRV_HAS_WARNING | (missing) | Internal +| platform.h | #define U_PF_EMSCRIPTEN | (missing) | Internal +| reldatefmt.h | enum UDateAbsoluteUnit::UDAT_ABSOLUTE_HOUR | (missing) | DraftICU 65 +| reldatefmt.h | enum UDateAbsoluteUnit::UDAT_ABSOLUTE_MINUTE | (missing) | DraftICU 65 +| stringpiece.h | icu::StringPiece::StringPiece(T) | (missing) | DraftICU 65 +| ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | (missing) | DraftICU 65 +| ucharstrie.h | UCharsTrie& icu::UCharsTrie::resetToState64(uint64_t) | (missing) | DraftICU 65 +| ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | (missing) | DraftICU 65 +| uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | (missing) | DraftICU 65 +| uloc.h | enum ULocAvailableType::ULOC_AVAILABLE_COUNT | (missing) | Internal +| uloc.h | enum ULocAvailableType::ULOC_AVAILABLE_DEFAULT | (missing) | DraftICU 65 +| uloc.h | enum ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | (missing) | DraftICU 65 +| uloc.h | enum ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES | (missing) | DraftICU 65 +| umachine.h | #define UPRV_BLOCK_MACRO_BEGIN | (missing) | Internal +| umachine.h | #define UPRV_BLOCK_MACRO_END | (missing) | Internal +| unifilt.h | void* icu::UnicodeFilter::clone() const | (missing) | StableICU 2.4 +| utrace.h | enum UTraceFunctionNumber::UTRACE_RES_DATA_LIMIT | (missing) | Internal +| utrace.h | enum UTraceFunctionNumber::UTRACE_UDATA_BUNDLE | (missing) | DraftICU 65 +| utrace.h | enum UTraceFunctionNumber::UTRACE_UDATA_DATA_FILE | (missing) | DraftICU 65 +| utrace.h | enum UTraceFunctionNumber::UTRACE_UDATA_RESOURCE | (missing) | DraftICU 65 +| utrace.h | enum UTraceFunctionNumber::UTRACE_UDATA_RES_FILE | (missing) | DraftICU 65 +| utrace.h | enum UTraceFunctionNumber::UTRACE_UDATA_START | (missing) | DraftICU 65 + +## Other + +Other existing drafts in ICU 65 + +| File | API | ICU 64 | ICU 65 | +|---|---|---|---| +| currunit.h | icu::CurrencyUnit::CurrencyUnit(StringPiece, UErrorCode&) | DraftICU 64 | +| decimfmt.h | UBool icu::DecimalFormat::isFormatFailIfMoreThanMaxDigits() const | DraftICU 64 | +| decimfmt.h | UBool icu::DecimalFormat::isParseCaseSensitive() const | DraftICU 64 | +| decimfmt.h | UBool icu::DecimalFormat::isParseNoExponent() const | DraftICU 64 | +| decimfmt.h | UBool icu::DecimalFormat::isSignAlwaysShown() const | DraftICU 64 | +| decimfmt.h | const number::LocalizedNumberFormatter* icu::DecimalFormat::toNumberFormatter(UErrorCode&) const | DraftICU 64 | +| decimfmt.h | int32_t icu::DecimalFormat::getMinimumGroupingDigits() const | DraftICU 64 | +| decimfmt.h | void icu::DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool) | DraftICU 64 | +| decimfmt.h | void icu::DecimalFormat::setMinimumGroupingDigits(int32_t) | DraftICU 64 | +| decimfmt.h | void icu::DecimalFormat::setParseCaseSensitive(UBool) | DraftICU 64 | +| decimfmt.h | void icu::DecimalFormat::setParseNoExponent(UBool) | DraftICU 64 | +| decimfmt.h | void icu::DecimalFormat::setSignAlwaysShown(UBool) | DraftICU 64 | +| dtitvfmt.h | Appendable& icu::FormattedDateInterval::appendTo(Appendable&, UErrorCode&) const | DraftICU 64 | +| dtitvfmt.h | FormattedDateInterval icu::DateIntervalFormat::formatToValue(Calendar&, Calendar&, UErrorCode&) const | DraftICU 64 | +| dtitvfmt.h | FormattedDateInterval icu::DateIntervalFormat::formatToValue(const DateInterval&, UErrorCode&) const | DraftICU 64 | +| dtitvfmt.h | FormattedDateInterval& icu::FormattedDateInterval::operator=(FormattedDateInterval&&) | DraftICU 64 | +| dtitvfmt.h | UBool icu::FormattedDateInterval::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const | DraftICU 64 | +| dtitvfmt.h | UnicodeString icu::FormattedDateInterval::toString(UErrorCode&) const | DraftICU 64 | +| dtitvfmt.h | UnicodeString icu::FormattedDateInterval::toTempString(UErrorCode&) const | DraftICU 64 | +| dtitvfmt.h | icu::FormattedDateInterval::FormattedDateInterval() | DraftICU 64 | +| dtitvfmt.h | icu::FormattedDateInterval::FormattedDateInterval(FormattedDateInterval&&) | DraftICU 64 | +| dtitvfmt.h | icu::FormattedDateInterval::~FormattedDateInterval() | DraftICU 64 | +| formattedvalue.h | Appendable& icu::FormattedValue::appendTo(Appendable&, UErrorCode&) const | DraftICU 64 | +| formattedvalue.h | UBool icu::ConstrainedFieldPosition::matchesField(int32_t, int32_t) const | DraftICU 64 | +| formattedvalue.h | UBool icu::FormattedValue::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const | DraftICU 64 | +| formattedvalue.h | UnicodeString icu::FormattedValue::toString(UErrorCode&) const | DraftICU 64 | +| formattedvalue.h | UnicodeString icu::FormattedValue::toTempString(UErrorCode&) const | DraftICU 64 | +| formattedvalue.h | icu::ConstrainedFieldPosition::ConstrainedFieldPosition() | DraftICU 64 | +| formattedvalue.h | icu::ConstrainedFieldPosition::~ConstrainedFieldPosition() | DraftICU 64 | +| formattedvalue.h | icu::FormattedValue::~FormattedValue() | DraftICU 64 | +| formattedvalue.h | int32_t icu::ConstrainedFieldPosition::getCategory() const | DraftICU 64 | +| formattedvalue.h | int32_t icu::ConstrainedFieldPosition::getField() const | DraftICU 64 | +| formattedvalue.h | int32_t icu::ConstrainedFieldPosition::getLimit() const | DraftICU 64 | +| formattedvalue.h | int32_t icu::ConstrainedFieldPosition::getStart() const | DraftICU 64 | +| formattedvalue.h | int64_t icu::ConstrainedFieldPosition::getInt64IterationContext() const | DraftICU 64 | +| formattedvalue.h | void icu::ConstrainedFieldPosition::constrainCategory(int32_t) | DraftICU 64 | +| formattedvalue.h | void icu::ConstrainedFieldPosition::constrainField(int32_t, int32_t) | DraftICU 64 | +| formattedvalue.h | void icu::ConstrainedFieldPosition::reset() | DraftICU 64 | +| formattedvalue.h | void icu::ConstrainedFieldPosition::setInt64IterationContext(int64_t) | DraftICU 64 | +| formattedvalue.h | void icu::ConstrainedFieldPosition::setState(int32_t, int32_t, int32_t, int32_t) | DraftICU 64 | +| listformatter.h | Appendable& icu::FormattedList::appendTo(Appendable&, UErrorCode&) const | DraftICU 64 | +| listformatter.h | FormattedList icu::ListFormatter::formatStringsToValue(const UnicodeString items[], int32_t, UErrorCode&) const | DraftICU 64 | +| listformatter.h | FormattedList& icu::FormattedList::operator=(FormattedList&&) | DraftICU 64 | +| listformatter.h | UBool icu::FormattedList::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const | DraftICU 64 | +| listformatter.h | UnicodeString icu::FormattedList::toString(UErrorCode&) const | DraftICU 64 | +| listformatter.h | UnicodeString icu::FormattedList::toTempString(UErrorCode&) const | DraftICU 64 | +| listformatter.h | UnicodeString& icu::ListFormatter::format(const UnicodeString items[], int32_t, UnicodeString&, FieldPositionIterator*, UErrorCode&) const | DraftICU 63 | +| listformatter.h | icu::FormattedList::FormattedList() | DraftICU 64 | +| listformatter.h | icu::FormattedList::FormattedList(FormattedList&&) | DraftICU 64 | +| listformatter.h | icu::FormattedList::~FormattedList() | DraftICU 64 | +| localebuilder.h | Locale icu::LocaleBuilder::build(UErrorCode&) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::addUnicodeLocaleAttribute(StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::clear() | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::clearExtensions() | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::removeUnicodeLocaleAttribute(StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setExtension(char, StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setLanguage(StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setLanguageTag(StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setLocale(const Locale&) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setRegion(StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setScript(StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setUnicodeLocaleKeyword(StringPiece, StringPiece) | DraftICU 64 | +| localebuilder.h | LocaleBuilder& icu::LocaleBuilder::setVariant(StringPiece) | DraftICU 64 | +| localebuilder.h | icu::LocaleBuilder::LocaleBuilder() | DraftICU 64 | +| localebuilder.h | icu::LocaleBuilder::~LocaleBuilder() | DraftICU 64 | +| localpointer.h | LocalArray<T>& icu::LocalArray< T >::operator=(std::unique_ptr< T[]>&&) | DraftICU 64 | +| localpointer.h | LocalPointer<T>& icu::LocalPointer< T >::operator=(std::unique_ptr< T >&&) | DraftICU 64 | +| localpointer.h | icu::LocalArray< T >::LocalArray(std::unique_ptr< T[]>&&) | DraftICU 64 | +| localpointer.h | icu::LocalArray< T >::operator std::unique_ptr< T[]>() && | DraftICU 64 | +| localpointer.h | icu::LocalPointer< T >::LocalPointer(std::unique_ptr< T >&&) | DraftICU 64 | +| localpointer.h | icu::LocalPointer< T >::operator std::unique_ptr< T >() && | DraftICU 64 | +| measfmt.h | void icu::MeasureFormat::parseObject(const UnicodeString&, Formattable&, ParsePosition&) const | DraftICU 53 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getAcre() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getAcreFoot() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getAmpere() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getArcMinute() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getArcSecond() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getAstronomicalUnit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getAtmosphere() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getBarrel() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getBit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getBritishThermalUnit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getBushel() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getByte() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCalorie() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCarat() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCelsius() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCentiliter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCentimeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCentury() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicCentimeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicFoot() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicInch() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicKilometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicMeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicMile() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCubicYard() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCup() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getCupMetric() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDalton() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDay() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDayPerson() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDeciliter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDecimeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDegree() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getDunam() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getEarthMass() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getElectronvolt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFahrenheit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFathom() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFluidOunce() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFluidOunceImperial() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFoodcalorie() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFoot() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getFurlong() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGForce() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGallon() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGallonImperial() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGenericTemperature() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGigabit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGigabyte() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGigahertz() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGigawatt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getGram() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getHectare() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getHectoliter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getHectopascal() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getHertz() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getHorsepower() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getHour() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getInch() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getInchHg() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getJoule() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKarat() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKelvin() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilobit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilobyte() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilocalorie() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilogram() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilohertz() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilojoule() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilometerPerHour() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilopascal() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilowatt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKilowattHour() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getKnot() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getLightYear() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getLiter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getLiterPer100Kilometers() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getLiterPerKilometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getLux() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegabit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegabyte() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegahertz() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegaliter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegapascal() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMegawatt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMeterPerSecond() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMeterPerSecondSquared() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMetricTon() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMicrogram() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMicrometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMicrosecond() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMile() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilePerGallon() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilePerGallonImperial() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilePerHour() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMileScandinavian() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilliampere() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMillibar() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilligram() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilligramPerDeciliter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilliliter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMillimeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMillimeterOfMercury() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMillimolePerLiter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMillisecond() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMilliwatt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMinute() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMole() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMonth() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getMonthPerson() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getNanometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getNanosecond() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getNauticalMile() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getNewton() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getNewtonMeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getOhm() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getOunce() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getOunceTroy() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getParsec() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPartPerMillion() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPercent() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPermille() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPermyriad() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPetabyte() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPicometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPint() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPintMetric() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPoint() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPound() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPoundFoot() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPoundForce() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getPoundPerSquareInch() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getQuart() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getRadian() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getRevolutionAngle() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSecond() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSolarLuminosity() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSolarMass() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSolarRadius() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareCentimeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareFoot() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareInch() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareKilometer() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareMeter() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareMile() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getSquareYard() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getStone() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getTablespoon() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getTeaspoon() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getTerabit() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getTerabyte() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getTon() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getVolt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getWatt() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getWeek() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getWeekPerson() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getYard() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getYear() | DraftICU 64 | +| measunit.h | static MeasureUnit icu::MeasureUnit::getYearPerson() | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createBarrel(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createBritishThermalUnit(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createDalton(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createDayPerson(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createDunam(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createEarthMass(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createElectronvolt(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createFluidOunceImperial(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createKilopascal(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createMegapascal(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createMole(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createMonthPerson(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createNewton(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createNewtonMeter(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPermyriad(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPoundFoot(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createPoundForce(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createSolarLuminosity(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createSolarMass(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createSolarRadius(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createWeekPerson(UErrorCode&) | DraftICU 64 | +| measunit.h | static MeasureUnit* icu::MeasureUnit::createYearPerson(UErrorCode&) | DraftICU 64 | +| nounit.h | UClassID icu::NoUnit::getDynamicClassID() const | DraftICU 60 | +| nounit.h | icu::NoUnit::NoUnit(const NoUnit&) | DraftICU 60 | +| nounit.h | icu::NoUnit::~NoUnit() | DraftICU 60 | +| nounit.h | static NoUnit icu::NoUnit::base() | DraftICU 60 | +| nounit.h | static NoUnit icu::NoUnit::percent() | DraftICU 60 | +| nounit.h | static NoUnit icu::NoUnit::permille() | DraftICU 60 | +| nounit.h | static UClassID icu::NoUnit::getStaticClassID() | DraftICU 60 | +| nounit.h | void* icu::NoUnit::clone() const | DraftICU 60 | +| numberformatter.h | LocalPointer<Derived> icu::number::NumberFormatterSettings< Derived >::clone() && | DraftICU 64 | +| numberformatter.h | LocalPointer<Derived> icu::number::NumberFormatterSettings< Derived >::clone() const & | DraftICU 64 | +| numberformatter.h | UBool icu::number::FormattedNumber::nextFieldPosition(FieldPosition&, UErrorCode&) const | DraftICU 62 | +| numberformatter.h | UBool icu::number::FormattedNumber::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const | DraftICU 64 | +| numberformatter.h | UnicodeString icu::number::FormattedNumber::toTempString(UErrorCode&) const | DraftICU 64 | +| numberformatter.h | icu::number::FormattedNumber::FormattedNumber() | DraftICU 64 | +| numberformatter.h | static UnlocalizedNumberFormatter icu::number::NumberFormatter::forSkeleton(const UnicodeString&, UParseError&, UErrorCode&) | DraftICU 64 | +| numberformatter.h | void icu::number::FormattedNumber::getAllFieldPositions(FieldPositionIterator&, UErrorCode&) const | DraftICU 62 | +| numberrangeformatter.h | LocalPointer<Derived> icu::number::NumberRangeFormatterSettings< Derived >::clone() && | DraftICU 64 | +| numberrangeformatter.h | LocalPointer<Derived> icu::number::NumberRangeFormatterSettings< Derived >::clone() const & | DraftICU 64 | +| numberrangeformatter.h | UBool icu::number::FormattedNumberRange::nextFieldPosition(FieldPosition&, UErrorCode&) const | DraftICU 63 | +| numberrangeformatter.h | UBool icu::number::FormattedNumberRange::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const | DraftICU 64 | +| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::getFirstDecimal(UErrorCode&) const | DraftICU 63 | +| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::getSecondDecimal(UErrorCode&) const | DraftICU 63 | +| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::toTempString(UErrorCode&) const | DraftICU 64 | +| numberrangeformatter.h | void icu::number::FormattedNumberRange::getAllFieldPositions(FieldPositionIterator&, UErrorCode&) const | DraftICU 63 | +| numfmt.h | enum icu::NumberFormat::EAlignmentFields::kCompactField | DraftICU 64 | +| numfmt.h | enum icu::NumberFormat::EAlignmentFields::kMeasureUnitField | DraftICU 64 | +| plurrule.h | UnicodeString icu::PluralRules::select(const number::FormattedNumber&, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | Appendable& icu::FormattedRelativeDateTime::appendTo(Appendable&, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | FormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatNumericToValue(double, URelativeDateTimeUnit, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | FormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(UDateDirection, UDateAbsoluteUnit, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | FormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(double, UDateDirection, UDateRelativeUnit, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | FormattedRelativeDateTime icu::RelativeDateTimeFormatter::formatToValue(double, URelativeDateTimeUnit, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | FormattedRelativeDateTime& icu::FormattedRelativeDateTime::operator=(FormattedRelativeDateTime&&) | DraftICU 64 | +| reldatefmt.h | UBool icu::FormattedRelativeDateTime::nextPosition(ConstrainedFieldPosition&, UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | UnicodeString icu::FormattedRelativeDateTime::toString(UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | UnicodeString icu::FormattedRelativeDateTime::toTempString(UErrorCode&) const | DraftICU 64 | +| reldatefmt.h | icu::FormattedRelativeDateTime::FormattedRelativeDateTime() | DraftICU 64 | +| reldatefmt.h | icu::FormattedRelativeDateTime::FormattedRelativeDateTime(FormattedRelativeDateTime&&) | DraftICU 64 | +| reldatefmt.h | icu::FormattedRelativeDateTime::~FormattedRelativeDateTime() | DraftICU 64 | +| udateintervalformat.h | UFormattedDateInterval* udtitvfmt_openResult(UErrorCode*) | DraftICU 64 | +| udateintervalformat.h | const UFormattedValue* udtitvfmt_resultAsValue(const UFormattedDateInterval*, UErrorCode*) | DraftICU 64 | +| udateintervalformat.h | void udtitvfmt_closeResult(UFormattedDateInterval*) | DraftICU 64 | +| udateintervalformat.h | void udtitvfmt_formatToResult(const UDateIntervalFormat*, UFormattedDateInterval*, UDate, UDate, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | UBool ucfpos_matchesField(const UConstrainedFieldPosition*, int32_t, int32_t, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | UBool ufmtval_nextPosition(const UFormattedValue*, UConstrainedFieldPosition*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | UConstrainedFieldPosition* ucfpos_open(UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | const UChar* ufmtval_getString(const UFormattedValue*, int32_t*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_DATE_INTERVAL_SPAN | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_DATE | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_LIST_SPAN | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_LIST | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_NUMBER | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_RELATIVE_DATETIME | DraftICU 64 | +| uformattedvalue.h | enum UFieldCategory::UFIELD_CATEGORY_UNDEFINED | DraftICU 64 | +| uformattedvalue.h | int32_t ucfpos_getCategory(const UConstrainedFieldPosition*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | int32_t ucfpos_getField(const UConstrainedFieldPosition*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | int64_t ucfpos_getInt64IterationContext(const UConstrainedFieldPosition*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_close(UConstrainedFieldPosition*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_constrainCategory(UConstrainedFieldPosition*, int32_t, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_constrainField(UConstrainedFieldPosition*, int32_t, int32_t, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_getIndexes(const UConstrainedFieldPosition*, int32_t*, int32_t*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_reset(UConstrainedFieldPosition*, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_setInt64IterationContext(UConstrainedFieldPosition*, int64_t, UErrorCode*) | DraftICU 64 | +| uformattedvalue.h | void ucfpos_setState(UConstrainedFieldPosition*, int32_t, int32_t, int32_t, int32_t, UErrorCode*) | DraftICU 64 | +| ulistformatter.h | UFormattedList* ulistfmt_openResult(UErrorCode*) | DraftICU 64 | +| ulistformatter.h | const UFormattedValue* ulistfmt_resultAsValue(const UFormattedList*, UErrorCode*) | DraftICU 64 | +| ulistformatter.h | enum UListFormatterField::ULISTFMT_ELEMENT_FIELD | DraftICU 63 | +| ulistformatter.h | enum UListFormatterField::ULISTFMT_LITERAL_FIELD | DraftICU 63 | +| ulistformatter.h | void ulistfmt_closeResult(UFormattedList*) | DraftICU 64 | +| ulistformatter.h | void ulistfmt_formatStringsToResult(const UListFormatter*, const UChar* const strings[], const int32_t*, int32_t, UFormattedList*, UErrorCode*) | DraftICU 64 | +| unum.h | enum UNumberFormatAttribute::UNUM_MINIMUM_GROUPING_DIGITS | DraftICU 64 | +| unum.h | enum UNumberFormatAttribute::UNUM_PARSE_CASE_SENSITIVE | DraftICU 64 | +| unum.h | enum UNumberFormatAttribute::UNUM_SIGN_ALWAYS_SHOWN | DraftICU 64 | +| unum.h | enum UNumberFormatFields::UNUM_COMPACT_FIELD | DraftICU 64 | +| unum.h | enum UNumberFormatFields::UNUM_MEASURE_UNIT_FIELD | DraftICU 64 | +| unumberformatter.h | UNumberFormatter* unumf_openForSkeletonAndLocaleWithError(const UChar*, int32_t, const char*, UParseError*, UErrorCode*) | DraftICU 64 | +| unumberformatter.h | const UFormattedValue* unumf_resultAsValue(const UFormattedNumber*, UErrorCode*) | DraftICU 64 | +| upluralrules.h | int32_t uplrules_selectFormatted(const UPluralRules*, const struct UFormattedNumber*, UChar*, int32_t, UErrorCode*) | DraftICU 64 | +| uregex.h | enum URegexpFlag::UREGEX_CANON_EQ | DraftICU 2.4 | +| ureldatefmt.h | UFormattedRelativeDateTime* ureldatefmt_openResult(UErrorCode*) | DraftICU 64 | +| ureldatefmt.h | const UFormattedValue* ureldatefmt_resultAsValue(const UFormattedRelativeDateTime*, UErrorCode*) | DraftICU 64 | +| ureldatefmt.h | enum URelativeDateTimeFormatterField::UDAT_REL_LITERAL_FIELD | DraftICU 64 | +| ureldatefmt.h | enum URelativeDateTimeFormatterField::UDAT_REL_NUMERIC_FIELD | DraftICU 64 | +| ureldatefmt.h | void ureldatefmt_closeResult(UFormattedRelativeDateTime*) | DraftICU 64 | +| ureldatefmt.h | void ureldatefmt_formatNumericToResult(const URelativeDateTimeFormatter*, double, URelativeDateTimeUnit, UFormattedRelativeDateTime*, UErrorCode*) | DraftICU 64 | +| ureldatefmt.h | void ureldatefmt_formatToResult(const URelativeDateTimeFormatter*, double, URelativeDateTimeUnit, UFormattedRelativeDateTime*, UErrorCode*) | DraftICU 64 | + +## Simplifications + +This section shows cases where the signature was "simplified" for the sake of comparison. The simplified form is in bold, followed by + all possible variations in "original" form. + +- **`void* icu::ChoiceFormat::clone() const`** + - `ChoiceFormat* icu::ChoiceFormat::clone() const` + - `Format* icu::ChoiceFormat::clone() const` +- **`void* icu::CompactDecimalFormat::clone() const`** + - `CompactDecimalFormat* icu::CompactDecimalFormat::clone() const U_OVERRIDE` + - `Format* icu::CompactDecimalFormat::clone() const U_OVERRIDE` +- **`void* icu::CurrencyAmount::clone() const`** + - `CurrencyAmount* icu::CurrencyAmount::clone() const` + - `UObject* icu::CurrencyAmount::clone() const` +- **`void* icu::CurrencyUnit::clone() const`** + - `CurrencyUnit* icu::CurrencyUnit::clone() const` + - `UObject* icu::CurrencyUnit::clone() const` +- **`void* icu::DateIntervalFormat::clone() const`** + - `DateIntervalFormat* icu::DateIntervalFormat::clone() const` + - `Format* icu::DateIntervalFormat::clone() const` +- **`void* icu::DecimalFormat::clone() const`** + - `DecimalFormat* icu::DecimalFormat::clone() const U_OVERRIDE` + - `Format* icu::DecimalFormat::clone() const U_OVERRIDE` +- **`void* icu::GregorianCalendar::clone() const`** + - `Calendar* icu::GregorianCalendar::clone() const` + - `GregorianCalendar* icu::GregorianCalendar::clone() const` +- **`void* icu::Measure::clone() const`** + - `Measure* icu::Measure::clone() const` + - `UObject* icu::Measure::clone() const` +- **`void* icu::MeasureFormat::clone() const`** + - `Format* icu::MeasureFormat::clone() const` + - `MeasureFormat* icu::MeasureFormat::clone() const` +- **`void* icu::MeasureUnit::clone() const`** + - `MeasureUnit* icu::MeasureUnit::clone() const` + - `UObject* icu::MeasureUnit::clone() const` +- **`void* icu::MessageFormat::clone() const`** + - `Format* icu::MessageFormat::clone() const` + - `MessageFormat* icu::MessageFormat::clone() const` +- **`void* icu::NoUnit::clone() const`** + - `NoUnit* icu::NoUnit::clone() const` + - `UObject* icu::NoUnit::clone() const` +- **`void* icu::PluralFormat::clone() const`** + - `Format* icu::PluralFormat::clone() const` + - `PluralFormat* icu::PluralFormat::clone() const` +- **`void* icu::RuleBasedBreakIterator::clone() const`** + - `BreakIterator* icu::RuleBasedBreakIterator::clone() const` + - `RuleBasedBreakIterator* icu::RuleBasedBreakIterator::clone() const` +- **`void* icu::RuleBasedBreakIterator::createBufferClone(void*, int32_t&, UErrorCode&)`** + - `BreakIterator* icu::RuleBasedBreakIterator::createBufferClone(void*, int32_t&, UErrorCode&)` + - `RuleBasedBreakIterator* icu::RuleBasedBreakIterator::createBufferClone(void*, int32_t&, UErrorCode&)` +- **`void* icu::RuleBasedCollator::clone() const`** + - `Collator* icu::RuleBasedCollator::clone() const` + - `RuleBasedCollator* icu::RuleBasedCollator::clone() const` +- **`void* icu::RuleBasedNumberFormat::clone() const`** + - `Format* icu::RuleBasedNumberFormat::clone() const` + - `RuleBasedNumberFormat* icu::RuleBasedNumberFormat::clone() const` +- **`void* icu::RuleBasedTimeZone::clone() const`** + - `RuleBasedTimeZone* icu::RuleBasedTimeZone::clone() const` + - `TimeZone* icu::RuleBasedTimeZone::clone() const` +- **`void* icu::SelectFormat::clone() const`** + - `Format* icu::SelectFormat::clone() const` + - `SelectFormat* icu::SelectFormat::clone() const` +- **`void* icu::SimpleDateFormat::clone() const`** + - `Format* icu::SimpleDateFormat::clone() const` + - `SimpleDateFormat* icu::SimpleDateFormat::clone() const` +- **`void* icu::SimpleTimeZone::clone() const`** + - `SimpleTimeZone* icu::SimpleTimeZone::clone() const` + - `TimeZone* icu::SimpleTimeZone::clone() const` +- **`void* icu::StringCharacterIterator::clone() const`** + - `CharacterIterator* icu::StringCharacterIterator::clone() const` + - `StringCharacterIterator* icu::StringCharacterIterator::clone() const` +- **`void* icu::StringSearch::safeClone() const`** + - `SearchIterator* icu::StringSearch::safeClone() const` + - `StringSearch* icu::StringSearch::safeClone() const` +- **`void* icu::TimeUnit::clone() const`** + - `TimeUnit* icu::TimeUnit::clone() const` + - `UObject* icu::TimeUnit::clone() const` +- **`void* icu::TimeUnitAmount::clone() const`** + - `TimeUnitAmount* icu::TimeUnitAmount::clone() const` + - `UObject* icu::TimeUnitAmount::clone() const` +- **`void* icu::TimeUnitFormat::clone() const`** + - `Format* icu::TimeUnitFormat::clone() const` + - `TimeUnitFormat* icu::TimeUnitFormat::clone() const` +- **`void* icu::TimeZoneFormat::clone() const`** + - `Format* icu::TimeZoneFormat::clone() const` + - `TimeZoneFormat* icu::TimeZoneFormat::clone() const` +- **`void* icu::UCharCharacterIterator::clone() const`** + - `CharacterIterator* icu::UCharCharacterIterator::clone() const` + - `UCharCharacterIterator* icu::UCharCharacterIterator::clone() const` +- **`void* icu::UnicodeSet::clone() const`** + - `UnicodeFunctor* icu::UnicodeSet::clone() const` + - `UnicodeSet* icu::UnicodeSet::clone() const` +- **`void* icu::UnicodeSet::cloneAsThawed() const`** + - `UnicodeFunctor* icu::UnicodeSet::cloneAsThawed() const` + - `UnicodeSet* icu::UnicodeSet::cloneAsThawed() const` +- **`void* icu::UnicodeSet::freeze()`** + - `UnicodeFunctor* icu::UnicodeSet::freeze()` + - `UnicodeSet* icu::UnicodeSet::freeze()` +- **`void* icu::UnicodeString::clone() const`** + - `Replaceable* icu::UnicodeString::clone() const` + - `UnicodeString* icu::UnicodeString::clone() const` +- **`void* icu::VTimeZone::clone() const`** + - `TimeZone* icu::VTimeZone::clone() const` + - `VTimeZone* icu::VTimeZone::clone() const` + +## Colophon + +Contents generated by StableAPI tool on Wed Oct 02 10:22:36 PDT 2019 + +Copyright © 2019 and later: Unicode, Inc. and others. +License & terms of use: http://www.unicode.org/copyright.html + \ No newline at end of file diff -Nru icu-64.2/as_is/bomlist.txt icu-65.1/as_is/bomlist.txt --- icu-64.2/as_is/bomlist.txt 2019-04-17 19:42:18.000000000 +0000 +++ icu-65.1/as_is/bomlist.txt 2019-10-03 11:16:44.000000000 +0000 @@ -88,8 +88,8 @@ icu/source/test/testdata/break_rules/line_loose.txt icu/source/test/testdata/break_rules/line_loose_cj.txt icu/source/test/testdata/break_rules/word.txt +icu/source/test/testdata/break_rules/README.md icu/source/test/testdata/break_rules/line.txt -icu/source/test/testdata/break_rules/readme.txt icu/source/test/testdata/break_rules/word_POSIX.txt icu/source/test/testdata/break_rules/sentence.txt icu/source/test/testdata/break_rules/line_normal_cj.txt diff -Nru icu-64.2/debian/changelog icu-65.1/debian/changelog --- icu-64.2/debian/changelog 2019-10-23 09:15:45.000000000 +0000 +++ icu-65.1/debian/changelog 2020-02-21 09:25:09.000000000 +0000 @@ -1,31 +1,64 @@ -icu (64.2-0.1+ubuntu18.04.1+deb.sury.org+1) bionic; urgency=medium +icu (65.1-1+ubuntu18.04.1+deb.sury.org+1) bionic; urgency=medium * No-change backport to bionic - -- Ondřej Surý Wed, 23 Oct 2019 11:15:45 +0200 + -- Ondřej Surý Fri, 21 Feb 2020 10:25:09 +0100 -icu (64.2-0.1) unstable; urgency=medium +icu (65.1-1) experimental; urgency=medium - * Non-maintainer upload - * Add python3-distutils kludge for Debian jessie and stretch - * New upstream version 64.2 - - -- Ondřej Surý Wed, 23 Oct 2019 11:00:39 +0200 - -icu (64.1-0.1) unstable; urgency=medium - - * Non-maintainer upload - * Allow build on Ubuntu Xenial - * Lower the debhelper compat level to v10 - * Add d/gbp.conf for deb.sury.org - * New upstream version 64.1 - * Remove patches merged upstream - * Add Build-Depends on python3 - * Add python3-distutils to Build-Depends - * Run test suite, but don't fail - * Bump SONAME to 64 + * New major upstream release. - -- Ondřej Surý Wed, 10 Apr 2019 08:14:15 +0000 + -- Laszlo Boszormenyi (GCS) Fri, 04 Oct 2019 00:19:19 +0000 + +icu (65.1~rc-1) experimental; urgency=medium + + * New major upstream release candidate version. + * ICU time zone data update for 2019c. + + -- Laszlo Boszormenyi (GCS) Tue, 17 Sep 2019 16:51:06 +0000 + +icu (64.2-4) experimental; urgency=medium + + * Fix big-endian FTBFS. + + -- Laszlo Boszormenyi (GCS) Tue, 10 Sep 2019 20:23:08 +0000 + +icu (64.2-3) experimental; urgency=medium + + * Backport upstream fixes: + - ICU-20558 fix regression in DateTimePatternGenerator, + - ICU-20575 fix broken default locale mapping for C.UTF-8 . + * Disable flaky self-tests to fix FTBFS. + + -- Laszlo Boszormenyi (GCS) Mon, 26 Aug 2019 18:23:05 +0000 + +icu (64.2-2) experimental; urgency=medium + + * Fix build dependencies. + + -- Laszlo Boszormenyi (GCS) Wed, 07 Aug 2019 15:19:46 +0000 + +icu (64.2-1) experimental; urgency=medium + + * New major upstream release. + + -- Laszlo Boszormenyi (GCS) Fri, 26 Jul 2019 19:01:33 +0000 + +icu (63.2-2) unstable; urgency=medium + + * Revert ICU-20250 (ICU 63 UnicodeSet startup performance regression) to + fix ABI break (closes: #929474). + + -- Laszlo Boszormenyi (GCS) Sat, 08 Jun 2019 21:46:51 +0000 + +icu (63.2-1) experimental; urgency=medium + + * New upstream release with Japanese new era "Reiwa" support + (closes: #927933). + * Drop backported ICU-20246 and ICU-20208 fixes as no longer needed. + * Break Chromium versions that not built with this ICU release. + + -- Laszlo Boszormenyi (GCS) Sat, 27 Apr 2019 06:44:54 +0000 icu (63.1-6) unstable; urgency=medium diff -Nru icu-64.2/debian/clean icu-65.1/debian/clean --- icu-64.2/debian/clean 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/clean 2019-10-04 00:19:19.000000000 +0000 @@ -1,3 +1,5 @@ source/config.log source/config/icu-config.1 source/test/letest/letest +source/data/rules.mk +source/test/testdata/rules.mk diff -Nru icu-64.2/debian/control icu-65.1/debian/control --- icu-64.2/debian/control 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/control 2019-10-04 00:19:19.000000000 +0000 @@ -3,30 +3,43 @@ Priority: optional Maintainer: Laszlo Boszormenyi (GCS) Standards-Version: 4.3.0 -Build-Depends: debhelper (>= 10), pkg-config, dh-autoreconf, python3, python3-distutils | python3 (<< 3.6~) +Build-Depends: debhelper (>= 9.20150101), pkg-config, dh-autoreconf, python3-distutils | python3 (<< 3.6~) Build-Depends-Indep: doxygen (>= 1.7.1) Build-Conflicts: clang Homepage: http://www.icu-project.org -Package: libicu64 +Package: libicu65 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: ${misc:Depends}, ${shlibs:Depends} -Breaks: openttd (<< 1.8.0-2~) +Breaks: openttd (<< 1.8.0-2~), libiculx63 (<< 63.1-5) +Replaces: libiculx63 (<< 63.1-5) Description: International Components for Unicode ICU is a C++ and C library that provides robust and full-featured Unicode and locale support. This package contains the runtime libraries for ICU. +#Package: libiculx63 +#Multi-Arch: same +#Architecture: any +#Pre-Depends: ${misc:Pre-Depends} +#Depends: ${misc:Depends}, ${shlibs:Depends} +#Description: International Components for Unicode +# ICU is a C++ and C library that provides robust and full-featured +# Unicode and locale support. This package contains the runtime +# libraries for ICU. +# . +# This package contains the layout engine. +# Package: libicu-dev Section: libdevel Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} -Depends: ${misc:Depends}, libicu64 (= ${binary:Version}), icu-devtools (>= ${binary:Version}), libc6-dev | libc-dev -Replaces: icu-devtools (<< 63.1-1~) -Breaks: icu-devtools (<< 63.1-1~) +Depends: ${misc:Depends}, libicu65 (= ${binary:Version}), icu-devtools (>= ${binary:Version}), libc6-dev | libc-dev +Replaces: icu-devtools (<< 65.1-1~) +Breaks: icu-devtools (<< 65.1-1~) Suggests: icu-doc Description: Development files for International Components for Unicode ICU is a C++ and C library that provides robust and full-featured @@ -39,8 +52,8 @@ Multi-Arch: foreign Pre-Depends: ${misc:Pre-Depends} Depends: ${misc:Depends}, ${shlibs:Depends} -Replaces: libicu-dev (<< ${binary:Version}), icu-tools (<< 63.1-1~) -Breaks: libicu-dev (<< ${binary:Version}), icu-tools (<< 63.1-1~) +Replaces: libicu-dev (<< ${binary:Version}), icu-tools (<< 65.1-1~) +Breaks: libicu-dev (<< ${binary:Version}), icu-tools (<< 65.1-1~) Description: Development utilities for International Components for Unicode ICU is a C++ and C library that provides robust and full-featured Unicode and locale support. This package contains programs used to diff -Nru icu-64.2/debian/copyright icu-65.1/debian/copyright --- icu-64.2/debian/copyright 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/copyright 2019-10-04 00:19:19.000000000 +0000 @@ -14,45 +14,47 @@ ICU License =========== -ICU License - ICU 1.8.1 and later +COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) -COPYRIGHT AND PERMISSION NOTICE +Copyright © 1991-2019 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. -Copyright (c) 1995-2013 International Business Machines Corporation and -others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. ----------------------------------------------------------------------- +--------------------- -All trademarks and registered trademarks mentioned herein are the -property of their respective owners. +Third-Party Software Licenses +This section contains third-party software notices and/or additional +terms for licensed third-party software components included within ICU +libraries. Unicode Data License ==================== diff -Nru icu-64.2/debian/libicu64.install icu-65.1/debian/libicu64.install --- icu-64.2/debian/libicu64.install 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/libicu64.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -usr/lib/*/libicudata.so.* -usr/lib/*/libicui18n.so.* -usr/lib/*/libicuio.so.* -usr/lib/*/libicutest.so.* -usr/lib/*/libicutu.so.* -usr/lib/*/libicuuc.so.* diff -Nru icu-64.2/debian/libicu64.lintian-overrides icu-65.1/debian/libicu64.lintian-overrides --- icu-64.2/debian/libicu64.lintian-overrides 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/libicu64.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -# libicu64 installs multiple shared libraries, none of which is -# actually called libicu.so.64, but all of which are libicu*.so.64. -libicu64: package-name-doesnt-match-sonames libicudata64 libicui18n64 libicuio64 libicutest64 libicutu64 libicuuc64 diff -Nru icu-64.2/debian/libicu64.shlibs icu-65.1/debian/libicu64.shlibs --- icu-64.2/debian/libicu64.shlibs 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/libicu64.shlibs 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -libicudata 64 libicu64 (>= 64.1~) -libicui18n 64 libicu64 (>= 64.1~) -libicuio 64 libicu64 (>= 64.1~) -libicutest 64 libicu64 (>= 64.1~) -libicutu 64 libicu64 (>= 64.1~) -libicuuc 64 libicu64 (>= 64.1~) -#libiculx 64 libicu64 (>= 64.1~) diff -Nru icu-64.2/debian/libicu65.install icu-65.1/debian/libicu65.install --- icu-64.2/debian/libicu65.install 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/libicu65.install 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,6 @@ +usr/lib/*/libicudata.so.* +usr/lib/*/libicui18n.so.* +usr/lib/*/libicuio.so.* +usr/lib/*/libicutest.so.* +usr/lib/*/libicutu.so.* +usr/lib/*/libicuuc.so.* diff -Nru icu-64.2/debian/libicu65.lintian-overrides icu-65.1/debian/libicu65.lintian-overrides --- icu-64.2/debian/libicu65.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/libicu65.lintian-overrides 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,3 @@ +# libicu65 installs multiple shared libraries, none of which is +# actually called libicu.so.65, but all of which are libicu*.so.65. +libicu65: package-name-doesnt-match-sonames libicudata65 libicui18n65 libicuio65 libicutest65 libicutu65 libicuuc65 diff -Nru icu-64.2/debian/libicu65.shlibs icu-65.1/debian/libicu65.shlibs --- icu-64.2/debian/libicu65.shlibs 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/libicu65.shlibs 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,7 @@ +libicudata 65 libicu65 (>= 65.1-1~) +libicui18n 65 libicu65 (>= 65.1-1~) +libicuio 65 libicu65 (>= 65.1-1~) +libicutest 65 libicu65 (>= 65.1-1~) +libicutu 65 libicu65 (>= 65.1-1~) +libicuuc 65 libicu65 (>= 65.1-1~) +#libiculx 65 libicu65 (>= 65.1-1~) diff -Nru icu-64.2/debian/libiculx65.install icu-65.1/debian/libiculx65.install --- icu-64.2/debian/libiculx65.install 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/libiculx65.install 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/*/libiculx.so.* diff -Nru icu-64.2/debian/libiculx65.shlibs icu-65.1/debian/libiculx65.shlibs --- icu-64.2/debian/libiculx65.shlibs 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/libiculx65.shlibs 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1 @@ +libiculx 65 libicu65 (>= 65.1-1~) diff -Nru icu-64.2/debian/patches/0001-icudata-stdlibs.patch icu-65.1/debian/patches/0001-icudata-stdlibs.patch --- icu-64.2/debian/patches/0001-icudata-stdlibs.patch 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/patches/0001-icudata-stdlibs.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -From: "Laszlo Boszormenyi (GCS)" -Date: Wed, 10 Apr 2019 06:42:46 +0000 -Subject: icudata-stdlibs - -=================================================================== ---- - source/config/mh-linux | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/source/config/mh-linux b/source/config/mh-linux -index 53d6780..9be0dca 100644 ---- a/source/config/mh-linux -+++ b/source/config/mh-linux -@@ -23,7 +23,9 @@ LD_RPATH= -Wl,-zorigin,-rpath,'$$'ORIGIN - LD_RPATH_PRE = -Wl,-rpath, - - ## These are the library specific LDFLAGS --LDFLAGSICUDT=-nodefaultlibs -nostdlib -+#LDFLAGSICUDT=-nodefaultlibs -nostdlib -+# Debian change: linking icudata as data only causes too many problems. -+LDFLAGSICUDT= - - ## Compiler switch to embed a library name - # The initial tab in the next line is to prevent icu-config from reading it. diff -Nru icu-64.2/debian/patches/0002-gennorm2-man.patch icu-65.1/debian/patches/0002-gennorm2-man.patch --- icu-64.2/debian/patches/0002-gennorm2-man.patch 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/patches/0002-gennorm2-man.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -From: Jay Berkenbilt -Date: Wed, 10 Apr 2019 06:42:46 +0000 -Subject: supply manual page for program that doesn't have one - -Bug: http://bugs.icu-project.org/trac/ticket/7554 ---- - source/tools/gennorm2/Makefile.in | 20 +++++++++-- - source/tools/gennorm2/gennorm2.8.in | 71 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 88 insertions(+), 3 deletions(-) - create mode 100644 source/tools/gennorm2/gennorm2.8.in - -diff --git a/source/tools/gennorm2/Makefile.in b/source/tools/gennorm2/Makefile.in -index afc3f9b..4af52a8 100644 ---- a/source/tools/gennorm2/Makefile.in -+++ b/source/tools/gennorm2/Makefile.in -@@ -18,8 +18,13 @@ subdir = tools/gennorm2 - - TARGET_STUB_NAME = gennorm2 - -+SECTION = 8 -+ -+MAN_FILES = $(TARGET_STUB_NAME).$(SECTION) -+ -+ - ## Extra files to remove for 'make clean' --CLEANFILES = *~ $(DEPS) -+CLEANFILES = *~ $(DEPS) $(MAN_FILES) - - ## Target information - TARGET = $(BINDIR)/$(TARGET_STUB_NAME)$(EXEEXT) -@@ -46,12 +51,16 @@ distclean : distclean-local - dist: dist-local - check: all check-local - --all-local: $(TARGET) -+all-local: $(TARGET) $(MAN_FILES) - --install-local: all-local -+install-local: all-local install-man - $(MKINSTALLDIRS) $(DESTDIR)$(sbindir) - $(INSTALL) $(TARGET) $(DESTDIR)$(sbindir) - -+install-man: $(MAN_FILES) -+ $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man$(SECTION) -+ $(INSTALL_DATA) $? $(DESTDIR)$(mandir)/man$(SECTION) -+ - dist-local: - - clean-local: -@@ -72,6 +81,11 @@ $(TARGET) : $(OBJECTS) - $(POST_BUILD_STEP) - - -+%.$(SECTION): $(srcdir)/%.$(SECTION).in -+ cd $(top_builddir) \ -+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status -+ -+ - ifeq (,$(MAKECMDGOALS)) - -include $(DEPS) - else -diff --git a/source/tools/gennorm2/gennorm2.8.in b/source/tools/gennorm2/gennorm2.8.in -new file mode 100644 -index 0000000..221f2ee ---- /dev/null -+++ b/source/tools/gennorm2/gennorm2.8.in -@@ -0,0 +1,71 @@ -+.\" Hey, Emacs! This is -*-nroff-*- you know... -+.\" -+.\" gennorm2.8: manual page for the gennorm2 utility -+.\" -+.\" Copyright (C) 2005-2006 International Business Machines Corporation and others -+.\" -+.TH GENNORM2 8 "15 March 2010" "ICU MANPAGE" "ICU @VERSION@ Manual" -+.SH NAME -+.B gennorm2 -+\- Builds binary data file with Unicode normalization data. -+.SH SYNOPSIS -+.B gennorm2 -+[ -+.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" -+] -+[ -+.BR "\-V\fP, \fB\-\-version" -+] -+[ -+.BR "\-c\fP, \fB\-\-copyright" -+] -+[ -+.BR "\-v\fP, \fB\-\-verbose" -+] -+[ -+.BI "\-u\fP, \fB\-\-unicode" " unicode\-version\-number" -+] -+[ -+.BI "\-s\fP, \fB\-\-sourcedir" " source\-directory" -+] -+[ -+.BI "\-o\fP, \fB\-\-output" " output\-filename" -+] -+.BI "\fB\-\-fast" -+.SH DESCRIPTION -+.B gennorm2 -+reads text files that define Unicode normalization, -+them, and builds a binary data file. -+.SH OPTIONS -+.TP -+.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" -+Print help about usage and exit. -+.TP -+.BR "\-V\fP, \fB\-\-version" -+Print the version of -+.B gennorm2 -+and exit. -+.TP -+.BR "\-c\fP, \fB\-\-copyright" -+Include a copyright notice. -+.TP -+.BR "\-v\fP, \fB\-\-verbose" -+Display extra informative messages during execution. -+.TP -+.BR "\-u\fP, \fB\-\-unicode" -+Specify Unicode version number, such as 5.2.0. -+.TP -+.BI "\-s\fP, \fB\-\-sourcedir" " source\-directory" -+Specify the input directory. -+.TP -+.BI "\-s\fP, \fB\-\-sourcedir" " source\-directory" -+Set the name of the output file. -+.TP -+.BI "\fB\-\-fast" -+optimize the .nrm file for fast normalization, -+which might increase its size (Writes fully decomposed -+regular mappings instead of delta mappings. -+You should measure the runtime speed to make sure that -+this is a good trade-off.) -+.SH COPYRIGHT -+Copyright (C) 2009-2010 International Business Machines Corporation and others diff -Nru icu-64.2/debian/patches/0003-icuinfo-man.patch icu-65.1/debian/patches/0003-icuinfo-man.patch --- icu-64.2/debian/patches/0003-icuinfo-man.patch 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/patches/0003-icuinfo-man.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -From: Jay Berkenbilt -Date: Wed, 10 Apr 2019 06:42:46 +0000 -Subject: supply manual page for program that doesn't have one - -Bug: http://bugs.icu-project.org/trac/ticket/7665 ---- - source/tools/icuinfo/Makefile.in | 24 ++++++++++--- - source/tools/icuinfo/icuinfo.1.in | 76 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 96 insertions(+), 4 deletions(-) - create mode 100644 source/tools/icuinfo/icuinfo.1.in - -diff --git a/source/tools/icuinfo/Makefile.in b/source/tools/icuinfo/Makefile.in -index ddbb2ee..50297ba 100644 ---- a/source/tools/icuinfo/Makefile.in -+++ b/source/tools/icuinfo/Makefile.in -@@ -16,8 +16,15 @@ include $(top_builddir)/icudefs.mk - ## Build directory information - subdir = tools/icuinfo - -+TARGET_STUB_NAME = icuinfo -+ -+SECTION = 1 -+ -+MAN_FILES = $(TARGET_STUB_NAME).$(SECTION) -+ -+ - ## Extra files to remove for 'make clean' --CLEANFILES = *~ $(DEPS) $(PLUGIN_OBJECTS) $(PLUGINFILE) $(PLUGIN) -+CLEANFILES = *~ $(DEPS) $(PLUGIN_OBJECTS) $(PLUGINFILE) $(PLUGIN) $(MAN_FILES) - - ## Target information - TARGET = icuinfo$(EXEEXT) -@@ -37,7 +44,8 @@ ICUINFO_OPTS=-i ../../data/out/build/$(ICUDATA_PLATFORM_NAME) -x $(top_builddir) - - ## List of phony targets - .PHONY : all all-local install install-local clean clean-local \ --distclean distclean-local dist dist-local check check-local plugin-check -+distclean distclean-local dist dist-local check check-local plugin-check \ -+install-man - - ## Clear suffix list - .SUFFIXES : -@@ -50,12 +58,16 @@ distclean : distclean-local - dist: dist-local - check: all check-local - --all-local: $(TARGET) -+all-local: $(TARGET) $(MAN_FILES) - --install-local: all-local -+install-local: all-local install-man - $(MKINSTALLDIRS) $(DESTDIR)$(bindir) - $(INSTALL) $(TARGET) $(DESTDIR)$(bindir) - -+install-man: $(MAN_FILES) -+ $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man$(SECTION) -+ $(INSTALL_DATA) $? $(DESTDIR)$(mandir)/man$(SECTION) -+ - dist-local: - - clean-local: -@@ -105,6 +117,10 @@ plugin plugin-check $(PLUGIN): - @echo "Plugins are disabled (use --enable-plugins to enable)" - endif - -+%.$(SECTION): $(srcdir)/%.$(SECTION).in -+ cd $(top_builddir) \ -+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status -+ - ifeq (,$(MAKECMDGOALS)) - -include $(DEPS) - else -diff --git a/source/tools/icuinfo/icuinfo.1.in b/source/tools/icuinfo/icuinfo.1.in -new file mode 100644 -index 0000000..76c5b0c ---- /dev/null -+++ b/source/tools/icuinfo/icuinfo.1.in -@@ -0,0 +1,76 @@ -+.\" Hey, Emacs! This is -*-nroff-*- you know... -+.\" -+.\" icuinfo.1: manual page for the icuinfo utility -+.\" -+.\" Copyright (C) 2005-2006 International Business Machines Corporation and others -+.\" -+.TH ICUINFO 1 "1 May 2010" "ICU MANPAGE" "ICU @VERSION@ Manual" -+.SH NAME -+.B icuinfo -+\- Shows some basic info about the current ICU -+.SH SYNOPSIS -+.B icuinfo -+[ -+.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" -+] -+[ -+.BR "\-V\fP, \fB\-\-version" -+] -+[ -+.BR "\-c\fP, \fB\-\-copyright" -+] -+[ -+.BI "\-i\fP, \fB\-\-icudatadir" " directory" -+] -+[ -+.BR "\-v\fP, \fB\-\-verbose" -+] -+[ -+.BI "\-L\fP, \fB\-\-list-plugins" -+] -+[ -+.BI "\-m\fP, \fB\-\-milisecond-time" -+] -+[ -+.BI "\-K\fP, \fB\-\-cleanup" -+] -+.SH DESCRIPTION -+.B icuinfo -+prints basic information about the current version of ICU. -+.SH OPTIONS -+.TP -+.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" -+Print help about usage and exit. -+.TP -+.BR "\-V\fP, \fB\-\-version" -+Print the version of -+.B icuinfo -+and exit. -+.TP -+.BR "\-c\fP, \fB\-\-copyright" -+Embeds the standard ICU copyright into the -+.IR output-file . -+.TP -+.BR "\-v\fP, \fB\-\-verbose" -+Display extra informative messages during execution. -+.TP -+.BI "\-i\fP, \fB\-\-icudatadir" " directory" -+Look for any necessary ICU data files in -+.IR directory . -+For example, the file -+.B pnames.icu -+must be located when ICU's data is not built as a shared library. -+The default ICU data directory is specified by the environment variable -+.BR ICU_DATA . -+Most configurations of ICU do not require this argument. -+.TP -+.BI "\-L\fP, \fB\-\-list-plugins" -+If specified, list and diagnose issues with ICU plugins. -+.TP -+.BI "\-K\fP, \fB\-\-cleanup" -+Attempt to unload plugins before exiting. -+.TP -+.BI "\-m\fP, \fB\-\-milisecond-time" -+Print the current UTC time in milliseconds. -+.SH COPYRIGHT -+Copyright (C) 2010 International Business Machines Corporation and others diff -Nru icu-64.2/debian/patches/0004-hurd-fix.diff icu-65.1/debian/patches/0004-hurd-fix.diff --- icu-64.2/debian/patches/0004-hurd-fix.diff 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/patches/0004-hurd-fix.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -From: "Laszlo Boszormenyi (GCS)" -Date: Wed, 10 Apr 2019 06:42:46 +0000 -Subject: hurd-fix - ---- - source/tools/toolutil/udbgutil.cpp | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/source/tools/toolutil/udbgutil.cpp b/source/tools/toolutil/udbgutil.cpp -index 285f68a..a0a2e43 100644 ---- a/source/tools/toolutil/udbgutil.cpp -+++ b/source/tools/toolutil/udbgutil.cpp -@@ -367,8 +367,6 @@ U_CAPI const char *udbg_getPlatform(void) - return "Linux"; - #elif U_PLATFORM == U_PF_ANDROID - return "Android"; --#elif U_PLATFORM == U_PF_CLASSIC_MACOS -- return "MacOS (Classic)"; - #elif U_PLATFORM == U_PF_OS390 - return "IBM z"; - #elif U_PLATFORM == U_PF_OS400 diff -Nru icu-64.2/debian/patches/0005-layout-test-fix.patch icu-65.1/debian/patches/0005-layout-test-fix.patch --- icu-64.2/debian/patches/0005-layout-test-fix.patch 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/patches/0005-layout-test-fix.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -From: "Laszlo Boszormenyi (GCS)" -Date: Wed, 10 Apr 2019 06:42:46 +0000 -Subject: update tests to match new Layout Extension - -Forwarded: no -Bug-Debian: https://bugs.debian.org/879820 -Last-Update: 2017-11-04 - -Update glyphs, indices and positions. ---- - source/test/testdata/letest.xml | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/source/test/testdata/letest.xml b/source/test/testdata/letest.xml -index c77eec0..2f90f5c 100644 ---- a/source/test/testdata/letest.xml -+++ b/source/test/testdata/letest.xml -@@ -1016,16 +1016,16 @@ - शङ़ु - - -- 0x00000002, 0x00000001, 0x00000006, 0x0000FFFF -+ 0x00000002, 0x00000001, 0x00000006, 0x0000FFFF, 0x0000FFFF - - - -- 0x00000000, 0x00000001, 0x00000002, 0x00000003 -+ 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000003 - - - -- 0.000000, 0.000000, 7.572000, 0.000000, 15.108000, 0.000000, 15.108000, 0.000000, -- 15.108000, 0.000000 -+ 0.000000, 0.000000, 7.571777, 0.000000, 15.107666, 0.000000, 15.107666, 0.000000, -+ 15.107666, 0.000000, 15.107666, 0.000000 - - - -@@ -1035,16 +1035,16 @@ - शङ़ु - - -- 0x00000005, 0x00000001, 0x00000006, 0x0000FFFF -+ 0x00000005, 0x00000001, 0x00000006, 0x0000FFFF, 0x0000FFFF - - - -- 0x00000000, 0x00000001, 0x00000002, 0x00000003 -+ 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000003 - - - -- 0.000000, 0.000000, 7.392000, 0.000000, 14.927999, 0.000000, 14.927999, 0.000000, -- 14.927999, 0.000000 -+ 0.000000, 0.000000, 7.391846, 0.000000, 14.927734, 0.000000, 14.927734, 0.000000, -+ 14.927734, 0.000000, 14.927734, 0.000000 - - - diff -Nru icu-64.2/debian/patches/flaky-tests.patch icu-65.1/debian/patches/flaky-tests.patch --- icu-64.2/debian/patches/flaky-tests.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/flaky-tests.patch 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,30 @@ +Description: disable flaky tests + These fail on buildds but not on porterboxes (unreproducible ones). +Author: Laszlo Boszormenyi (GCS) +Forwarded: no +Last-Update: 2019-08-26 + +--- + +--- icu-64.2.orig/source/test/cintltst/udatpg_test.c ++++ icu-64.2/source/test/cintltst/udatpg_test.c +@@ -45,7 +45,7 @@ static void TestOptions(void); + static void TestGetFieldDisplayNames(void); + + void addDateTimePatternGeneratorTest(TestNode** root) { +- TESTCASE(TestOpenClose); ++ /* TESTCASE(TestOpenClose); */ + TESTCASE(TestUsage); + TESTCASE(TestBuilder); + TESTCASE(TestOptions); +--- icu-64.2.orig/source/test/intltest/uobjtest.cpp ++++ icu-64.2/source/test/intltest/uobjtest.cpp +@@ -610,7 +610,7 @@ void UObjectTest::runIndexedTest( int32_ + { + switch (index) { + +- TESTCASE(0, testIDs); ++ // TESTCASE(0, testIDs); + TESTCASE(1, testUMemory); + TESTCASE(2, TestMFCCompatibility); + TESTCASE(3, TestCompilerRTTI); diff -Nru icu-64.2/debian/patches/gennorm2-man.patch icu-65.1/debian/patches/gennorm2-man.patch --- icu-64.2/debian/patches/gennorm2-man.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/gennorm2-man.patch 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,130 @@ +Description: supply manual page for program that doesn't have one +Author: Jay Berkenbilt +Bug: http://bugs.icu-project.org/trac/ticket/7554 + +Index: icu-52~m1/source/tools/gennorm2/Makefile.in +=================================================================== +--- icu-52~m1.orig/source/tools/gennorm2/Makefile.in 2013-09-14 18:53:23.432040469 -0400 ++++ icu-52~m1/source/tools/gennorm2/Makefile.in 2013-09-14 18:53:23.428040469 -0400 +@@ -16,8 +16,13 @@ + + TARGET_STUB_NAME = gennorm2 + ++SECTION = 8 ++ ++MAN_FILES = $(TARGET_STUB_NAME).$(SECTION) ++ ++ + ## Extra files to remove for 'make clean' +-CLEANFILES = *~ $(DEPS) ++CLEANFILES = *~ $(DEPS) $(MAN_FILES) + + ## Target information + TARGET = $(BINDIR)/$(TARGET_STUB_NAME)$(EXEEXT) +@@ -44,12 +49,16 @@ + dist: dist-local + check: all check-local + +-all-local: $(TARGET) ++all-local: $(TARGET) $(MAN_FILES) + +-install-local: all-local ++install-local: all-local install-man + $(MKINSTALLDIRS) $(DESTDIR)$(sbindir) + $(INSTALL) $(TARGET) $(DESTDIR)$(sbindir) + ++install-man: $(MAN_FILES) ++ $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man$(SECTION) ++ $(INSTALL_DATA) $? $(DESTDIR)$(mandir)/man$(SECTION) ++ + dist-local: + + clean-local: +@@ -70,6 +79,11 @@ + $(POST_BUILD_STEP) + + ++%.$(SECTION): $(srcdir)/%.$(SECTION).in ++ cd $(top_builddir) \ ++ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status ++ ++ + ifeq (,$(MAKECMDGOALS)) + -include $(DEPS) + else +Index: icu-52~m1/source/tools/gennorm2/gennorm2.8.in +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ icu-52~m1/source/tools/gennorm2/gennorm2.8.in 2013-09-14 18:53:23.428040469 -0400 +@@ -0,0 +1,71 @@ ++.\" Hey, Emacs! This is -*-nroff-*- you know... ++.\" ++.\" gennorm2.8: manual page for the gennorm2 utility ++.\" ++.\" Copyright (C) 2005-2006 International Business Machines Corporation and others ++.\" ++.TH GENNORM2 8 "15 March 2010" "ICU MANPAGE" "ICU @VERSION@ Manual" ++.SH NAME ++.B gennorm2 ++\- Builds binary data file with Unicode normalization data. ++.SH SYNOPSIS ++.B gennorm2 ++[ ++.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" ++] ++[ ++.BR "\-V\fP, \fB\-\-version" ++] ++[ ++.BR "\-c\fP, \fB\-\-copyright" ++] ++[ ++.BR "\-v\fP, \fB\-\-verbose" ++] ++[ ++.BI "\-u\fP, \fB\-\-unicode" " unicode\-version\-number" ++] ++[ ++.BI "\-s\fP, \fB\-\-sourcedir" " source\-directory" ++] ++[ ++.BI "\-o\fP, \fB\-\-output" " output\-filename" ++] ++.BI "\fB\-\-fast" ++.SH DESCRIPTION ++.B gennorm2 ++reads text files that define Unicode normalization, ++them, and builds a binary data file. ++.SH OPTIONS ++.TP ++.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" ++Print help about usage and exit. ++.TP ++.BR "\-V\fP, \fB\-\-version" ++Print the version of ++.B gennorm2 ++and exit. ++.TP ++.BR "\-c\fP, \fB\-\-copyright" ++Include a copyright notice. ++.TP ++.BR "\-v\fP, \fB\-\-verbose" ++Display extra informative messages during execution. ++.TP ++.BR "\-u\fP, \fB\-\-unicode" ++Specify Unicode version number, such as 5.2.0. ++.TP ++.BI "\-s\fP, \fB\-\-sourcedir" " source\-directory" ++Specify the input directory. ++.TP ++.BI "\-s\fP, \fB\-\-sourcedir" " source\-directory" ++Set the name of the output file. ++.TP ++.BI "\fB\-\-fast" ++optimize the .nrm file for fast normalization, ++which might increase its size (Writes fully decomposed ++regular mappings instead of delta mappings. ++You should measure the runtime speed to make sure that ++this is a good trade-off.) ++.SH COPYRIGHT ++Copyright (C) 2009-2010 International Business Machines Corporation and others diff -Nru icu-64.2/debian/patches/hurd-fix.diff icu-65.1/debian/patches/hurd-fix.diff --- icu-64.2/debian/patches/hurd-fix.diff 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/hurd-fix.diff 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,11 @@ +--- ./source/tools/toolutil/udbgutil.cpp.orig 2015-08-03 11:53:13.788781812 +0200 ++++ ./source/tools/toolutil/udbgutil.cpp 2015-08-03 11:53:14.736758140 +0200 +@@ -366,8 +366,6 @@ + return "Linux"; + #elif U_PLATFORM == U_PF_ANDROID + return "Android"; +-#elif U_PLATFORM == U_PF_CLASSIC_MACOS +- return "MacOS (Classic)"; + #elif U_PLATFORM == U_PF_OS390 + return "IBM z"; + #elif U_PLATFORM == U_PF_OS400 diff -Nru icu-64.2/debian/patches/icu-64.1-data_archive_generation.patch icu-65.1/debian/patches/icu-64.1-data_archive_generation.patch --- icu-64.2/debian/patches/icu-64.1-data_archive_generation.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/icu-64.1-data_archive_generation.patch 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,14 @@ +https://bugs.gentoo.org/682170 + +--- a/source/data/Makefile.in ++++ b/source/data/Makefile.in +@@ -148,7 +148,8 @@ + # and convert it to the current type. + ifneq ($(ICUDATA_ARCHIVE),) + ICUDATA_SOURCE_ARCHIVE = $(OUTDIR)/$(ICUDATA_PLATFORM_NAME).dat +-$(ICUDATA_SOURCE_ARCHIVE): $(ICUDATA_ARCHIVE) $(OUTDIR) ++$(ICUDATA_SOURCE_ARCHIVE): $(ICUDATA_ARCHIVE) ++ $(MKINSTALLDIRS) $(OUTDIR) + $(INVOKE) $(TOOLBINDIR)/icupkg -t$(ICUDATA_CHAR) $(ICUDATA_ARCHIVE) $(ICUDATA_SOURCE_ARCHIVE) + endif + else diff -Nru icu-64.2/debian/patches/icudata-stdlibs.patch icu-65.1/debian/patches/icudata-stdlibs.patch --- icu-64.2/debian/patches/icudata-stdlibs.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/icudata-stdlibs.patch 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,15 @@ +Index: icu-52~m1/source/config/mh-linux +=================================================================== +--- icu-52~m1.orig/source/config/mh-linux 2013-09-14 18:53:23.284040467 -0400 ++++ icu-52~m1/source/config/mh-linux 2013-09-14 18:53:23.284040467 -0400 +@@ -21,7 +21,9 @@ + LD_RPATH_PRE = -Wl,-rpath, + + ## These are the library specific LDFLAGS +-LDFLAGSICUDT=-nodefaultlibs -nostdlib ++#LDFLAGSICUDT=-nodefaultlibs -nostdlib ++# Debian change: linking icudata as data only causes too many problems. ++LDFLAGSICUDT= + + ## Compiler switch to embed a library name + # The initial tab in the next line is to prevent icu-config from reading it. diff -Nru icu-64.2/debian/patches/icuinfo-man.patch icu-65.1/debian/patches/icuinfo-man.patch --- icu-64.2/debian/patches/icuinfo-man.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/icuinfo-man.patch 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,146 @@ +Description: supply manual page for program that doesn't have one +Author: Jay Berkenbilt +Bug: http://bugs.icu-project.org/trac/ticket/7665 + +Index: icu-52~m1/source/tools/icuinfo/Makefile.in +=================================================================== +--- icu-52~m1.orig/source/tools/icuinfo/Makefile.in 2013-09-14 18:53:23.552040471 -0400 ++++ icu-52~m1/source/tools/icuinfo/Makefile.in 2013-09-14 18:53:23.544040471 -0400 +@@ -14,8 +14,15 @@ + ## Build directory information + subdir = tools/icuinfo + ++TARGET_STUB_NAME = icuinfo ++ ++SECTION = 1 ++ ++MAN_FILES = $(TARGET_STUB_NAME).$(SECTION) ++ ++ + ## Extra files to remove for 'make clean' +-CLEANFILES = *~ $(DEPS) $(PLUGIN_OBJECTS) $(PLUGINFILE) $(PLUGIN) ++CLEANFILES = *~ $(DEPS) $(PLUGIN_OBJECTS) $(PLUGINFILE) $(PLUGIN) $(MAN_FILES) + + ## Target information + TARGET = icuinfo$(EXEEXT) +@@ -35,7 +42,8 @@ + + ## List of phony targets + .PHONY : all all-local install install-local clean clean-local \ +-distclean distclean-local dist dist-local check check-local plugin-check ++distclean distclean-local dist dist-local check check-local plugin-check \ ++install-man + + ## Clear suffix list + .SUFFIXES : +@@ -48,12 +56,16 @@ + dist: dist-local + check: all check-local + +-all-local: $(TARGET) ++all-local: $(TARGET) $(MAN_FILES) + +-install-local: all-local ++install-local: all-local install-man + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) + $(INSTALL) $(TARGET) $(DESTDIR)$(bindir) + ++install-man: $(MAN_FILES) ++ $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man$(SECTION) ++ $(INSTALL_DATA) $? $(DESTDIR)$(mandir)/man$(SECTION) ++ + dist-local: + + clean-local: +@@ -103,6 +115,10 @@ plugin plugin-check $(PLUGIN): + @echo "Plugins are disabled (use --enable-plugins to enable)" + endif + ++%.$(SECTION): $(srcdir)/%.$(SECTION).in ++ cd $(top_builddir) \ ++ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status ++ + ifeq (,$(MAKECMDGOALS)) + -include $(DEPS) + else +Index: icu-52~m1/source/tools/icuinfo/icuinfo.1.in +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ icu-52~m1/source/tools/icuinfo/icuinfo.1.in 2013-09-14 18:53:23.552040471 -0400 +@@ -0,0 +1,76 @@ ++.\" Hey, Emacs! This is -*-nroff-*- you know... ++.\" ++.\" icuinfo.1: manual page for the icuinfo utility ++.\" ++.\" Copyright (C) 2005-2006 International Business Machines Corporation and others ++.\" ++.TH ICUINFO 1 "1 May 2010" "ICU MANPAGE" "ICU @VERSION@ Manual" ++.SH NAME ++.B icuinfo ++\- Shows some basic info about the current ICU ++.SH SYNOPSIS ++.B icuinfo ++[ ++.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" ++] ++[ ++.BR "\-V\fP, \fB\-\-version" ++] ++[ ++.BR "\-c\fP, \fB\-\-copyright" ++] ++[ ++.BI "\-i\fP, \fB\-\-icudatadir" " directory" ++] ++[ ++.BR "\-v\fP, \fB\-\-verbose" ++] ++[ ++.BI "\-L\fP, \fB\-\-list-plugins" ++] ++[ ++.BI "\-m\fP, \fB\-\-milisecond-time" ++] ++[ ++.BI "\-K\fP, \fB\-\-cleanup" ++] ++.SH DESCRIPTION ++.B icuinfo ++prints basic information about the current version of ICU. ++.SH OPTIONS ++.TP ++.BR "\-h\fP, \fB\-?\fP, \fB\-\-help" ++Print help about usage and exit. ++.TP ++.BR "\-V\fP, \fB\-\-version" ++Print the version of ++.B icuinfo ++and exit. ++.TP ++.BR "\-c\fP, \fB\-\-copyright" ++Embeds the standard ICU copyright into the ++.IR output-file . ++.TP ++.BR "\-v\fP, \fB\-\-verbose" ++Display extra informative messages during execution. ++.TP ++.BI "\-i\fP, \fB\-\-icudatadir" " directory" ++Look for any necessary ICU data files in ++.IR directory . ++For example, the file ++.B pnames.icu ++must be located when ICU's data is not built as a shared library. ++The default ICU data directory is specified by the environment variable ++.BR ICU_DATA . ++Most configurations of ICU do not require this argument. ++.TP ++.BI "\-L\fP, \fB\-\-list-plugins" ++If specified, list and diagnose issues with ICU plugins. ++.TP ++.BI "\-K\fP, \fB\-\-cleanup" ++Attempt to unload plugins before exiting. ++.TP ++.BI "\-m\fP, \fB\-\-milisecond-time" ++Print the current UTC time in milliseconds. ++.SH COPYRIGHT ++Copyright (C) 2010 International Business Machines Corporation and others diff -Nru icu-64.2/debian/patches/layout-test-fix.patch icu-65.1/debian/patches/layout-test-fix.patch --- icu-64.2/debian/patches/layout-test-fix.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/debian/patches/layout-test-fix.patch 2019-10-04 00:19:19.000000000 +0000 @@ -0,0 +1,53 @@ +Description: update tests to match new Layout Extension + Update glyphs, indices and positions. +Forwarded: no +Author: Laszlo Boszormenyi (GCS) +Bug-Debian: https://bugs.debian.org/879820 +Last-Update: 2017-11-04 + +--- + +--- icu-60.1.orig/source/test/testdata/letest.xml ++++ icu-60.1/source/test/testdata/letest.xml +@@ -1016,16 +1016,16 @@ + शङ़ु + + +- 0x00000002, 0x00000001, 0x00000006, 0x0000FFFF ++ 0x00000002, 0x00000001, 0x00000006, 0x0000FFFF, 0x0000FFFF + + + +- 0x00000000, 0x00000001, 0x00000002, 0x00000003 ++ 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000003 + + + +- 0.000000, 0.000000, 7.572000, 0.000000, 15.108000, 0.000000, 15.108000, 0.000000, +- 15.108000, 0.000000 ++ 0.000000, 0.000000, 7.571777, 0.000000, 15.107666, 0.000000, 15.107666, 0.000000, ++ 15.107666, 0.000000, 15.107666, 0.000000 + + + +@@ -1035,16 +1035,16 @@ + शङ़ु + + +- 0x00000005, 0x00000001, 0x00000006, 0x0000FFFF ++ 0x00000005, 0x00000001, 0x00000006, 0x0000FFFF, 0x0000FFFF + + + +- 0x00000000, 0x00000001, 0x00000002, 0x00000003 ++ 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000003 + + + +- 0.000000, 0.000000, 7.392000, 0.000000, 14.927999, 0.000000, 14.927999, 0.000000, +- 14.927999, 0.000000 ++ 0.000000, 0.000000, 7.391846, 0.000000, 14.927734, 0.000000, 14.927734, 0.000000, ++ 14.927734, 0.000000, 14.927734, 0.000000 + + + diff -Nru icu-64.2/debian/patches/series icu-65.1/debian/patches/series --- icu-64.2/debian/patches/series 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/patches/series 2019-10-04 00:19:19.000000000 +0000 @@ -1,5 +1,7 @@ -0001-icudata-stdlibs.patch -0002-gennorm2-man.patch -0003-icuinfo-man.patch -0004-hurd-fix.diff -0005-layout-test-fix.patch +icudata-stdlibs.patch +gennorm2-man.patch +icuinfo-man.patch +hurd-fix.diff +layout-test-fix.patch +flaky-tests.patch +icu-64.1-data_archive_generation.patch diff -Nru icu-64.2/debian/rules icu-65.1/debian/rules --- icu-64.2/debian/rules 2019-10-23 09:00:39.000000000 +0000 +++ icu-65.1/debian/rules 2019-10-04 00:19:19.000000000 +0000 @@ -11,7 +11,7 @@ DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/buildflags.mk -l_SONAME=64 +l_SONAME=65 override_dh_auto_clean: dh_auto_clean --no-parallel @@ -61,7 +61,7 @@ dh_missing --list-missing %: - dh $@ --with autoreconf --sourcedirectory=$(CURDIR)/source/ + dh $@ --sourcedirectory=$(CURDIR)/source/ .PHONY: override_dh_auto_clean override_dh_clean override_dh_auto_configure \ override_dh_auto_build override_dh_auto_test \ diff -Nru icu-64.2/packaging/distrelease.ps1 icu-65.1/packaging/distrelease.ps1 --- icu-64.2/packaging/distrelease.ps1 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/packaging/distrelease.ps1 2019-10-03 11:16:41.000000000 +0000 @@ -13,7 +13,7 @@ # (bring up Powershell ISE) # cd C:\icu\icu4c\ # Set-ExecutionPolicy -Scope Process Unrestricted -# .\packaging\distrelease.ps1 +# .\packaging\distrelease.ps1 -arch "x64 or x86 or ARM64" # # Will emit: c:\icu4c\icu\source\dist\icu-windows.zip # @@ -22,6 +22,9 @@ # see https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-5.1&viewFallbackFrom=powershell-Microsoft.PowerShell.Core # for more about execution policies. +Param( + [string]$arch = "x64" # use x64 as default +) $icuDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $icuDir = Resolve-Path -Path '$icuDir\..' @@ -35,11 +38,30 @@ New-Item -Path $source -ItemType "directory" -ErrorAction SilentlyContinue # copy required stuff -Copy-Item -Path "$icuDir\lib" -Destination $source -Recurse -Copy-Item -Path "$icuDir\lib64" -Destination $source -Recurse +if ($arch -eq "x64") +{ + Copy-Item -Path "$icuDir\lib64" -Destination $source -Recurse + Copy-Item -Path "$icuDir\bin64" -Destination $source -Recurse +} +elseif ($arch -eq "x86") +{ + Copy-Item -Path "$icuDir\lib" -Destination $source -Recurse + Copy-Item -Path "$icuDir\bin" -Destination $source -Recurse +} +elseif ($arch -eq "ARM64") +{ + Copy-Item -Path "$icuDir\libARM64" -Destination $source -Recurse + Copy-Item -Path "$icuDir\binARM64" -Destination $source -Recurse +} +else +{ + $filename = $MyInvocation.MyCommand.Name; + echo "Invalid architecture." + echo "Usage: $filename -arch `"x64 or x86`"" + exit +} + Copy-Item -Path "$icuDir\include" -Destination $source -Recurse -Copy-Item -Path "$icuDir\bin" -Destination $source -Recurse -Copy-Item -Path "$icuDir\bin64" -Destination $source -Recurse Copy-Item -Path "$icuDir\APIChangeReport.html" -Destination $source -Recurse Copy-Item -Path "$icuDir\icu4c.css" -Destination $source -Recurse Copy-Item -Path "$icuDir\LICENSE" -Destination $source -Recurse @@ -48,9 +70,14 @@ $destination = "$icuDir\source\dist\icu-windows.zip" Remove-Item -Path $destination -ErrorAction Continue -Add-Type -assembly "system.io.compression.filesystem" Echo $source Echo $destination -[io.compression.zipfile]::CreateFromDirectory($source, $destination) + +# Use 7Zip to build zip file to avoid backslash path separator errors when unzipping on CygWin +if (-not (Get-Module -ListAvailable -Name 7Zip4PowerShell)) +{ + Install-Module 7Zip4PowerShell -Force -Verbose +} +Compress-7Zip $source -ArchiveFileName $destination -Format Zip echo $destination \ No newline at end of file diff -Nru icu-64.2/readme.html icu-65.1/readme.html --- icu-64.2/readme.html 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/readme.html 2019-10-03 11:16:41.000000000 +0000 @@ -3,7 +3,7 @@ - ReadMe for ICU 64.2 + ReadMe for ICU 65.1 @@ -44,7 +44,7 @@

This is a release candidate version of ICU4C. It is not recommended for production use.

-

Last updated: 2019-Apr-04
+

Last updated: 2019-Sept-16
Copyright © 2016 and later: Unicode, Inc. and others. License & terms of use: http://www.unicode.org/copyright.html
Copyright © 1997-2016 International Business Machines Corporation and others. @@ -233,7 +233,7 @@

What Is New In This Release?

-

See the ICU 64 download page +

See the ICU 65 download page for an overview of this release, important changes, new features, bug fixes, known issues, changes to supported platforms and build environments, and migration issues for existing applications migrating from previous ICU releases.

@@ -744,7 +744,8 @@ across library and compiler versions is very hard to achieve. Most ICU C++ APIs are in header files that contain a comment with \brief C++ API. - Consider not installing these header files. + Consider not installing these header files, or define U_SHOW_CPLUSPLUS_API + to be 0 by modifying unicode/utypes.h before installing it.
  • Disable renaming: By default, ICU library entry point names have an ICU version suffix. Turn this off for a system-level installation, to enable upgrading ICU without breaking applications. For example:
    diff -Nru icu-64.2/source/aclocal.m4 icu-65.1/source/aclocal.m4 --- icu-64.2/source/aclocal.m4 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/aclocal.m4 2019-10-03 11:16:41.000000000 +0000 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -13,7 +13,7 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -dnl serial 11 (pkg-config-0.29.1) +dnl serial 11 (pkg-config-0.29) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson @@ -55,7 +55,7 @@ dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29.1]) +[m4_define([PKG_MACROS_VERSION], [0.29]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ diff -Nru icu-64.2/source/allinone/allinone.sln icu-65.1/source/allinone/allinone.sln --- icu-64.2/source/allinone/allinone.sln 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/allinone/allinone.sln 2019-10-03 11:16:41.000000000 +0000 @@ -197,335 +197,515 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Debug|ARM.ActiveCfg = Debug|Win32 + {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Debug|ARM64.ActiveCfg = Debug|Win32 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Debug|Win32.ActiveCfg = Debug|Win32 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Debug|Win32.Build.0 = Debug|Win32 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Debug|x64.ActiveCfg = Debug|x64 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Debug|x64.Build.0 = Debug|x64 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Release|ARM.ActiveCfg = Release|Win32 + {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Release|ARM64.ActiveCfg = Release|Win32 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Release|Win32.ActiveCfg = Release|Win32 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Release|Win32.Build.0 = Release|Win32 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Release|x64.ActiveCfg = Release|x64 {F7659D77-09CF-4FE9-ACEE-927287AA9509}.Release|x64.Build.0 = Release|x64 - {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|ARM.ActiveCfg = Debug|Win32 + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|ARM.ActiveCfg = Debug|ARM + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|ARM.Build.0 = Debug|ARM + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|ARM64.Build.0 = Debug|ARM64 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|Win32.ActiveCfg = Debug|Win32 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|Win32.Build.0 = Debug|Win32 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|x64.ActiveCfg = Debug|x64 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Debug|x64.Build.0 = Debug|x64 - {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|ARM.ActiveCfg = Release|Win32 + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|ARM.ActiveCfg = Release|ARM + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|ARM.Build.0 = Release|ARM + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|ARM64.ActiveCfg = Release|ARM64 + {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|ARM64.Build.0 = Release|ARM64 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|Win32.ActiveCfg = Release|Win32 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|Win32.Build.0 = Release|Win32 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|x64.ActiveCfg = Release|x64 {3D1246AE-1B32-479B-BECA-AEFA97BE2321}.Release|x64.Build.0 = Release|x64 - {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|ARM.ActiveCfg = Debug|Win32 + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|ARM.ActiveCfg = Debug|ARM + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|ARM.Build.0 = Debug|ARM + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|ARM64.Build.0 = Debug|ARM64 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|Win32.ActiveCfg = Debug|Win32 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|Win32.Build.0 = Debug|Win32 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|x64.ActiveCfg = Debug|x64 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Debug|x64.Build.0 = Debug|x64 - {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|ARM.ActiveCfg = Release|Win32 + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|ARM.ActiveCfg = Release|ARM + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|ARM.Build.0 = Release|ARM + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|ARM64.ActiveCfg = Release|ARM64 + {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|ARM64.Build.0 = Release|ARM64 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|Win32.ActiveCfg = Release|Win32 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|Win32.Build.0 = Release|Win32 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|x64.ActiveCfg = Release|x64 {73C0A65B-D1F2-4DE1-B3A6-15DAD2C23F3D}.Release|x64.Build.0 = Release|x64 - {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|ARM.ActiveCfg = Debug|Win32 + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|ARM.ActiveCfg = Debug|ARM + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|ARM.Build.0 = Debug|ARM + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|ARM64.Build.0 = Debug|ARM64 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|Win32.ActiveCfg = Debug|Win32 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|Win32.Build.0 = Debug|Win32 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|x64.ActiveCfg = Debug|x64 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Debug|x64.Build.0 = Debug|x64 - {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|ARM.ActiveCfg = Release|Win32 + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|ARM.ActiveCfg = Release|ARM + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|ARM.Build.0 = Release|ARM + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|ARM64.ActiveCfg = Release|ARM64 + {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|ARM64.Build.0 = Release|ARM64 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|Win32.ActiveCfg = Release|Win32 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|Win32.Build.0 = Release|Win32 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|x64.ActiveCfg = Release|x64 {ECA6B435-B4FA-4F9F-BF95-F451D078FC47}.Release|x64.Build.0 = Release|x64 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Debug|ARM.ActiveCfg = Debug|Win32 + {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Debug|ARM64.ActiveCfg = Debug|Win32 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Debug|Win32.ActiveCfg = Debug|Win32 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Debug|Win32.Build.0 = Debug|Win32 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Debug|x64.ActiveCfg = Debug|x64 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Debug|x64.Build.0 = Debug|x64 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Release|ARM.ActiveCfg = Release|Win32 + {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Release|ARM64.ActiveCfg = Release|Win32 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Release|Win32.ActiveCfg = Release|Win32 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Release|Win32.Build.0 = Release|Win32 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Release|x64.ActiveCfg = Release|x64 {38B5751A-C6F9-4409-950C-F4F9DA17275F}.Release|x64.Build.0 = Release|x64 - {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|ARM.ActiveCfg = Debug|Win32 + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|ARM.ActiveCfg = Debug|ARM + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|ARM.Build.0 = Debug|ARM + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|ARM64.Build.0 = Debug|ARM64 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|Win32.ActiveCfg = Debug|Win32 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|Win32.Build.0 = Debug|Win32 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|x64.ActiveCfg = Debug|x64 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Debug|x64.Build.0 = Debug|x64 - {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|ARM.ActiveCfg = Release|Win32 + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|ARM.ActiveCfg = Release|ARM + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|ARM.Build.0 = Release|ARM + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|ARM64.ActiveCfg = Release|ARM64 + {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|ARM64.Build.0 = Release|ARM64 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|Win32.ActiveCfg = Release|Win32 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|Win32.Build.0 = Release|Win32 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|x64.ActiveCfg = Release|x64 {D3065ADB-8820-4CC7-9B6C-9510833961A3}.Release|x64.Build.0 = Release|x64 - {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|ARM.ActiveCfg = Debug|Win32 + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|ARM.ActiveCfg = Debug|ARM + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|ARM.Build.0 = Debug|ARM + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|ARM64.Build.0 = Debug|ARM64 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|Win32.ActiveCfg = Debug|Win32 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|Win32.Build.0 = Debug|Win32 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|x64.ActiveCfg = Debug|x64 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Debug|x64.Build.0 = Debug|x64 - {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|ARM.ActiveCfg = Release|Win32 + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|ARM.ActiveCfg = Release|ARM + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|ARM.Build.0 = Release|ARM + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|ARM64.ActiveCfg = Release|ARM64 + {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|ARM64.Build.0 = Release|ARM64 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|Win32.ActiveCfg = Release|Win32 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|Win32.Build.0 = Release|Win32 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|x64.ActiveCfg = Release|x64 {C2BE5000-7501-4E87-9724-B8D82494FAE6}.Release|x64.Build.0 = Release|x64 - {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|ARM.ActiveCfg = Debug|Win32 + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|ARM.ActiveCfg = Debug|ARM + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|ARM.Build.0 = Debug|ARM + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|ARM64.Build.0 = Debug|ARM64 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|Win32.ActiveCfg = Debug|Win32 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|Win32.Build.0 = Debug|Win32 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|x64.ActiveCfg = Debug|x64 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Debug|x64.Build.0 = Debug|x64 - {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|ARM.ActiveCfg = Release|Win32 + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|ARM.ActiveCfg = Release|ARM + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|ARM.Build.0 = Release|ARM + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|ARM64.ActiveCfg = Release|ARM64 + {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|ARM64.Build.0 = Release|ARM64 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|Win32.ActiveCfg = Release|Win32 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|Win32.Build.0 = Release|Win32 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|x64.ActiveCfg = Release|x64 {FDD3C4F2-9805-44EB-9A77-BC1C1C95B547}.Release|x64.Build.0 = Release|x64 - {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|ARM.ActiveCfg = Debug|Win32 + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|ARM.ActiveCfg = Debug|ARM + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|ARM.Build.0 = Debug|ARM + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|ARM64.Build.0 = Debug|ARM64 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|Win32.ActiveCfg = Debug|Win32 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|Win32.Build.0 = Debug|Win32 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|x64.ActiveCfg = Debug|x64 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Debug|x64.Build.0 = Debug|x64 - {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|ARM.ActiveCfg = Release|Win32 + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|ARM.ActiveCfg = Release|ARM + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|ARM.Build.0 = Release|ARM + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|ARM64.ActiveCfg = Release|ARM64 + {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|ARM64.Build.0 = Release|ARM64 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|Win32.ActiveCfg = Release|Win32 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|Win32.Build.0 = Release|Win32 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|x64.ActiveCfg = Release|x64 {A8D36F8D-09E6-4174-91C3-7BEAA9C3F04F}.Release|x64.Build.0 = Release|x64 - {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|ARM.ActiveCfg = Debug|Win32 + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|ARM.ActiveCfg = Debug|ARM + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|ARM.Build.0 = Debug|ARM + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|ARM64.Build.0 = Debug|ARM64 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|Win32.ActiveCfg = Debug|Win32 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|Win32.Build.0 = Debug|Win32 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|x64.ActiveCfg = Debug|x64 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Debug|x64.Build.0 = Debug|x64 - {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|ARM.ActiveCfg = Release|Win32 + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|ARM.ActiveCfg = Release|ARM + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|ARM.Build.0 = Release|ARM + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|ARM64.ActiveCfg = Release|ARM64 + {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|ARM64.Build.0 = Release|ARM64 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|Win32.ActiveCfg = Release|Win32 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|Win32.Build.0 = Release|Win32 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|x64.ActiveCfg = Release|x64 {8B41752B-5A52-41E4-B7E0-07921C0CC6BF}.Release|x64.Build.0 = Release|x64 - {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|ARM.ActiveCfg = Debug|Win32 + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|ARM.ActiveCfg = Debug|ARM + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|ARM.Build.0 = Debug|ARM + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|ARM64.Build.0 = Debug|ARM64 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|Win32.ActiveCfg = Debug|Win32 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|Win32.Build.0 = Debug|Win32 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|x64.ActiveCfg = Debug|x64 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Debug|x64.Build.0 = Debug|x64 - {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|ARM.ActiveCfg = Release|Win32 + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|ARM.ActiveCfg = Release|ARM + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|ARM.Build.0 = Release|ARM + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|ARM64.ActiveCfg = Release|ARM64 + {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|ARM64.Build.0 = Release|ARM64 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|Win32.ActiveCfg = Release|Win32 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|Win32.Build.0 = Release|Win32 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|x64.ActiveCfg = Release|x64 {97521D06-EC47-45D4-8BD0-9E16B3F93B2A}.Release|x64.Build.0 = Release|x64 - {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|ARM.ActiveCfg = Debug|Win32 + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|ARM.ActiveCfg = Debug|ARM + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|ARM.Build.0 = Debug|ARM + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|ARM64.Build.0 = Debug|ARM64 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|Win32.ActiveCfg = Debug|Win32 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|Win32.Build.0 = Debug|Win32 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|x64.ActiveCfg = Debug|x64 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Debug|x64.Build.0 = Debug|x64 - {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|ARM.ActiveCfg = Release|Win32 + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|ARM.ActiveCfg = Release|ARM + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|ARM.Build.0 = Release|ARM + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|ARM64.ActiveCfg = Release|ARM64 + {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|ARM64.Build.0 = Release|ARM64 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|Win32.ActiveCfg = Release|Win32 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|Win32.Build.0 = Release|Win32 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|x64.ActiveCfg = Release|x64 {77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|x64.Build.0 = Release|x64 - {0178B127-6269-407D-B112-93877BB62776}.Debug|ARM.ActiveCfg = Debug|Win32 + {0178B127-6269-407D-B112-93877BB62776}.Debug|ARM.ActiveCfg = Debug|ARM + {0178B127-6269-407D-B112-93877BB62776}.Debug|ARM.Build.0 = Debug|ARM + {0178B127-6269-407D-B112-93877BB62776}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0178B127-6269-407D-B112-93877BB62776}.Debug|ARM64.Build.0 = Debug|ARM64 {0178B127-6269-407D-B112-93877BB62776}.Debug|Win32.ActiveCfg = Debug|Win32 {0178B127-6269-407D-B112-93877BB62776}.Debug|Win32.Build.0 = Debug|Win32 {0178B127-6269-407D-B112-93877BB62776}.Debug|x64.ActiveCfg = Debug|x64 {0178B127-6269-407D-B112-93877BB62776}.Debug|x64.Build.0 = Debug|x64 - {0178B127-6269-407D-B112-93877BB62776}.Release|ARM.ActiveCfg = Release|Win32 + {0178B127-6269-407D-B112-93877BB62776}.Release|ARM.ActiveCfg = Release|ARM + {0178B127-6269-407D-B112-93877BB62776}.Release|ARM.Build.0 = Release|ARM + {0178B127-6269-407D-B112-93877BB62776}.Release|ARM64.ActiveCfg = Release|ARM64 + {0178B127-6269-407D-B112-93877BB62776}.Release|ARM64.Build.0 = Release|ARM64 {0178B127-6269-407D-B112-93877BB62776}.Release|Win32.ActiveCfg = Release|Win32 {0178B127-6269-407D-B112-93877BB62776}.Release|Win32.Build.0 = Release|Win32 {0178B127-6269-407D-B112-93877BB62776}.Release|x64.ActiveCfg = Release|x64 {0178B127-6269-407D-B112-93877BB62776}.Release|x64.Build.0 = Release|x64 - {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|ARM.ActiveCfg = Debug|Win32 + {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|ARM.ActiveCfg = Debug|ARM + {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|ARM.Build.0 = Debug|ARM + {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|ARM64.Build.0 = Debug|ARM64 {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|Win32.ActiveCfg = Debug|Win32 {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|Win32.Build.0 = Debug|Win32 {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|x64.ActiveCfg = Debug|x64 {73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|x64.Build.0 = Debug|x64 - {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|ARM.ActiveCfg = Release|Win32 + {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|ARM.ActiveCfg = Release|ARM + {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|ARM.Build.0 = Release|ARM + {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|ARM64.ActiveCfg = Release|ARM64 + {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|ARM64.Build.0 = Release|ARM64 {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|Win32.ActiveCfg = Release|Win32 {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|Win32.Build.0 = Release|Win32 {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|x64.ActiveCfg = Release|x64 {73632960-B3A6-464D-83A3-4B43365F19B8}.Release|x64.Build.0 = Release|x64 - {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|ARM.ActiveCfg = Debug|Win32 + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|ARM.ActiveCfg = Debug|ARM + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|ARM.Build.0 = Debug|ARM + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|ARM64.Build.0 = Debug|ARM64 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|Win32.ActiveCfg = Debug|Win32 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|Win32.Build.0 = Debug|Win32 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|x64.ActiveCfg = Debug|x64 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Debug|x64.Build.0 = Debug|x64 - {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|ARM.ActiveCfg = Release|Win32 + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|ARM.ActiveCfg = Release|ARM + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|ARM.Build.0 = Release|ARM + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|ARM64.ActiveCfg = Release|ARM64 + {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|ARM64.Build.0 = Release|ARM64 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|Win32.ActiveCfg = Release|Win32 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|Win32.Build.0 = Release|Win32 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|x64.ActiveCfg = Release|x64 {F5AD9738-1A3D-4906-B9C4-A7D9CE33DC2C}.Release|x64.Build.0 = Release|x64 - {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|ARM.ActiveCfg = Debug|Win32 + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|ARM.ActiveCfg = Debug|ARM + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|ARM.Build.0 = Debug|ARM + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|ARM64.Build.0 = Debug|ARM64 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|Win32.ActiveCfg = Debug|Win32 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|Win32.Build.0 = Debug|Win32 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|x64.ActiveCfg = Debug|x64 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Debug|x64.Build.0 = Debug|x64 - {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|ARM.ActiveCfg = Release|Win32 + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|ARM.ActiveCfg = Release|ARM + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|ARM.Build.0 = Release|ARM + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|ARM64.ActiveCfg = Release|ARM64 + {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|ARM64.Build.0 = Release|ARM64 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|Win32.ActiveCfg = Release|Win32 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|Win32.Build.0 = Release|Win32 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|x64.ActiveCfg = Release|x64 {D9DF7F2F-93B7-4810-B5CD-96F4F33C079B}.Release|x64.Build.0 = Release|x64 - {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|ARM.ActiveCfg = Debug|Win32 + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|ARM.ActiveCfg = Debug|ARM + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|ARM.Build.0 = Debug|ARM + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|ARM64.Build.0 = Debug|ARM64 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|Win32.ActiveCfg = Debug|Win32 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|Win32.Build.0 = Debug|Win32 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|x64.ActiveCfg = Debug|x64 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Debug|x64.Build.0 = Debug|x64 - {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|ARM.ActiveCfg = Release|Win32 + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|ARM.ActiveCfg = Release|ARM + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|ARM.Build.0 = Release|ARM + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|ARM64.ActiveCfg = Release|ARM64 + {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|ARM64.Build.0 = Release|ARM64 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|Win32.ActiveCfg = Release|Win32 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|Win32.Build.0 = Release|Win32 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|x64.ActiveCfg = Release|x64 {4C8454FE-81D3-4CA3-9927-29BA96F03DAC}.Release|x64.Build.0 = Release|x64 - {203EC78A-0531-43F0-A636-285439BDE025}.Debug|ARM.ActiveCfg = Debug|Win32 + {203EC78A-0531-43F0-A636-285439BDE025}.Debug|ARM.ActiveCfg = Debug|ARM + {203EC78A-0531-43F0-A636-285439BDE025}.Debug|ARM.Build.0 = Debug|ARM + {203EC78A-0531-43F0-A636-285439BDE025}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {203EC78A-0531-43F0-A636-285439BDE025}.Debug|ARM64.Build.0 = Debug|ARM64 {203EC78A-0531-43F0-A636-285439BDE025}.Debug|Win32.ActiveCfg = Debug|Win32 {203EC78A-0531-43F0-A636-285439BDE025}.Debug|Win32.Build.0 = Debug|Win32 {203EC78A-0531-43F0-A636-285439BDE025}.Debug|x64.ActiveCfg = Debug|x64 {203EC78A-0531-43F0-A636-285439BDE025}.Debug|x64.Build.0 = Debug|x64 - {203EC78A-0531-43F0-A636-285439BDE025}.Release|ARM.ActiveCfg = Release|Win32 + {203EC78A-0531-43F0-A636-285439BDE025}.Release|ARM.ActiveCfg = Release|ARM + {203EC78A-0531-43F0-A636-285439BDE025}.Release|ARM.Build.0 = Release|ARM + {203EC78A-0531-43F0-A636-285439BDE025}.Release|ARM64.ActiveCfg = Release|ARM64 + {203EC78A-0531-43F0-A636-285439BDE025}.Release|ARM64.Build.0 = Release|ARM64 {203EC78A-0531-43F0-A636-285439BDE025}.Release|Win32.ActiveCfg = Release|Win32 {203EC78A-0531-43F0-A636-285439BDE025}.Release|Win32.Build.0 = Release|Win32 {203EC78A-0531-43F0-A636-285439BDE025}.Release|x64.ActiveCfg = Release|x64 {203EC78A-0531-43F0-A636-285439BDE025}.Release|x64.Build.0 = Release|x64 - {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|ARM.ActiveCfg = Debug|Win32 + {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|ARM.ActiveCfg = Debug|ARM + {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|ARM.Build.0 = Debug|ARM + {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|ARM64.Build.0 = Debug|ARM64 {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|Win32.ActiveCfg = Debug|Win32 {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|Win32.Build.0 = Debug|Win32 {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|x64.ActiveCfg = Debug|x64 {6B231032-3CB5-4EED-9210-810D666A23A0}.Debug|x64.Build.0 = Debug|x64 - {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|ARM.ActiveCfg = Release|Win32 + {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|ARM.ActiveCfg = Release|ARM + {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|ARM.Build.0 = Release|ARM + {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|ARM64.Build.0 = Release|ARM64 {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|Win32.ActiveCfg = Release|Win32 {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|Win32.Build.0 = Release|Win32 {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|x64.ActiveCfg = Release|x64 {6B231032-3CB5-4EED-9210-810D666A23A0}.Release|x64.Build.0 = Release|x64 - {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|ARM.ActiveCfg = Debug|Win32 + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|ARM.ActiveCfg = Debug|ARM + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|ARM.Build.0 = Debug|ARM + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|ARM64.Build.0 = Debug|ARM64 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|Win32.ActiveCfg = Debug|Win32 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|Win32.Build.0 = Debug|Win32 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|x64.ActiveCfg = Debug|x64 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Debug|x64.Build.0 = Debug|x64 - {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|ARM.ActiveCfg = Release|Win32 + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|ARM.ActiveCfg = Release|ARM + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|ARM.Build.0 = Release|ARM + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|ARM64.ActiveCfg = Release|ARM64 + {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|ARM64.Build.0 = Release|ARM64 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|Win32.ActiveCfg = Release|Win32 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|Win32.Build.0 = Release|Win32 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|x64.ActiveCfg = Release|x64 {DBA4088D-F6F9-4F8F-8820-082A4765C16C}.Release|x64.Build.0 = Release|x64 - {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|ARM.ActiveCfg = Debug|Win32 + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|ARM.ActiveCfg = Debug|ARM + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|ARM.Build.0 = Debug|ARM + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|ARM64.Build.0 = Debug|ARM64 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|Win32.ActiveCfg = Debug|Win32 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|Win32.Build.0 = Debug|Win32 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|x64.ActiveCfg = Debug|x64 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Debug|x64.Build.0 = Debug|x64 - {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|ARM.ActiveCfg = Release|Win32 + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|ARM.ActiveCfg = Release|ARM + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|ARM.Build.0 = Release|ARM + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|ARM64.ActiveCfg = Release|ARM64 + {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|ARM64.Build.0 = Release|ARM64 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|Win32.ActiveCfg = Release|Win32 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|Win32.Build.0 = Release|Win32 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|x64.ActiveCfg = Release|x64 {C2B04507-2521-4801-BF0D-5FD79D6D518C}.Release|x64.Build.0 = Release|x64 - {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|ARM.ActiveCfg = Debug|Win32 + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|ARM.ActiveCfg = Debug|ARM + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|ARM.Build.0 = Debug|ARM + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|ARM64.Build.0 = Debug|ARM64 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|Win32.ActiveCfg = Debug|Win32 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|Win32.Build.0 = Debug|Win32 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|x64.ActiveCfg = Debug|x64 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Debug|x64.Build.0 = Debug|x64 - {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|ARM.ActiveCfg = Release|Win32 + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|ARM.ActiveCfg = Release|ARM + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|ARM.Build.0 = Release|ARM + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|ARM64.ActiveCfg = Release|ARM64 + {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|ARM64.Build.0 = Release|ARM64 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|Win32.ActiveCfg = Release|Win32 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|Win32.Build.0 = Release|Win32 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|x64.ActiveCfg = Release|x64 {631C23CE-6C1D-4875-88F0-85E0A42B36EA}.Release|x64.Build.0 = Release|x64 - {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|ARM.ActiveCfg = Debug|Win32 + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|ARM.ActiveCfg = Debug|ARM + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|ARM.Build.0 = Debug|ARM + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|ARM64.Build.0 = Debug|ARM64 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|Win32.ActiveCfg = Debug|Win32 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|Win32.Build.0 = Debug|Win32 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|x64.ActiveCfg = Debug|x64 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Debug|x64.Build.0 = Debug|x64 - {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|ARM.ActiveCfg = Release|Win32 + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|ARM.ActiveCfg = Release|ARM + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|ARM.Build.0 = Release|ARM + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|ARM64.ActiveCfg = Release|ARM64 + {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|ARM64.Build.0 = Release|ARM64 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|Win32.ActiveCfg = Release|Win32 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|Win32.Build.0 = Release|Win32 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|x64.ActiveCfg = Release|x64 {E4993E82-D68A-46CA-BAE0-9D35E172E46F}.Release|x64.Build.0 = Release|x64 - {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|ARM.ActiveCfg = Debug|Win32 + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|ARM.ActiveCfg = Debug|ARM + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|ARM.Build.0 = Debug|ARM + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|ARM64.Build.0 = Debug|ARM64 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|Win32.ActiveCfg = Debug|Win32 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|Win32.Build.0 = Debug|Win32 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|x64.ActiveCfg = Debug|x64 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Debug|x64.Build.0 = Debug|x64 - {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|ARM.ActiveCfg = Release|Win32 + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|ARM.ActiveCfg = Release|ARM + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|ARM.Build.0 = Release|ARM + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|ARM64.ActiveCfg = Release|ARM64 + {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|ARM64.Build.0 = Release|ARM64 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|Win32.ActiveCfg = Release|Win32 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|Win32.Build.0 = Release|Win32 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|x64.ActiveCfg = Release|x64 {62D4B15D-7A90-4ECB-BA19-5E021D6A21BC}.Release|x64.Build.0 = Release|x64 - {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|ARM.ActiveCfg = Debug|Win32 + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|ARM.ActiveCfg = Debug|ARM + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|ARM.Build.0 = Debug|ARM + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|ARM64.Build.0 = Debug|ARM64 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|Win32.ActiveCfg = Debug|Win32 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|Win32.Build.0 = Debug|Win32 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|x64.ActiveCfg = Debug|x64 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Debug|x64.Build.0 = Debug|x64 - {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|ARM.ActiveCfg = Release|Win32 + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|ARM.ActiveCfg = Release|ARM + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|ARM.Build.0 = Release|ARM + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|ARM64.ActiveCfg = Release|ARM64 + {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|ARM64.Build.0 = Release|ARM64 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|Win32.ActiveCfg = Release|Win32 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|Win32.Build.0 = Release|Win32 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|x64.ActiveCfg = Release|x64 {9D4211F7-2C77-439C-82F0-30A4E43BA569}.Release|x64.Build.0 = Release|x64 - {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|ARM.ActiveCfg = Debug|Win32 + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|ARM.ActiveCfg = Debug|ARM + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|ARM.Build.0 = Debug|ARM + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|ARM64.Build.0 = Debug|ARM64 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|Win32.ActiveCfg = Debug|Win32 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|Win32.Build.0 = Debug|Win32 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|x64.ActiveCfg = Debug|x64 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Debug|x64.Build.0 = Debug|x64 - {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|ARM.ActiveCfg = Release|Win32 + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|ARM.ActiveCfg = Release|ARM + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|ARM.Build.0 = Release|ARM + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|ARM64.ActiveCfg = Release|ARM64 + {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|ARM64.Build.0 = Release|ARM64 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|Win32.ActiveCfg = Release|Win32 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|Win32.Build.0 = Release|Win32 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|x64.ActiveCfg = Release|x64 {691EE0C0-DC57-4A48-8AEE-8ED75EB3A057}.Release|x64.Build.0 = Release|x64 - {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|ARM.ActiveCfg = Debug|Win32 + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|ARM.ActiveCfg = Debug|ARM + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|ARM.Build.0 = Debug|ARM + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|ARM64.Build.0 = Debug|ARM64 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|Win32.ActiveCfg = Debug|Win32 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|Win32.Build.0 = Debug|Win32 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|x64.ActiveCfg = Debug|x64 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Debug|x64.Build.0 = Debug|x64 - {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|ARM.ActiveCfg = Release|Win32 + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|ARM.ActiveCfg = Release|ARM + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|ARM.Build.0 = Release|ARM + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|ARM64.ActiveCfg = Release|ARM64 + {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|ARM64.Build.0 = Release|ARM64 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|Win32.ActiveCfg = Release|Win32 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|Win32.Build.0 = Release|Win32 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|x64.ActiveCfg = Release|x64 {C7891A65-80AB-4245-912E-5F1E17B0E6C4}.Release|x64.Build.0 = Release|x64 - {E7611F49-F088-4175-9446-6111444E72C8}.Debug|ARM.ActiveCfg = Debug|Win32 + {E7611F49-F088-4175-9446-6111444E72C8}.Debug|ARM.ActiveCfg = Debug|ARM + {E7611F49-F088-4175-9446-6111444E72C8}.Debug|ARM.Build.0 = Debug|ARM + {E7611F49-F088-4175-9446-6111444E72C8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E7611F49-F088-4175-9446-6111444E72C8}.Debug|ARM64.Build.0 = Debug|ARM64 {E7611F49-F088-4175-9446-6111444E72C8}.Debug|Win32.ActiveCfg = Debug|Win32 {E7611F49-F088-4175-9446-6111444E72C8}.Debug|Win32.Build.0 = Debug|Win32 {E7611F49-F088-4175-9446-6111444E72C8}.Debug|x64.ActiveCfg = Debug|x64 {E7611F49-F088-4175-9446-6111444E72C8}.Debug|x64.Build.0 = Debug|x64 - {E7611F49-F088-4175-9446-6111444E72C8}.Release|ARM.ActiveCfg = Release|Win32 + {E7611F49-F088-4175-9446-6111444E72C8}.Release|ARM.ActiveCfg = Release|ARM + {E7611F49-F088-4175-9446-6111444E72C8}.Release|ARM.Build.0 = Release|ARM + {E7611F49-F088-4175-9446-6111444E72C8}.Release|ARM64.ActiveCfg = Release|ARM64 + {E7611F49-F088-4175-9446-6111444E72C8}.Release|ARM64.Build.0 = Release|ARM64 {E7611F49-F088-4175-9446-6111444E72C8}.Release|Win32.ActiveCfg = Release|Win32 {E7611F49-F088-4175-9446-6111444E72C8}.Release|Win32.Build.0 = Release|Win32 {E7611F49-F088-4175-9446-6111444E72C8}.Release|x64.ActiveCfg = Release|x64 {E7611F49-F088-4175-9446-6111444E72C8}.Release|x64.Build.0 = Release|x64 - {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|ARM.ActiveCfg = Debug|Win32 + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|ARM.ActiveCfg = Debug|ARM + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|ARM.Build.0 = Debug|ARM + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|ARM64.Build.0 = Debug|ARM64 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|Win32.ActiveCfg = Debug|Win32 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|Win32.Build.0 = Debug|Win32 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|x64.ActiveCfg = Debug|x64 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Debug|x64.Build.0 = Debug|x64 - {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|ARM.ActiveCfg = Release|Win32 + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|ARM.ActiveCfg = Release|ARM + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|ARM.Build.0 = Release|ARM + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|ARM64.ActiveCfg = Release|ARM64 + {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|ARM64.Build.0 = Release|ARM64 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|Win32.ActiveCfg = Release|Win32 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|Win32.Build.0 = Release|Win32 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|x64.ActiveCfg = Release|x64 {659D0C08-D4ED-4BF3-B02B-2D8D4B5A7A7A}.Release|x64.Build.0 = Release|x64 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|ARM.ActiveCfg = Debug|ARM {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|ARM.Build.0 = Debug|ARM + {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|ARM64.Build.0 = Debug|ARM64 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|Win32.ActiveCfg = Debug|Win32 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|Win32.Build.0 = Debug|Win32 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|x64.ActiveCfg = Debug|x64 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Debug|x64.Build.0 = Debug|x64 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|ARM.ActiveCfg = Release|ARM {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|ARM.Build.0 = Release|ARM + {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|ARM64.ActiveCfg = Release|ARM64 + {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|ARM64.Build.0 = Release|ARM64 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|Win32.ActiveCfg = Release|Win32 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|Win32.Build.0 = Release|Win32 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|x64.ActiveCfg = Release|x64 {B1D53358-37BD-48BC-B27C-68BAF1E78508}.Release|x64.Build.0 = Release|x64 {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|ARM.ActiveCfg = Debug|ARM {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|ARM.Build.0 = Debug|ARM + {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|ARM64.Build.0 = Debug|ARM64 {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|Win32.ActiveCfg = Debug|Win32 {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|Win32.Build.0 = Debug|Win32 {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|x64.ActiveCfg = Debug|x64 {6786C051-383B-47E0-9E82-B8B994E06A25}.Debug|x64.Build.0 = Debug|x64 {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|ARM.ActiveCfg = Release|ARM {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|ARM.Build.0 = Release|ARM + {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|ARM64.ActiveCfg = Release|ARM64 + {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|ARM64.Build.0 = Release|ARM64 {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|Win32.ActiveCfg = Release|Win32 {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|Win32.Build.0 = Release|Win32 {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|x64.ActiveCfg = Release|x64 {6786C051-383B-47E0-9E82-B8B994E06A25}.Release|x64.Build.0 = Release|x64 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|ARM.ActiveCfg = Debug|ARM {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|ARM.Build.0 = Debug|ARM + {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|ARM64.Build.0 = Debug|ARM64 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|Win32.ActiveCfg = Debug|Win32 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|Win32.Build.0 = Debug|Win32 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|x64.ActiveCfg = Debug|x64 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Debug|x64.Build.0 = Debug|x64 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|ARM.ActiveCfg = Release|ARM {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|ARM.Build.0 = Release|ARM + {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|ARM64.ActiveCfg = Release|ARM64 + {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|ARM64.Build.0 = Release|ARM64 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|Win32.ActiveCfg = Release|Win32 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|Win32.Build.0 = Release|Win32 {C10CF34B-3F79-430E-AD38-5A32DC0589C2}.Release|x64.ActiveCfg = Release|x64 diff -Nru icu-64.2/source/allinone/Build.Windows.Library.WarningSettings.ProjectConfiguration.props icu-65.1/source/allinone/Build.Windows.Library.WarningSettings.ProjectConfiguration.props --- icu-64.2/source/allinone/Build.Windows.Library.WarningSettings.ProjectConfiguration.props 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/allinone/Build.Windows.Library.WarningSettings.ProjectConfiguration.props 2019-10-03 11:16:41.000000000 +0000 @@ -17,8 +17,10 @@ C4005 Macro redifintion. C4068 Unknown pragma. C4267 Conversion from size_t to type, possible loss of data. + C4910 __declspec(dllexport) and extern are incompatible on an explicit instantiation. + C4003 Not enough parameters for macro. --> - 4251;4661;4715;4706;4005;4068;4267;%(TreatSpecificWarningsAsErrors) + 4251;4661;4715;4706;4005;4068;4267;4910;4003;%(TreatSpecificWarningsAsErrors) diff -Nru icu-64.2/source/allinone/Build.Windows.ProjectConfiguration.props icu-65.1/source/allinone/Build.Windows.ProjectConfiguration.props --- icu-64.2/source/allinone/Build.Windows.ProjectConfiguration.props 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/allinone/Build.Windows.ProjectConfiguration.props 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,14 @@ Debug x64 + + Debug + ARM + + + Debug + ARM64 + Release Win32 @@ -20,15 +28,52 @@ Release x64 + + Release + ARM + + + Release + ARM64 + + + + bin + lib + + + bin64 + lib64 + + + binARM + libARM + + + binARM64 + libARM64 + + - 8.1 + + + + 10.0.16299.0 + true + + + 10.0.16299.0 + true + 0x0601 @@ -61,6 +106,7 @@ true + true @@ -71,12 +117,15 @@ NDEBUG;%(PreprocessorDefinitions) true + true + ProgramDatabase NDEBUG;%(PreprocessorDefinitions) true + UseLinkTimeCodeGeneration @@ -122,4 +171,36 @@ MachineX64 + + + + ARM + + + ARM;WIN32;%(PreprocessorDefinitions) + + + MachineARM + + kernel32.lib;%(AdditionalDependencies) + + C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm + + + + + + ARM64 + + + ARM64;WIN32;%(PreprocessorDefinitions) + + + MachineARM64 + + kernel32.lib;%(AdditionalDependencies) + + C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64 + + \ No newline at end of file diff -Nru icu-64.2/source/allinone/Build.Windows.UWP.ProjectConfiguration.props icu-65.1/source/allinone/Build.Windows.UWP.ProjectConfiguration.props --- icu-64.2/source/allinone/Build.Windows.UWP.ProjectConfiguration.props 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/allinone/Build.Windows.UWP.ProjectConfiguration.props 2019-10-03 11:16:41.000000000 +0000 @@ -24,6 +24,23 @@ + + + bin32uwp + lib32uwp + + + bin64uwp + lib64uwp + + + binARMuwp + libARMuwp + + + binARM64uwp + libARM64uwp + diff -Nru icu-64.2/source/allinone/icucheck.bat icu-65.1/source/allinone/icucheck.bat --- icu-64.2/source/allinone/icucheck.bat 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/allinone/icucheck.bat 2019-10-03 11:16:41.000000000 +0000 @@ -11,7 +11,7 @@ set ICU_DBRL=%2 if "%1" == "" ( -echo Usage: %0 "x86 or x64" "Debug or Release" +echo Usage: %0 "x86 or x64 or ARM or ARM64" "Debug or Release" exit /b 1 ) @@ -25,9 +25,13 @@ set ICU_ICUDIR="%~dp0"\..\.. if "%ICU_ARCH%" == "x64" ( -set ICU_BINDIR=%~dp0\..\..\bin64 + set ICU_BINDIR=%~dp0\..\..\bin64 +) else if "%ICU_ARCH%" == "ARM64" ( + set ICU_BINDIR=%~dp0\..\..\binARM64 +) else if "%ICU_ARCH%" == "ARM" ( + set ICU_BINDIR=%~dp0\..\..\binARM ) else ( -set ICU_BINDIR=%~dp0\..\..\bin + set ICU_BINDIR=%~dp0\..\..\bin ) set PATH=%ICU_BINDIR%;%PATH% diff -Nru icu-64.2/source/common/brkeng.cpp icu-65.1/source/common/brkeng.cpp --- icu-64.2/source/common/brkeng.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/brkeng.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -129,7 +129,7 @@ const LanguageBreakEngine *lbe = NULL; UErrorCode status = U_ZERO_ERROR; - static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER; + static UMutex gBreakEngineMutex; Mutex m(&gBreakEngineMutex); if (fEngines == NULL) { diff -Nru icu-64.2/source/common/brkiter.cpp icu-65.1/source/common/brkiter.cpp --- icu-64.2/source/common/brkiter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/brkiter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -277,7 +277,7 @@ // defined in ucln_cmn.h U_NAMESPACE_END -static icu::UInitOnce gInitOnceBrkiter; +static icu::UInitOnce gInitOnceBrkiter = U_INITONCE_INITIALIZER; static icu::ICULocaleService* gService = NULL; diff -Nru icu-64.2/source/common/bytesinkutil.h icu-65.1/source/common/bytesinkutil.h --- icu-64.2/source/common/bytesinkutil.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/bytesinkutil.h 2019-10-03 11:16:41.000000000 +0000 @@ -59,7 +59,7 @@ ByteSink &sink, uint32_t options, Edits *edits); }; -class CharStringByteSink : public ByteSink { +class U_COMMON_API CharStringByteSink : public ByteSink { public: CharStringByteSink(CharString* dest); ~CharStringByteSink() override; diff -Nru icu-64.2/source/common/characterproperties.cpp icu-65.1/source/common/characterproperties.cpp --- icu-64.2/source/common/characterproperties.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/characterproperties.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -38,8 +38,8 @@ constexpr int32_t NUM_INCLUSIONS = UPROPS_SRC_COUNT + UCHAR_INT_LIMIT - UCHAR_INT_START; struct Inclusion { - UnicodeSet *fSet; - UInitOnce fInitOnce; + UnicodeSet *fSet = nullptr; + UInitOnce fInitOnce = U_INITONCE_INITIALIZER; }; Inclusion gInclusions[NUM_INCLUSIONS]; // cached getInclusions() @@ -47,10 +47,7 @@ UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {}; -icu::UMutex *cpMutex() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +icu::UMutex cpMutex; //---------------------------------------------------------------- // Inclusions list @@ -361,7 +358,7 @@ *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - Mutex m(cpMutex()); + Mutex m(&cpMutex); UnicodeSet *set = sets[property]; if (set == nullptr) { sets[property] = set = makeSet(property, *pErrorCode); @@ -377,7 +374,7 @@ *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - Mutex m(cpMutex()); + Mutex m(&cpMutex); UCPMap *map = maps[property - UCHAR_INT_START]; if (map == nullptr) { maps[property - UCHAR_INT_START] = map = makeMap(property, *pErrorCode); diff -Nru icu-64.2/source/common/charstr.cpp icu-65.1/source/common/charstr.cpp --- icu-64.2/source/common/charstr.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/charstr.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -35,6 +35,17 @@ return *this; } +char *CharString::cloneData(UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } + char *p = static_cast(uprv_malloc(len + 1)); + if (p == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + uprv_memcpy(p, buffer.getAlias(), len + 1); + return p; +} + CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { len=s.len; @@ -52,6 +63,18 @@ return -1; } +bool CharString::contains(StringPiece s) const { + if (s.empty()) { return false; } + const char *p = buffer.getAlias(); + int32_t lastStart = len - s.length(); + for (int32_t i = 0; i <= lastStart; ++i) { + if (uprv_memcmp(p + i, s.data(), s.length()) == 0) { + return true; + } + } + return false; +} + CharString &CharString::truncate(int32_t newLength) { if(newLength<0) { newLength=0; diff -Nru icu-64.2/source/common/charstr.h icu-65.1/source/common/charstr.h --- icu-64.2/source/common/charstr.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/charstr.h 2019-10-03 11:16:41.000000000 +0000 @@ -82,10 +82,24 @@ const char *data() const { return buffer.getAlias(); } char *data() { return buffer.getAlias(); } + /** + * Allocates length()+1 chars and copies the NUL-terminated data(). + * The caller must uprv_free() the result. + */ + char *cloneData(UErrorCode &errorCode) const; + + bool operator==(StringPiece other) const { + return len == other.length() && (len == 0 || uprv_memcmp(data(), other.data(), len) == 0); + } + bool operator!=(StringPiece other) const { + return !operator==(other); + } /** @return last index of c, or -1 if c is not in this string */ int32_t lastIndexOf(char c) const; + bool contains(StringPiece s) const; + CharString &clear() { len=0; buffer[0]=0; return *this; } CharString &truncate(int32_t newLength); diff -Nru icu-64.2/source/common/cmemory.h icu-65.1/source/common/cmemory.h --- icu-64.2/source/common/cmemory.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/cmemory.h 2019-10-03 11:16:41.000000000 +0000 @@ -65,37 +65,36 @@ uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2); /** - * This should align the memory properly on any machine. - * This is very useful for the safeClone functions. - */ -typedef union { - long t1; - double t2; - void *t3; -} UAlignedMemory; - -/** * Get the least significant bits of a pointer (a memory address). * For example, with a mask of 3, the macro gets the 2 least significant bits, * which will be 0 if the pointer is 32-bit (4-byte) aligned. * - * ptrdiff_t is the most appropriate integer type to cast to. - * size_t should work too, since on most (or all?) platforms it has the same - * width as ptrdiff_t. + * uintptr_t is the most appropriate integer type to cast to. */ -#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask)) +#define U_POINTER_MASK_LSB(ptr, mask) ((uintptr_t)(ptr) & (mask)) /** - * Get the amount of bytes that a pointer is off by from - * the previous UAlignedMemory-aligned pointer. - */ -#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1) - -/** - * Get the amount of bytes to add to a pointer - * in order to get the next UAlignedMemory-aligned address. + * Create & return an instance of "type" in statically allocated storage. + * e.g. + * static std::mutex *myMutex = STATIC_NEW(std::mutex); + * To destroy an object created in this way, invoke the destructor explicitly, e.g. + * myMutex->~mutex(); + * DO NOT use delete. + * DO NOT use with class UMutex, which has specific support for static instances. + * + * STATIC_NEW is intended for use when + * - We want a static (or global) object. + * - We don't want it to ever be destructed, or to explicitly control destruction, + * to avoid use-after-destruction problems. + * - We want to avoid an ordinary heap allocated object, + * to avoid the possibility of memory allocation failures, and + * to avoid memory leak reports, from valgrind, for example. + * This is defined as a macro rather than a template function because each invocation + * must define distinct static storage for the object being returned. */ -#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr)) +#define STATIC_NEW(type) [] () { \ + alignas(type) static char storage[sizeof(type)]; \ + return new(storage) type();} () /** * Heap clean up function, called from u_cleanup() diff -Nru icu-64.2/source/common/common_uwp.vcxproj icu-65.1/source/common/common_uwp.vcxproj --- icu-64.2/source/common/common_uwp.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/common_uwp.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,10 @@ Debug ARM + + Debug + ARM64 + Release Win32 @@ -25,6 +29,10 @@ Release ARM + + Release + ARM64 + {C10CF34B-3F79-430E-AD38-5A32DC0589C2} @@ -51,26 +59,21 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\ReleaseUWP\ - .\x86\ReleaseUWP\ - .\x86\DebugUWP\ - .\x86\DebugUWP\ - .\x64\ReleaseUWP\ - .\x64\ReleaseUWP\ - .\x64\DebugUWP\ - .\x64\DebugUWP\ - .\arm\ReleaseUWP\ - .\arm\ReleaseUWP\ - .\arm\DebugUWP\ - .\arm\DebugUWP\ - false + .\$(Platform)\$(Configuration)UWP\ + .\$(Platform)\$(Configuration)UWP\ + + .\x86\$(Configuration)UWP\ + .\x86\$(Configuration)UWP\ + true + false true true + $(OutDir)\icuuc.tlb ..\..\include;..\common;%(AdditionalIncludeDirectories) @@ -89,6 +92,11 @@ NotUsing false /utf-8 %(AdditionalOptions) + $(OutDir)/icuuc.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/icuuc.pdb + ProgramDatabase 0x0409 @@ -102,7 +110,8 @@ true vccorlib.lib;msvcrt.lib - onecoreuap.lib + + icudt.lib;onecore.lib;%(AdditionalDependencies) @@ -119,7 +128,10 @@ true - vccorlib.lib;WindowsApp.lib;msvcrt.lib;%(AdditionalDependencies) + vccorlib.lib;msvcrt.lib;vcruntime.lib;%(AdditionalDependencies) + ..\..\$(IcuBinOutputDir)\icuuc65.dll + .\..\..\$(IcuLibOutputDir)\icuuc.pdb + ..\..\$(IcuLibOutputDir)\icuuc.lib @@ -133,14 +145,16 @@ Disabled EnableFastChecks true - EditAndContinue _DEBUG;%(PreprocessorDefinitions) true - vccorlibd.lib;WindowsApp.lib;msvcrtd.lib;%(AdditionalDependencies) + vccorlibd.lib;msvcrtd.lib;vcruntimed.lib;%(AdditionalDependencies) + ..\..\$(IcuBinOutputDir)\icuuc65d.dll + .\..\..\$(IcuLibOutputDir)\icuucd.pdb + ..\..\$(IcuLibOutputDir)\icuucd.lib @@ -151,6 +165,10 @@ WIN32;%(PreprocessorDefinitions) + + + .\..\..\lib;%(AdditionalLibraryDirectories) + @@ -162,6 +180,8 @@ MachineX64 + + .\..\..\lib64;%(AdditionalLibraryDirectories) @@ -174,103 +194,22 @@ MachineARM + + .\..\..\libARM;%(AdditionalLibraryDirectories) - - - - .\..\..\lib32uwp\icuuc.tlb - - - .\x86\ReleaseUWP/common.pch - .\x86\ReleaseUWP/ - .\x86\ReleaseUWP/ - .\x86\ReleaseUWP/ - - - ..\..\bin32uwp\icuuc64.dll - .\..\..\lib32uwp\icuuc.pdb - ..\..\lib32uwp\icuuc.lib - - - - - .\..\..\lib32uwp\icuucd.tlb - - - .\x86\DebugUWP/common.pch - .\x86\DebugUWP/ - .\x86\DebugUWP/ - .\x86\DebugUWP/ - - - ..\..\bin32uwp\icuuc64d.dll - .\..\..\lib32uwp\icuucd.pdb - ..\..\lib32uwp\icuucd.lib - - - - - .\..\..\lib64uwp\icuuc.tlb - - - .\x64\ReleaseUWP/common.pch - .\x64\ReleaseUWP/ - .\x64\ReleaseUWP/ - .\x64\ReleaseUWP/ - - - ..\..\bin64uwp\icuuc64.dll - .\..\..\lib64uwp\icuuc.pdb - ..\..\lib64uwp\icuuc.lib - - - + + - .\..\..\lib64uwp\icuucd.tlb + ARM64 - .\x64\DebugUWP/common.pch - .\x64\DebugUWP/ - .\x64\DebugUWP/ - .\x64\DebugUWP/ + ARM64;WIN32;%(PreprocessorDefinitions) - ..\..\bin64uwp\icuuc64d.dll - .\..\..\lib64uwp\icuucd.pdb - ..\..\lib64uwp\icuucd.lib - - - - - .\..\..\libARMuwp\icuuc.tlb - - - .\ARM\ReleaseUWP/common.pch - .\ARM\ReleaseUWP/ - .\ARM\ReleaseUWP/ - .\ARM\ReleaseUWP/ - - - ..\..\binARMuwp\icuuc64.dll - .\..\..\libARMuwp\icuuc.pdb - ..\..\libARMuwp\icuuc.lib - - - - - .\..\..\libARMuwp\icuucd.tlb - - - .\ARM\DebugUWP/common.pch - .\ARM\DebugUWP/ - .\ARM\DebugUWP/ - .\ARM\DebugUWP/ - - - ..\..\binARMuwp\icuuc64d.dll - .\..\..\libARMuwp\icuucd.pdb - ..\..\libARMuwp\icuucd.lib + MachineARM64 + + .\..\..\libARM64;%(AdditionalLibraryDirectories) @@ -317,9 +256,7 @@ - - true - + @@ -365,14 +302,20 @@ + + + + + + @@ -383,7 +326,6 @@ - @@ -465,6 +407,7 @@ + @@ -534,8 +477,12 @@ + + + + @@ -574,7 +521,7 @@ - + @@ -585,4 +532,4 @@ - + \ No newline at end of file diff -Nru icu-64.2/source/common/common.vcxproj icu-65.1/source/common/common.vcxproj --- icu-64.2/source/common/common.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/common.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -35,29 +35,35 @@ <_ProjectFileVersion>10.0.30319.1 - .\..\..\lib\ - .\x86\Release\ - false - .\..\..\lib\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false + + $(OutDir)\icuuc.tlb + U_ATTRIBUTE_DEPRECATED=;U_COMMON_IMPLEMENTATION;U_PLATFORM_USES_ONLY_WIN32_API=1;%(PreprocessorDefinitions) false Level3 + Default + ProgramDatabase + $(OutDir)/icuuc.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/icuuc.pdb + icudt.lib;%(AdditionalDependencies) - 0x4a800000 + .\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) @@ -67,6 +73,11 @@ true MultiThreadedDebugDLL + + ..\..\$(IcuBinOutputDir)\icuuc65d.dll + .\..\..\$(IcuLibOutputDir)\icuucd.pdb + ..\..\$(IcuLibOutputDir)\icuucd.lib + @@ -74,79 +85,10 @@ MultiThreadedDLL true - - - - .\..\..\lib\icuuc.tlb - - - .\x86\Release/common.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - - - ..\..\bin\icuuc64.dll - .\..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\lib\icuuc.pdb - - - ..\..\lib\icuuc.lib - - - - - .\..\..\lib\icuucd.tlb - - - .\x86\Debug/common.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - EditAndContinue - - ..\..\bin\icuuc64d.dll - .\..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\lib\icuucd.pdb - - - ..\..\lib\icuucd.lib - - - - - .\..\..\lib64\icuuc.tlb - - - .\x64\Release/common.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - - - ..\..\bin64\icuuc64.dll - .\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\lib64\icuuc.pdb - ..\..\lib64\icuuc.lib - - - - - .\..\..\lib64\icuucd.tlb - - - .\x64\Debug/common.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - ProgramDatabase - - - ..\..\bin64\icuuc64d.dll - .\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\lib64\icuucd.pdb - ..\..\lib64\icuucd.lib + ..\..\$(IcuBinOutputDir)\icuuc65.dll + .\..\..\$(IcuLibOutputDir)\icuuc.pdb + ..\..\$(IcuLibOutputDir)\icuuc.lib @@ -238,14 +180,20 @@ + + + + + + @@ -256,7 +204,6 @@ - @@ -339,6 +286,7 @@ + @@ -406,8 +354,12 @@ + + + + @@ -447,7 +399,7 @@ - + diff -Nru icu-64.2/source/common/common.vcxproj.filters icu-65.1/source/common/common.vcxproj.filters --- icu-64.2/source/common/common.vcxproj.filters 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/common.vcxproj.filters 2019-10-03 11:16:41.000000000 +0000 @@ -313,6 +313,15 @@ idna + + locales & resources + + + locales & resources + + + locales & resources + locales & resources @@ -322,18 +331,27 @@ locales & resources + + locales & resources + locales & resources locales & resources + + locales & resources + locales & resources locales & resources + + locales & resources + locales & resources @@ -361,9 +379,6 @@ locales & resources - - locales & resources - normalization @@ -619,6 +634,9 @@ formatting + + data & memory + @@ -813,12 +831,24 @@ idna + + locales & resources + locales & resources + + locales & resources + + + locales & resources + locales & resources + + locales & resources + locales & resources @@ -954,9 +984,12 @@ formatting - + data & memory - + + + data & memory + @@ -1072,6 +1105,12 @@ idna + + locales & resources + + + locales & resources + locales & resources @@ -1231,8 +1270,5 @@ strings - - locales & resources - diff -Nru icu-64.2/source/common/edits.cpp icu-65.1/source/common/edits.cpp --- icu-64.2/source/common/edits.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/edits.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -243,7 +243,7 @@ return TRUE; } -UBool Edits::copyErrorTo(UErrorCode &outErrorCode) { +UBool Edits::copyErrorTo(UErrorCode &outErrorCode) const { if (U_FAILURE(outErrorCode)) { return TRUE; } if (U_SUCCESS(errorCode_)) { return FALSE; } outErrorCode = errorCode_; diff -Nru icu-64.2/source/common/filteredbrk.cpp icu-65.1/source/common/filteredbrk.cpp --- icu-64.2/source/common/filteredbrk.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/filteredbrk.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -173,7 +173,7 @@ status = U_SAFECLONE_ALLOCATED_WARNING; return clone(); } - virtual BreakIterator* clone(void) const { return new SimpleFilteredSentenceBreakIterator(*this); } + virtual SimpleFilteredSentenceBreakIterator* clone() const { return new SimpleFilteredSentenceBreakIterator(*this); } virtual UClassID getDynamicClassID(void) const { return NULL; } virtual UBool operator==(const BreakIterator& o) const { if(this==&o) return true; return false; } diff -Nru icu-64.2/source/common/localebuilder.cpp icu-65.1/source/common/localebuilder.cpp --- icu-64.2/source/common/localebuilder.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/localebuilder.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -157,13 +157,18 @@ } static void -_copyExtensions(const Locale& from, Locale* to, bool validate, UErrorCode& errorCode) +_copyExtensions(const Locale& from, icu::StringEnumeration *keywords, + Locale& to, bool validate, UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { return; } - LocalPointer iter(from.createKeywords(errorCode)); - if (U_FAILURE(errorCode) || iter.isNull()) { return; } + LocalPointer ownedKeywords; + if (keywords == nullptr) { + ownedKeywords.adoptInstead(from.createKeywords(errorCode)); + if (U_FAILURE(errorCode) || ownedKeywords.isNull()) { return; } + keywords = ownedKeywords.getAlias(); + } const char* key; - while ((key = iter->next(nullptr, errorCode)) != nullptr) { + while ((key = keywords->next(nullptr, errorCode)) != nullptr) { CharString value; CharStringByteSink sink(&value); from.getKeywordValue(key, sink, errorCode); @@ -176,34 +181,34 @@ errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } - to->setKeywordValue(key, value.data(), errorCode); + to.setKeywordValue(key, value.data(), errorCode); if (U_FAILURE(errorCode)) { return; } } } void static -_clearUAttributesAndKeyType(Locale* locale, UErrorCode& errorCode) +_clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode) { // Clear Unicode attributes - locale->setKeywordValue(kAttributeKey, "", errorCode); + locale.setKeywordValue(kAttributeKey, "", errorCode); // Clear all Unicode keyword values - LocalPointer iter(locale->createUnicodeKeywords(errorCode)); + LocalPointer iter(locale.createUnicodeKeywords(errorCode)); if (U_FAILURE(errorCode) || iter.isNull()) { return; } const char* key; while ((key = iter->next(nullptr, errorCode)) != nullptr) { - locale->setUnicodeKeywordValue(key, nullptr, errorCode); + locale.setUnicodeKeywordValue(key, nullptr, errorCode); } } static void -_setUnicodeExtensions(Locale* locale, const CharString& value, UErrorCode& errorCode) +_setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode) { // Add the unicode extensions to extensions_ CharString locale_str("und-u-", errorCode); locale_str.append(value, errorCode); _copyExtensions( - Locale::forLanguageTag(locale_str.data(), errorCode), + Locale::forLanguageTag(locale_str.data(), errorCode), nullptr, locale, false, errorCode); } @@ -235,10 +240,10 @@ status_); return *this; } - _clearUAttributesAndKeyType(extensions_, status_); + _clearUAttributesAndKeyType(*extensions_, status_); if (U_FAILURE(status_)) { return *this; } if (!value.empty()) { - _setUnicodeExtensions(extensions_, value_str, status_); + _setUnicodeExtensions(*extensions_, value_str, status_); } return *this; } @@ -401,6 +406,24 @@ return bogus; } +void LocaleBuilder::copyExtensionsFrom(const Locale& src, UErrorCode& errorCode) +{ + if (U_FAILURE(errorCode)) { return; } + LocalPointer keywords(src.createKeywords(errorCode)); + if (U_FAILURE(errorCode) || keywords.isNull() || keywords->count(errorCode) == 0) { + // Error, or no extensions to copy. + return; + } + if (extensions_ == nullptr) { + extensions_ = new Locale(); + if (extensions_ == nullptr) { + status_ = U_MEMORY_ALLOCATION_ERROR; + return; + } + } + _copyExtensions(src, keywords.getAlias(), *extensions_, false, errorCode); +} + Locale LocaleBuilder::build(UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { @@ -425,7 +448,7 @@ } Locale product(locale_str.data()); if (extensions_ != nullptr) { - _copyExtensions(*extensions_, &product, true, errorCode); + _copyExtensions(*extensions_, nullptr, product, true, errorCode); } if (U_FAILURE(errorCode)) { return makeBogusLocale(); @@ -433,4 +456,13 @@ return product; } +UBool LocaleBuilder::copyErrorTo(UErrorCode &outErrorCode) const { + if (U_FAILURE(outErrorCode)) { + // Do not overwrite the older error code + return TRUE; + } + outErrorCode = status_; + return U_FAILURE(outErrorCode); +} + U_NAMESPACE_END diff -Nru icu-64.2/source/common/localematcher.cpp icu-65.1/source/common/localematcher.cpp --- icu-64.2/source/common/localematcher.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/localematcher.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,720 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localematcher.cpp +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCMATCHER_H__ +#define __LOCMATCHER_H__ + +#include "unicode/utypes.h" +#include "unicode/localebuilder.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" +#include "cstring.h" +#include "localeprioritylist.h" +#include "loclikelysubtags.h" +#include "locdistance.h" +#include "lsr.h" +#include "uassert.h" +#include "uhash.h" +#include "uvector.h" + +#define UND_LSR LSR("und", "", "") + +/** + * Indicator for the lifetime of desired-locale objects passed into the LocaleMatcher. + * + * @draft ICU 65 + */ +enum ULocMatchLifetime { + /** + * Locale objects are temporary. + * The matcher will make a copy of a locale that will be used beyond one function call. + * + * @draft ICU 65 + */ + ULOCMATCH_TEMPORARY_LOCALES, + /** + * Locale objects are stored at least as long as the matcher is used. + * The matcher will keep only a pointer to a locale that will be used beyond one function call, + * avoiding a copy. + * + * @draft ICU 65 + */ + ULOCMATCH_STORED_LOCALES // TODO: permanent? cached? clone? +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchLifetime ULocMatchLifetime; +#endif + +U_NAMESPACE_BEGIN + +LocaleMatcher::Result::Result(LocaleMatcher::Result &&src) U_NOEXCEPT : + desiredLocale(src.desiredLocale), + supportedLocale(src.supportedLocale), + desiredIndex(src.desiredIndex), + supportedIndex(src.supportedIndex), + desiredIsOwned(src.desiredIsOwned) { + if (desiredIsOwned) { + src.desiredLocale = nullptr; + src.desiredIndex = -1; + src.desiredIsOwned = FALSE; + } +} + +LocaleMatcher::Result::~Result() { + if (desiredIsOwned) { + delete desiredLocale; + } +} + +LocaleMatcher::Result &LocaleMatcher::Result::operator=(LocaleMatcher::Result &&src) U_NOEXCEPT { + this->~Result(); + + desiredLocale = src.desiredLocale; + supportedLocale = src.supportedLocale; + desiredIndex = src.desiredIndex; + supportedIndex = src.supportedIndex; + desiredIsOwned = src.desiredIsOwned; + + if (desiredIsOwned) { + src.desiredLocale = nullptr; + src.desiredIndex = -1; + src.desiredIsOwned = FALSE; + } + return *this; +} + +Locale LocaleMatcher::Result::makeResolvedLocale(UErrorCode &errorCode) const { + if (U_FAILURE(errorCode) || supportedLocale == nullptr) { + return Locale::getRoot(); + } + const Locale *bestDesired = getDesiredLocale(); + if (bestDesired == nullptr || *supportedLocale == *bestDesired) { + return *supportedLocale; + } + LocaleBuilder b; + b.setLocale(*supportedLocale); + + // Copy the region from bestDesired, if there is one. + const char *region = bestDesired->getCountry(); + if (*region != 0) { + b.setRegion(region); + } + + // Copy the variants from bestDesired, if there are any. + // Note that this will override any supportedLocale variants. + // For example, "sco-ulster-fonipa" + "...-fonupa" => "sco-fonupa" (replacing ulster). + const char *variants = bestDesired->getVariant(); + if (*variants != 0) { + b.setVariant(variants); + } + + // Copy the extensions from bestDesired, if there are any. + // C++ note: The following note, copied from Java, may not be true, + // as long as C++ copies by legacy ICU keyword, not by extension singleton. + // Note that this will override any supportedLocale extensions. + // For example, "th-u-nu-latn-ca-buddhist" + "...-u-nu-native" => "th-u-nu-native" + // (replacing calendar). + b.copyExtensionsFrom(*bestDesired, errorCode); + return b.build(errorCode); +} + +LocaleMatcher::Builder::Builder(LocaleMatcher::Builder &&src) U_NOEXCEPT : + errorCode_(src.errorCode_), + supportedLocales_(src.supportedLocales_), + thresholdDistance_(src.thresholdDistance_), + demotion_(src.demotion_), + defaultLocale_(src.defaultLocale_), + favor_(src.favor_) { + src.supportedLocales_ = nullptr; + src.defaultLocale_ = nullptr; +} + +LocaleMatcher::Builder::~Builder() { + delete supportedLocales_; + delete defaultLocale_; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::operator=(LocaleMatcher::Builder &&src) U_NOEXCEPT { + this->~Builder(); + + errorCode_ = src.errorCode_; + supportedLocales_ = src.supportedLocales_; + thresholdDistance_ = src.thresholdDistance_; + demotion_ = src.demotion_; + defaultLocale_ = src.defaultLocale_; + favor_ = src.favor_; + + src.supportedLocales_ = nullptr; + src.defaultLocale_ = nullptr; + return *this; +} + +void LocaleMatcher::Builder::clearSupportedLocales() { + if (supportedLocales_ != nullptr) { + supportedLocales_->removeAllElements(); + } +} + +bool LocaleMatcher::Builder::ensureSupportedLocaleVector() { + if (U_FAILURE(errorCode_)) { return false; } + if (supportedLocales_ != nullptr) { return true; } + supportedLocales_ = new UVector(uprv_deleteUObject, nullptr, errorCode_); + if (U_FAILURE(errorCode_)) { return false; } + if (supportedLocales_ == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + return false; + } + return true; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListString( + StringPiece locales) { + LocalePriorityList list(locales, errorCode_); + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + if (!ensureSupportedLocaleVector()) { return *this; } + int32_t length = list.getLengthIncludingRemoved(); + for (int32_t i = 0; i < length; ++i) { + Locale *locale = list.orphanLocaleAt(i); + if (locale == nullptr) { continue; } + supportedLocales_->addElement(locale, errorCode_); + if (U_FAILURE(errorCode_)) { + delete locale; + break; + } + } + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator &locales) { + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + if (!ensureSupportedLocaleVector()) { return *this; } + while (locales.hasNext()) { + const Locale &locale = locales.next(); + Locale *clone = locale.clone(); + if (clone == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + break; + } + supportedLocales_->addElement(clone, errorCode_); + if (U_FAILURE(errorCode_)) { + delete clone; + break; + } + } + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::addSupportedLocale(const Locale &locale) { + if (!ensureSupportedLocaleVector()) { return *this; } + Locale *clone = locale.clone(); + if (clone == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + return *this; + } + supportedLocales_->addElement(clone, errorCode_); + if (U_FAILURE(errorCode_)) { + delete clone; + } + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setDefaultLocale(const Locale *defaultLocale) { + if (U_FAILURE(errorCode_)) { return *this; } + Locale *clone = nullptr; + if (defaultLocale != nullptr) { + clone = defaultLocale->clone(); + if (clone == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + return *this; + } + } + delete defaultLocale_; + defaultLocale_ = clone; + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag subtag) { + if (U_FAILURE(errorCode_)) { return *this; } + favor_ = subtag; + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion demotion) { + if (U_FAILURE(errorCode_)) { return *this; } + demotion_ = demotion; + return *this; +} + +#if 0 +/** + * Internal only! + * + * @param thresholdDistance the thresholdDistance to set, with -1 = default + * @return this Builder object + * @internal + * @deprecated This API is ICU internal only. + */ +@Deprecated +LocaleMatcher::Builder &LocaleMatcher::Builder::internalSetThresholdDistance(int32_t thresholdDistance) { + if (U_FAILURE(errorCode_)) { return *this; } + if (thresholdDistance > 100) { + thresholdDistance = 100; + } + thresholdDistance_ = thresholdDistance; + return *this; +} +#endif + +UBool LocaleMatcher::Builder::copyErrorTo(UErrorCode &outErrorCode) const { + if (U_FAILURE(outErrorCode)) { return TRUE; } + if (U_SUCCESS(errorCode_)) { return FALSE; } + outErrorCode = errorCode_; + return TRUE; +} + +LocaleMatcher LocaleMatcher::Builder::build(UErrorCode &errorCode) const { + if (U_SUCCESS(errorCode) && U_FAILURE(errorCode_)) { + errorCode = errorCode_; + } + return LocaleMatcher(*this, errorCode); +} + +namespace { + +LSR getMaximalLsrOrUnd(const XLikelySubtags &likelySubtags, const Locale &locale, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) { + return UND_LSR; + } else { + return likelySubtags.makeMaximizedLsrFrom(locale, errorCode); + } +} + +int32_t hashLSR(const UHashTok token) { + const LSR *lsr = static_cast(token.pointer); + return lsr->hashCode; +} + +UBool compareLSRs(const UHashTok t1, const UHashTok t2) { + const LSR *lsr1 = static_cast(t1.pointer); + const LSR *lsr2 = static_cast(t2.pointer); + return *lsr1 == *lsr2; +} + +bool putIfAbsent(UHashtable *lsrToIndex, const LSR &lsr, int32_t i, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return false; } + U_ASSERT(i > 0); + int32_t index = uhash_geti(lsrToIndex, &lsr); + if (index != 0) { + return false; + } else { + uhash_puti(lsrToIndex, const_cast(&lsr), i, &errorCode); + return U_SUCCESS(errorCode); + } +} + +} // namespace + +LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : + likelySubtags(*XLikelySubtags::getSingleton(errorCode)), + localeDistance(*LocaleDistance::getSingleton(errorCode)), + thresholdDistance(builder.thresholdDistance_), + demotionPerDesiredLocale(0), + favorSubtag(builder.favor_), + supportedLocales(nullptr), lsrs(nullptr), supportedLocalesLength(0), + supportedLsrToIndex(nullptr), + supportedLSRs(nullptr), supportedIndexes(nullptr), supportedLSRsLength(0), + ownedDefaultLocale(nullptr), defaultLocale(nullptr), defaultLocaleIndex(-1) { + if (U_FAILURE(errorCode)) { return; } + if (thresholdDistance < 0) { + thresholdDistance = localeDistance.getDefaultScriptDistance(); + } + supportedLocalesLength = builder.supportedLocales_ != nullptr ? + builder.supportedLocales_->size() : 0; + const Locale *def = builder.defaultLocale_; + int32_t idef = -1; + if (supportedLocalesLength > 0) { + // Store the supported locales in input order, + // so that when different types are used (e.g., language tag strings) + // we can return those by parallel index. + supportedLocales = static_cast( + uprv_malloc(supportedLocalesLength * sizeof(const Locale *))); + // Supported LRSs in input order. + // In C++, we store these permanently to simplify ownership management + // in the hash tables. Duplicate LSRs (if any) are unused overhead. + lsrs = new LSR[supportedLocalesLength]; + if (supportedLocales == nullptr || lsrs == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + // If the constructor fails partway, we need null pointers for destructibility. + uprv_memset(supportedLocales, 0, supportedLocalesLength * sizeof(const Locale *)); + // Also find the first supported locale whose LSR is + // the same as that for the default locale. + LSR builderDefaultLSR; + const LSR *defLSR = nullptr; + if (def != nullptr) { + builderDefaultLSR = getMaximalLsrOrUnd(likelySubtags, *def, errorCode); + if (U_FAILURE(errorCode)) { return; } + defLSR = &builderDefaultLSR; + } + for (int32_t i = 0; i < supportedLocalesLength; ++i) { + const Locale &locale = *static_cast(builder.supportedLocales_->elementAt(i)); + supportedLocales[i] = locale.clone(); + if (supportedLocales[i] == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + const Locale &supportedLocale = *supportedLocales[i]; + LSR &lsr = lsrs[i] = getMaximalLsrOrUnd(likelySubtags, supportedLocale, errorCode); + lsr.setHashCode(); + if (U_FAILURE(errorCode)) { return; } + if (idef < 0 && defLSR != nullptr && lsr == *defLSR) { + idef = i; + defLSR = &lsr; // owned pointer to put into supportedLsrToIndex + if (*def == supportedLocale) { + def = &supportedLocale; // owned pointer to keep + } + } + } + + // We need an unordered map from LSR to first supported locale with that LSR, + // and an ordered list of (LSR, supported index). + // We insert the supported locales in the following order: + // 1. Default locale, if it is supported. + // 2. Priority locales (aka "paradigm locales") in builder order. + // 3. Remaining locales in builder order. + // In Java, we use a LinkedHashMap for both map & ordered lists. + // In C++, we use separate structures. + // We over-allocate arrays of LSRs and indexes for simplicity. + // We reserve slots at the array starts for the default and paradigm locales, + // plus enough for all supported locales. + // If there are few paradigm locales and few duplicate supported LSRs, + // then the amount of wasted space is small. + supportedLsrToIndex = uhash_openSize(hashLSR, compareLSRs, uhash_compareLong, + supportedLocalesLength, &errorCode); + if (U_FAILURE(errorCode)) { return; } + int32_t paradigmLimit = 1 + localeDistance.getParadigmLSRsLength(); + int32_t suppLSRsCapacity = paradigmLimit + supportedLocalesLength; + supportedLSRs = static_cast( + uprv_malloc(suppLSRsCapacity * sizeof(const LSR *))); + supportedIndexes = static_cast( + uprv_malloc(suppLSRsCapacity * sizeof(int32_t))); + if (supportedLSRs == nullptr || supportedIndexes == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + int32_t paradigmIndex = 0; + int32_t otherIndex = paradigmLimit; + if (idef >= 0) { + uhash_puti(supportedLsrToIndex, const_cast(defLSR), idef + 1, &errorCode); + supportedLSRs[0] = defLSR; + supportedIndexes[0] = idef; + paradigmIndex = 1; + } + for (int32_t i = 0; i < supportedLocalesLength; ++i) { + if (i == idef) { continue; } + const Locale &locale = *supportedLocales[i]; + const LSR &lsr = lsrs[i]; + if (defLSR == nullptr) { + U_ASSERT(i == 0); + def = &locale; + defLSR = &lsr; + idef = 0; + uhash_puti(supportedLsrToIndex, const_cast(&lsr), 0 + 1, &errorCode); + supportedLSRs[0] = &lsr; + supportedIndexes[0] = 0; + paradigmIndex = 1; + } else if (idef >= 0 && lsr == *defLSR) { + // lsr == *defLSR means that this supported locale is + // a duplicate of the default locale. + // Either an explicit default locale is supported, and we added it before the loop, + // or there is no explicit default locale, and this is + // a duplicate of the first supported locale. + // In both cases, idef >= 0 now, so otherwise we can skip the comparison. + // For a duplicate, putIfAbsent() is a no-op, so nothing to do. + } else { + if (putIfAbsent(supportedLsrToIndex, lsr, i + 1, errorCode)) { + if (localeDistance.isParadigmLSR(lsr)) { + supportedLSRs[paradigmIndex] = &lsr; + supportedIndexes[paradigmIndex++] = i; + } else { + supportedLSRs[otherIndex] = &lsr; + supportedIndexes[otherIndex++] = i; + } + } + } + if (U_FAILURE(errorCode)) { return; } + } + // Squeeze out unused array slots. + if (paradigmIndex < paradigmLimit && paradigmLimit < otherIndex) { + uprv_memmove(supportedLSRs + paradigmIndex, supportedLSRs + paradigmLimit, + (otherIndex - paradigmLimit) * sizeof(const LSR *)); + uprv_memmove(supportedIndexes + paradigmIndex, supportedIndexes + paradigmLimit, + (otherIndex - paradigmLimit) * sizeof(int32_t)); + } + supportedLSRsLength = otherIndex - (paradigmLimit - paradigmIndex); + } + + if (def != nullptr && (idef < 0 || def != supportedLocales[idef])) { + ownedDefaultLocale = def->clone(); + if (ownedDefaultLocale == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + def = ownedDefaultLocale; + } + defaultLocale = def; + defaultLocaleIndex = idef; + + if (builder.demotion_ == ULOCMATCH_DEMOTION_REGION) { + demotionPerDesiredLocale = localeDistance.getDefaultDemotionPerDesiredLocale(); + } +} + +LocaleMatcher::LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT : + likelySubtags(src.likelySubtags), + localeDistance(src.localeDistance), + thresholdDistance(src.thresholdDistance), + demotionPerDesiredLocale(src.demotionPerDesiredLocale), + favorSubtag(src.favorSubtag), + supportedLocales(src.supportedLocales), lsrs(src.lsrs), + supportedLocalesLength(src.supportedLocalesLength), + supportedLsrToIndex(src.supportedLsrToIndex), + supportedLSRs(src.supportedLSRs), + supportedIndexes(src.supportedIndexes), + supportedLSRsLength(src.supportedLSRsLength), + ownedDefaultLocale(src.ownedDefaultLocale), defaultLocale(src.defaultLocale), + defaultLocaleIndex(src.defaultLocaleIndex) { + src.supportedLocales = nullptr; + src.lsrs = nullptr; + src.supportedLocalesLength = 0; + src.supportedLsrToIndex = nullptr; + src.supportedLSRs = nullptr; + src.supportedIndexes = nullptr; + src.supportedLSRsLength = 0; + src.ownedDefaultLocale = nullptr; + src.defaultLocale = nullptr; + src.defaultLocaleIndex = -1; +} + +LocaleMatcher::~LocaleMatcher() { + for (int32_t i = 0; i < supportedLocalesLength; ++i) { + delete supportedLocales[i]; + } + uprv_free(supportedLocales); + delete[] lsrs; + uhash_close(supportedLsrToIndex); + uprv_free(supportedLSRs); + uprv_free(supportedIndexes); + delete ownedDefaultLocale; +} + +LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { + this->~LocaleMatcher(); + + thresholdDistance = src.thresholdDistance; + demotionPerDesiredLocale = src.demotionPerDesiredLocale; + favorSubtag = src.favorSubtag; + supportedLocales = src.supportedLocales; + lsrs = src.lsrs; + supportedLocalesLength = src.supportedLocalesLength; + supportedLsrToIndex = src.supportedLsrToIndex; + supportedLSRs = src.supportedLSRs; + supportedIndexes = src.supportedIndexes; + supportedLSRsLength = src.supportedLSRsLength; + ownedDefaultLocale = src.ownedDefaultLocale; + defaultLocale = src.defaultLocale; + defaultLocaleIndex = src.defaultLocaleIndex; + + src.supportedLocales = nullptr; + src.lsrs = nullptr; + src.supportedLocalesLength = 0; + src.supportedLsrToIndex = nullptr; + src.supportedLSRs = nullptr; + src.supportedIndexes = nullptr; + src.supportedLSRsLength = 0; + src.ownedDefaultLocale = nullptr; + src.defaultLocale = nullptr; + src.defaultLocaleIndex = -1; + return *this; +} + +class LocaleLsrIterator { +public: + LocaleLsrIterator(const XLikelySubtags &likelySubtags, Locale::Iterator &locales, + ULocMatchLifetime lifetime) : + likelySubtags(likelySubtags), locales(locales), lifetime(lifetime) {} + + ~LocaleLsrIterator() { + if (lifetime == ULOCMATCH_TEMPORARY_LOCALES) { + delete remembered; + } + } + + bool hasNext() const { + return locales.hasNext(); + } + + LSR next(UErrorCode &errorCode) { + current = &locales.next(); + return getMaximalLsrOrUnd(likelySubtags, *current, errorCode); + } + + void rememberCurrent(int32_t desiredIndex, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + bestDesiredIndex = desiredIndex; + if (lifetime == ULOCMATCH_STORED_LOCALES) { + remembered = current; + } else { + // ULOCMATCH_TEMPORARY_LOCALES + delete remembered; + remembered = new Locale(*current); + if (remembered == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + } + } + } + + const Locale *orphanRemembered() { + const Locale *rem = remembered; + remembered = nullptr; + return rem; + } + + int32_t getBestDesiredIndex() const { + return bestDesiredIndex; + } + +private: + const XLikelySubtags &likelySubtags; + Locale::Iterator &locales; + ULocMatchLifetime lifetime; + const Locale *current = nullptr, *remembered = nullptr; + int32_t bestDesiredIndex = -1; +}; + +const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } + int32_t suppIndex = getBestSuppIndex( + getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), + nullptr, errorCode); + return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; +} + +const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } + if (!desiredLocales.hasNext()) { + return defaultLocale; + } + LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); + int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); + return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; +} + +const Locale *LocaleMatcher::getBestMatchForListString( + StringPiece desiredLocaleList, UErrorCode &errorCode) const { + LocalePriorityList list(desiredLocaleList, errorCode); + LocalePriorityList::Iterator iter = list.iterator(); + return getBestMatch(iter, errorCode); +} + +LocaleMatcher::Result LocaleMatcher::getBestMatchResult( + const Locale &desiredLocale, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + } + int32_t suppIndex = getBestSuppIndex( + getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), + nullptr, errorCode); + if (U_FAILURE(errorCode) || suppIndex < 0) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + } else { + return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, FALSE); + } +} + +LocaleMatcher::Result LocaleMatcher::getBestMatchResult( + Locale::Iterator &desiredLocales, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode) || !desiredLocales.hasNext()) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + } + LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); + int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); + if (U_FAILURE(errorCode) || suppIndex < 0) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + } else { + return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex], + lsrIter.getBestDesiredIndex(), suppIndex, TRUE); + } +} + +int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return -1; } + int32_t desiredIndex = 0; + int32_t bestSupportedLsrIndex = -1; + for (int32_t bestDistance = thresholdDistance;;) { + // Quick check for exact maximized LSR. + // Returns suppIndex+1 where 0 means not found. + if (supportedLsrToIndex != nullptr) { + desiredLSR.setHashCode(); + int32_t index = uhash_geti(supportedLsrToIndex, &desiredLSR); + if (index != 0) { + int32_t suppIndex = index - 1; + if (remainingIter != nullptr) { + remainingIter->rememberCurrent(desiredIndex, errorCode); + } + return suppIndex; + } + } + int32_t bestIndexAndDistance = localeDistance.getBestIndexAndDistance( + desiredLSR, supportedLSRs, supportedLSRsLength, bestDistance, favorSubtag); + if (bestIndexAndDistance >= 0) { + bestDistance = bestIndexAndDistance & 0xff; + if (remainingIter != nullptr) { + remainingIter->rememberCurrent(desiredIndex, errorCode); + if (U_FAILURE(errorCode)) { return -1; } + } + bestSupportedLsrIndex = bestIndexAndDistance >= 0 ? bestIndexAndDistance >> 8 : -1; + } + if ((bestDistance -= demotionPerDesiredLocale) <= 0) { + break; + } + if (remainingIter == nullptr || !remainingIter->hasNext()) { + break; + } + desiredLSR = remainingIter->next(errorCode); + if (U_FAILURE(errorCode)) { return -1; } + ++desiredIndex; + } + if (bestSupportedLsrIndex < 0) { + // no good match + return -1; + } + return supportedIndexes[bestSupportedLsrIndex]; +} + +double LocaleMatcher::internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const { + // Returns the inverse of the distance: That is, 1-distance(desired, supported). + LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); + if (U_FAILURE(errorCode)) { return 0; } + const LSR *pSuppLSR = &suppLSR; + int32_t distance = localeDistance.getBestIndexAndDistance( + getMaximalLsrOrUnd(likelySubtags, desired, errorCode), + &pSuppLSR, 1, + thresholdDistance, favorSubtag) & 0xff; + return (100 - distance) / 100.0; +} + +U_NAMESPACE_END + +#endif // __LOCMATCHER_H__ diff -Nru icu-64.2/source/common/localeprioritylist.cpp icu-65.1/source/common/localeprioritylist.cpp --- icu-64.2/source/common/localeprioritylist.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/localeprioritylist.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,239 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localeprioritylist.cpp +// created: 2019jul11 Markus W. Scherer + +#include "unicode/utypes.h" +#include "unicode/localpointer.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" +#include "charstr.h" +#include "cmemory.h" +#include "localeprioritylist.h" +#include "uarrsort.h" +#include "uassert.h" +#include "uhash.h" + +U_NAMESPACE_BEGIN + +namespace { + +int32_t hashLocale(const UHashTok token) { + auto *locale = static_cast(token.pointer); + return locale->hashCode(); +} + +UBool compareLocales(const UHashTok t1, const UHashTok t2) { + auto *l1 = static_cast(t1.pointer); + auto *l2 = static_cast(t2.pointer); + return *l1 == *l2; +} + +constexpr int32_t WEIGHT_ONE = 1000; + +struct LocaleAndWeight { + Locale *locale; + int32_t weight; // 0..1000 = 0.0..1.0 + int32_t index; // force stable sort + + int32_t compare(const LocaleAndWeight &other) const { + int32_t diff = other.weight - weight; // descending: other-this + if (diff != 0) { return diff; } + return index - other.index; + } +}; + +int32_t U_CALLCONV +compareLocaleAndWeight(const void * /*context*/, const void *left, const void *right) { + return static_cast(left)-> + compare(*static_cast(right)); +} + +const char *skipSpaces(const char *p, const char *limit) { + while (p < limit && *p == ' ') { ++p; } + return p; +} + +int32_t findTagLength(const char *p, const char *limit) { + // Look for accept-language delimiters. + // Leave other validation up to the Locale constructor. + const char *q; + for (q = p; q < limit; ++q) { + char c = *q; + if (c == ' ' || c == ',' || c == ';') { break; } + } + return static_cast(q - p); +} + +/** + * Parses and returns a qvalue weight in millis. + * Advances p to after the parsed substring. + * Returns a negative value if parsing fails. + */ +int32_t parseWeight(const char *&p, const char *limit) { + p = skipSpaces(p, limit); + char c; + if (p == limit || ((c = *p) != '0' && c != '1')) { return -1; } + int32_t weight = (c - '0') * 1000; + if (++p == limit || *p != '.') { return weight; } + int32_t multiplier = 100; + while (++p != limit && '0' <= (c = *p) && c <= '9') { + c -= '0'; + if (multiplier > 0) { + weight += c * multiplier; + multiplier /= 10; + } else if (multiplier == 0) { + // round up + if (c >= 5) { ++weight; } + multiplier = -1; + } // else ignore further fraction digits + } + return weight <= WEIGHT_ONE ? weight : -1; // bad if > 1.0 +} + +} // namespace + +/** + * Nothing but a wrapper over a MaybeStackArray of LocaleAndWeight. + * + * This wrapper exists (and is not in an anonymous namespace) + * so that we can forward-declare it in the header file and + * don't have to expose the MaybeStackArray specialization and + * the LocaleAndWeight to code (like the test) that #includes localeprioritylist.h. + * Also, otherwise we would have to do a platform-specific + * template export declaration of some kind for the MaybeStackArray specialization + * to be properly exported from the common DLL. + */ +struct LocaleAndWeightArray : public UMemory { + MaybeStackArray array; +}; + +LocalePriorityList::LocalePriorityList(StringPiece s, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + list = new LocaleAndWeightArray(); + if (list == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + const char *p = s.data(); + const char *limit = p + s.length(); + while ((p = skipSpaces(p, limit)) != limit) { + if (*p == ',') { // empty range field + ++p; + continue; + } + int32_t tagLength = findTagLength(p, limit); + if (tagLength == 0) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + CharString tag(p, tagLength, errorCode); + if (U_FAILURE(errorCode)) { return; } + Locale locale = Locale(tag.data()); + if (locale.isBogus()) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + int32_t weight = WEIGHT_ONE; + if ((p = skipSpaces(p + tagLength, limit)) != limit && *p == ';') { + if ((p = skipSpaces(p + 1, limit)) == limit || *p != 'q' || + (p = skipSpaces(p + 1, limit)) == limit || *p != '=' || + (++p, (weight = parseWeight(p, limit)) < 0)) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + p = skipSpaces(p, limit); + } + if (p != limit && *p != ',') { // trailing junk + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + add(locale, weight, errorCode); + if (p == limit) { break; } + ++p; + } + sort(errorCode); +} + +LocalePriorityList::~LocalePriorityList() { + if (list != nullptr) { + for (int32_t i = 0; i < listLength; ++i) { + delete list->array[i].locale; + } + delete list; + } + uhash_close(map); +} + +const Locale *LocalePriorityList::localeAt(int32_t i) const { + return list->array[i].locale; +} + +Locale *LocalePriorityList::orphanLocaleAt(int32_t i) { + if (list == nullptr) { return nullptr; } + LocaleAndWeight &lw = list->array[i]; + Locale *l = lw.locale; + lw.locale = nullptr; + return l; +} + +bool LocalePriorityList::add(const Locale &locale, int32_t weight, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return false; } + if (map == nullptr) { + if (weight <= 0) { return true; } // do not add q=0 + map = uhash_open(hashLocale, compareLocales, uhash_compareLong, &errorCode); + if (U_FAILURE(errorCode)) { return false; } + } + LocalPointer clone; + int32_t index = uhash_geti(map, &locale); + if (index != 0) { + // Duplicate: Remove the old item and append it anew. + LocaleAndWeight &lw = list->array[index - 1]; + clone.adoptInstead(lw.locale); + lw.locale = nullptr; + lw.weight = 0; + ++numRemoved; + } + if (weight <= 0) { // do not add q=0 + if (index != 0) { + // Not strictly necessary but cleaner. + uhash_removei(map, &locale); + } + return true; + } + if (clone.isNull()) { + clone.adoptInstead(locale.clone()); + if (clone.isNull() || (clone->isBogus() && !locale.isBogus())) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + } + if (listLength == list->array.getCapacity()) { + int32_t newCapacity = listLength < 50 ? 100 : 4 * listLength; + if (list->array.resize(newCapacity, listLength) == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + } + uhash_puti(map, clone.getAlias(), listLength + 1, &errorCode); + if (U_FAILURE(errorCode)) { return false; } + LocaleAndWeight &lw = list->array[listLength]; + lw.locale = clone.orphan(); + lw.weight = weight; + lw.index = listLength++; + if (weight < WEIGHT_ONE) { hasWeights = true; } + U_ASSERT(uhash_count(map) == getLength()); + return true; +} + +void LocalePriorityList::sort(UErrorCode &errorCode) { + // Sort by descending weights if there is a mix of weights. + // The comparator forces a stable sort via the item index. + if (U_FAILURE(errorCode) || getLength() <= 1 || !hasWeights) { return; } + uprv_sortArray(list->array.getAlias(), listLength, sizeof(LocaleAndWeight), + compareLocaleAndWeight, nullptr, FALSE, &errorCode); +} + +U_NAMESPACE_END diff -Nru icu-64.2/source/common/localeprioritylist.h icu-65.1/source/common/localeprioritylist.h --- icu-64.2/source/common/localeprioritylist.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/localeprioritylist.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,115 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localeprioritylist.h +// created: 2019jul11 Markus W. Scherer + +#ifndef __LOCALEPRIORITYLIST_H__ +#define __LOCALEPRIORITYLIST_H__ + +#include "unicode/utypes.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" + +struct UHashtable; + +U_NAMESPACE_BEGIN + +struct LocaleAndWeightArray; + +/** + * Parses a list of locales from an accept-language string. + * We are a bit more lenient than the spec: + * We accept extra whitespace in more places, empty range fields, + * and any number of qvalue fraction digits. + * + * https://tools.ietf.org/html/rfc2616#section-14.4 + * 14.4 Accept-Language + * + * Accept-Language = "Accept-Language" ":" + * 1#( language-range [ ";" "q" "=" qvalue ] ) + * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) + * + * Each language-range MAY be given an associated quality value which + * represents an estimate of the user's preference for the languages + * specified by that range. The quality value defaults to "q=1". For + * example, + * + * Accept-Language: da, en-gb;q=0.8, en;q=0.7 + * + * https://tools.ietf.org/html/rfc2616#section-3.9 + * 3.9 Quality Values + * + * HTTP content negotiation (section 12) uses short "floating point" + * numbers to indicate the relative importance ("weight") of various + * negotiable parameters. A weight is normalized to a real number in + * the range 0 through 1, where 0 is the minimum and 1 the maximum + * value. If a parameter has a quality value of 0, then content with + * this parameter is `not acceptable' for the client. HTTP/1.1 + * applications MUST NOT generate more than three digits after the + * decimal point. User configuration of these values SHOULD also be + * limited in this fashion. + * + * qvalue = ( "0" [ "." 0*3DIGIT ] ) + * | ( "1" [ "." 0*3("0") ] ) + */ +class U_COMMON_API LocalePriorityList : public UMemory { +public: + class Iterator : public Locale::Iterator { + public: + UBool hasNext() const override { return count < length; } + + const Locale &next() override { + for(;;) { + const Locale *locale = list.localeAt(index++); + if (locale != nullptr) { + ++count; + return *locale; + } + } + } + + private: + friend class LocalePriorityList; + + Iterator(const LocalePriorityList &list) : list(list), length(list.getLength()) {} + + const LocalePriorityList &list; + int32_t index = 0; + int32_t count = 0; + const int32_t length; + }; + + LocalePriorityList(StringPiece s, UErrorCode &errorCode); + + ~LocalePriorityList(); + + int32_t getLength() const { return listLength - numRemoved; } + + int32_t getLengthIncludingRemoved() const { return listLength; } + + Iterator iterator() const { return Iterator(*this); } + + const Locale *localeAt(int32_t i) const; + + Locale *orphanLocaleAt(int32_t i); + +private: + LocalePriorityList(const LocalePriorityList &) = delete; + LocalePriorityList &operator=(const LocalePriorityList &) = delete; + + bool add(const Locale &locale, int32_t weight, UErrorCode &errorCode); + + void sort(UErrorCode &errorCode); + + LocaleAndWeightArray *list = nullptr; + int32_t listLength = 0; + int32_t numRemoved = 0; + bool hasWeights = false; // other than 1.0 + UHashtable *map = nullptr; +}; + +U_NAMESPACE_END + +#endif // __LOCALEPRIORITYLIST_H__ diff -Nru icu-64.2/source/common/locavailable.cpp icu-65.1/source/common/locavailable.cpp --- icu-64.2/source/common/locavailable.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/locavailable.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -19,11 +19,13 @@ * that then do not depend on resource bundle code and res_index bundles. */ +#include "unicode/errorcode.h" #include "unicode/utypes.h" #include "unicode/locid.h" #include "unicode/uloc.h" #include "unicode/ures.h" #include "cmemory.h" +#include "cstring.h" #include "ucln_cmn.h" #include "uassert.h" #include "umutex.h" @@ -95,85 +97,174 @@ /* ### Constants **************************************************/ -/* These strings describe the resources we attempt to load from - the locale ResourceBundle data file.*/ -static const char _kIndexLocaleName[] = "res_index"; -static const char _kIndexTag[] = "InstalledLocales"; - -static char** _installedLocales = NULL; -static int32_t _installedLocalesCount = 0; -static icu::UInitOnce _installedLocalesInitOnce; +namespace { -/* ### Get available **************************************************/ +// Enough capacity for the two lists in the res_index.res file +const char** gAvailableLocaleNames[2] = {}; +int32_t gAvailableLocaleCounts[2] = {}; +icu::UInitOnce ginstalledLocalesInitOnce = U_INITONCE_INITIALIZER; + +class AvailableLocalesSink : public ResourceSink { + public: + void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) U_OVERRIDE { + ResourceTable resIndexTable = value.getTable(status); + if (U_FAILURE(status)) { + return; + } + for (int32_t i = 0; resIndexTable.getKeyAndValue(i, key, value); ++i) { + ULocAvailableType type; + if (uprv_strcmp(key, "InstalledLocales") == 0) { + type = ULOC_AVAILABLE_DEFAULT; + } else if (uprv_strcmp(key, "AliasLocales") == 0) { + type = ULOC_AVAILABLE_ONLY_LEGACY_ALIASES; + } else { + // CLDRVersion, etc. + continue; + } + ResourceTable availableLocalesTable = value.getTable(status); + if (U_FAILURE(status)) { + return; + } + gAvailableLocaleCounts[type] = availableLocalesTable.getSize(); + gAvailableLocaleNames[type] = static_cast( + uprv_malloc(gAvailableLocaleCounts[type] * sizeof(const char*))); + if (gAvailableLocaleNames[type] == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t j = 0; availableLocalesTable.getKeyAndValue(j, key, value); ++j) { + gAvailableLocaleNames[type][j] = key; + } + } + } +}; -static UBool U_CALLCONV uloc_cleanup(void) { - char ** temp; +class AvailableLocalesStringEnumeration : public StringEnumeration { + public: + AvailableLocalesStringEnumeration(ULocAvailableType type) : fType(type) { + } + + const char* next(int32_t *resultLength, UErrorCode&) override { + ULocAvailableType actualType = fType; + int32_t actualIndex = fIndex++; + + // If the "combined" list was requested, resolve that now + if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) { + int32_t defaultLocalesCount = gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT]; + if (actualIndex < defaultLocalesCount) { + actualType = ULOC_AVAILABLE_DEFAULT; + } else { + actualIndex -= defaultLocalesCount; + actualType = ULOC_AVAILABLE_ONLY_LEGACY_ALIASES; + } + } + + // Return the requested string + int32_t count = gAvailableLocaleCounts[actualType]; + const char* result; + if (actualIndex < count) { + result = gAvailableLocaleNames[actualType][actualIndex]; + if (resultLength != nullptr) { + *resultLength = static_cast(uprv_strlen(result)); + } + } else { + result = nullptr; + if (resultLength != nullptr) { + *resultLength = 0; + } + } + return result; + } + + void reset(UErrorCode&) override { + fIndex = 0; + } - if (_installedLocales) { - temp = _installedLocales; - _installedLocales = NULL; + int32_t count(UErrorCode&) const override { + if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) { + return gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT] + + gAvailableLocaleCounts[ULOC_AVAILABLE_ONLY_LEGACY_ALIASES]; + } else { + return gAvailableLocaleCounts[fType]; + } + } - _installedLocalesCount = 0; - _installedLocalesInitOnce.reset(); + private: + ULocAvailableType fType; + int32_t fIndex = 0; +}; - uprv_free(temp); +/* ### Get available **************************************************/ + +static UBool U_CALLCONV uloc_cleanup(void) { + for (int32_t i = 0; i < UPRV_LENGTHOF(gAvailableLocaleNames); i++) { + uprv_free(gAvailableLocaleNames[i]); + gAvailableLocaleNames[i] = nullptr; + gAvailableLocaleCounts[i] = 0; } + ginstalledLocalesInitOnce.reset(); return TRUE; } // Load Installed Locales. This function will be called exactly once // via the initOnce mechanism. -static void U_CALLCONV loadInstalledLocales() { - UErrorCode status = U_ZERO_ERROR; - int32_t i = 0; - int32_t localeCount; - - U_ASSERT(_installedLocales == NULL); - U_ASSERT(_installedLocalesCount == 0); - - _installedLocalesCount = 0; +static void U_CALLCONV loadInstalledLocales(UErrorCode& status) { + ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); - icu::LocalUResourceBundlePointer indexLocale(ures_openDirect(NULL, _kIndexLocaleName, &status)); - icu::StackUResourceBundle installed; - - ures_getByKey(indexLocale.getAlias(), _kIndexTag, installed.getAlias(), &status); - - if(U_SUCCESS(status)) { - localeCount = ures_getSize(installed.getAlias()); - _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1)); - if (_installedLocales != NULL) { - ures_resetIterator(installed.getAlias()); - while(ures_hasNext(installed.getAlias())) { - ures_getNextString(installed.getAlias(), NULL, (const char **)&_installedLocales[i++], &status); - } - _installedLocales[i] = NULL; - _installedLocalesCount = localeCount; - ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); - } - } + icu::LocalUResourceBundlePointer rb(ures_openDirect(NULL, "res_index", &status)); + AvailableLocalesSink sink; + ures_getAllItemsWithFallback(rb.getAlias(), "", sink, status); } -static void _load_installedLocales() -{ - umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales); +void _load_installedLocales(UErrorCode& status) { + umtx_initOnce(ginstalledLocalesInitOnce, &loadInstalledLocales, status); } +} // namespace + U_CAPI const char* U_EXPORT2 -uloc_getAvailable(int32_t offset) -{ - - _load_installedLocales(); - - if (offset > _installedLocalesCount) - return NULL; - return _installedLocales[offset]; +uloc_getAvailable(int32_t offset) { + icu::ErrorCode status; + _load_installedLocales(status); + if (status.isFailure()) { + return nullptr; + } + if (offset > gAvailableLocaleCounts[0]) { + // *status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + return gAvailableLocaleNames[0][offset]; } U_CAPI int32_t U_EXPORT2 -uloc_countAvailable() -{ - _load_installedLocales(); - return _installedLocalesCount; +uloc_countAvailable() { + icu::ErrorCode status; + _load_installedLocales(status); + if (status.isFailure()) { + return 0; + } + return gAvailableLocaleCounts[0]; +} + +U_CAPI UEnumeration* U_EXPORT2 +uloc_openAvailableByType(ULocAvailableType type, UErrorCode* status) { + if (U_FAILURE(*status)) { + return nullptr; + } + if (type < 0 || type >= ULOC_AVAILABLE_COUNT) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + _load_installedLocales(*status); + if (U_FAILURE(*status)) { + return nullptr; + } + LocalPointer result( + new AvailableLocalesStringEnumeration(type), *status); + if (U_FAILURE(*status)) { + return nullptr; + } + return uenum_openFromStringEnumeration(result.orphan(), status); } diff -Nru icu-64.2/source/common/locbased.h icu-65.1/source/common/locbased.h --- icu-64.2/source/common/locbased.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/locbased.h 2019-10-03 11:16:41.000000000 +0000 @@ -22,7 +22,7 @@ * `actualLocale' of size ULOC_FULLNAME_CAPACITY */ #define U_LOCALE_BASED(varname, objname) \ - LocaleBased varname((objname).validLocale, (objname).actualLocale); + LocaleBased varname((objname).validLocale, (objname).actualLocale) U_NAMESPACE_BEGIN diff -Nru icu-64.2/source/common/locdistance.cpp icu-65.1/source/common/locdistance.cpp --- icu-64.2/source/common/locdistance.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/locdistance.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,364 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// locdistance.cpp +// created: 2019may08 Markus W. Scherer + +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "unicode/ures.h" +#include "cstring.h" +#include "locdistance.h" +#include "loclikelysubtags.h" +#include "uassert.h" +#include "ucln_cmn.h" +#include "uinvchar.h" +#include "umutex.h" + +U_NAMESPACE_BEGIN + +namespace { + +/** + * Bit flag used on the last character of a subtag in the trie. + * Must be set consistently by the builder and the lookup code. + */ +constexpr int32_t END_OF_SUBTAG = 0x80; +/** Distance value bit flag, set by the builder. */ +constexpr int32_t DISTANCE_SKIP_SCRIPT = 0x80; +/** Distance value bit flag, set by trieNext(). */ +constexpr int32_t DISTANCE_IS_FINAL = 0x100; +constexpr int32_t DISTANCE_IS_FINAL_OR_SKIP_SCRIPT = DISTANCE_IS_FINAL | DISTANCE_SKIP_SCRIPT; + +constexpr int32_t ABOVE_THRESHOLD = 100; + +// Indexes into array of distances. +enum { + IX_DEF_LANG_DISTANCE, + IX_DEF_SCRIPT_DISTANCE, + IX_DEF_REGION_DISTANCE, + IX_MIN_REGION_DISTANCE, + IX_LIMIT +}; + +LocaleDistance *gLocaleDistance = nullptr; +UInitOnce gInitOnce = U_INITONCE_INITIALIZER; + +UBool U_CALLCONV cleanup() { + delete gLocaleDistance; + gLocaleDistance = nullptr; + gInitOnce.reset(); + return TRUE; +} + +} // namespace + +void U_CALLCONV LocaleDistance::initLocaleDistance(UErrorCode &errorCode) { + // This function is invoked only via umtx_initOnce(). + U_ASSERT(gLocaleDistance == nullptr); + const XLikelySubtags &likely = *XLikelySubtags::getSingleton(errorCode); + if (U_FAILURE(errorCode)) { return; } + const LocaleDistanceData &data = likely.getDistanceData(); + if (data.distanceTrieBytes == nullptr || + data.regionToPartitions == nullptr || data.partitions == nullptr || + // ok if no paradigms + data.distances == nullptr) { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } + gLocaleDistance = new LocaleDistance(data); + if (gLocaleDistance == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_common_registerCleanup(UCLN_COMMON_LOCALE_DISTANCE, cleanup); +} + +const LocaleDistance *LocaleDistance::getSingleton(UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + umtx_initOnce(gInitOnce, &LocaleDistance::initLocaleDistance, errorCode); + return gLocaleDistance; +} + +LocaleDistance::LocaleDistance(const LocaleDistanceData &data) : + trie(data.distanceTrieBytes), + regionToPartitionsIndex(data.regionToPartitions), partitionArrays(data.partitions), + paradigmLSRs(data.paradigms), paradigmLSRsLength(data.paradigmsLength), + defaultLanguageDistance(data.distances[IX_DEF_LANG_DISTANCE]), + defaultScriptDistance(data.distances[IX_DEF_SCRIPT_DISTANCE]), + defaultRegionDistance(data.distances[IX_DEF_REGION_DISTANCE]), + minRegionDistance(data.distances[IX_MIN_REGION_DISTANCE]) { + // For the default demotion value, use the + // default region distance between unrelated Englishes. + // Thus, unless demotion is turned off, + // a mere region difference for one desired locale + // is as good as a perfect match for the next following desired locale. + // As of CLDR 36, we have . + LSR en("en", "Latn", "US"); + LSR enGB("en", "Latn", "GB"); + const LSR *p_enGB = &enGB; + defaultDemotionPerDesiredLocale = getBestIndexAndDistance(en, &p_enGB, 1, + 50, ULOCMATCH_FAVOR_LANGUAGE) & 0xff; +} + +int32_t LocaleDistance::getBestIndexAndDistance( + const LSR &desired, + const LSR **supportedLSRs, int32_t supportedLSRsLength, + int32_t threshold, ULocMatchFavorSubtag favorSubtag) const { + BytesTrie iter(trie); + // Look up the desired language only once for all supported LSRs. + // Its "distance" is either a match point value of 0, or a non-match negative value. + // Note: The data builder verifies that there are no <*, supported> or rules. + int32_t desLangDistance = trieNext(iter, desired.language, false); + uint64_t desLangState = desLangDistance >= 0 && supportedLSRsLength > 1 ? iter.getState64() : 0; + // Index of the supported LSR with the lowest distance. + int32_t bestIndex = -1; + for (int32_t slIndex = 0; slIndex < supportedLSRsLength; ++slIndex) { + const LSR &supported = *supportedLSRs[slIndex]; + bool star = false; + int32_t distance = desLangDistance; + if (distance >= 0) { + U_ASSERT((distance & DISTANCE_IS_FINAL) == 0); + if (slIndex != 0) { + iter.resetToState64(desLangState); + } + distance = trieNext(iter, supported.language, true); + } + // Note: The data builder verifies that there are no rules with "any" (*) language and + // real (non *) script or region subtags. + // This means that if the lookup for either language fails we can use + // the default distances without further lookups. + int32_t flags; + if (distance >= 0) { + flags = distance & DISTANCE_IS_FINAL_OR_SKIP_SCRIPT; + distance &= ~DISTANCE_IS_FINAL_OR_SKIP_SCRIPT; + } else { // <*, *> + if (uprv_strcmp(desired.language, supported.language) == 0) { + distance = 0; + } else { + distance = defaultLanguageDistance; + } + flags = 0; + star = true; + } + U_ASSERT(0 <= distance && distance <= 100); + // We implement "favor subtag" by reducing the language subtag distance + // (unscientifically reducing it to a quarter of the normal value), + // so that the script distance is relatively more important. + // For example, given a default language distance of 80, we reduce it to 20, + // which is below the default threshold of 50, which is the default script distance. + if (favorSubtag == ULOCMATCH_FAVOR_SCRIPT) { + distance >>= 2; + } + if (distance >= threshold) { + continue; + } + + int32_t scriptDistance; + if (star || flags != 0) { + if (uprv_strcmp(desired.script, supported.script) == 0) { + scriptDistance = 0; + } else { + scriptDistance = defaultScriptDistance; + } + } else { + scriptDistance = getDesSuppScriptDistance(iter, iter.getState64(), + desired.script, supported.script); + flags = scriptDistance & DISTANCE_IS_FINAL; + scriptDistance &= ~DISTANCE_IS_FINAL; + } + distance += scriptDistance; + if (distance >= threshold) { + continue; + } + + if (uprv_strcmp(desired.region, supported.region) == 0) { + // regionDistance = 0 + } else if (star || (flags & DISTANCE_IS_FINAL) != 0) { + distance += defaultRegionDistance; + } else { + int32_t remainingThreshold = threshold - distance; + if (minRegionDistance >= remainingThreshold) { + continue; + } + + // From here on we know the regions are not equal. + // Map each region to zero or more partitions. (zero = one non-matching string) + // (Each array of single-character partition strings is encoded as one string.) + // If either side has more than one, then we find the maximum distance. + // This could be optimized by adding some more structure, but probably not worth it. + distance += getRegionPartitionsDistance( + iter, iter.getState64(), + partitionsForRegion(desired), + partitionsForRegion(supported), + remainingThreshold); + } + if (distance < threshold) { + if (distance == 0) { + return slIndex << 8; + } + bestIndex = slIndex; + threshold = distance; + } + } + return bestIndex >= 0 ? (bestIndex << 8) | threshold : 0xffffff00 | ABOVE_THRESHOLD; +} + +int32_t LocaleDistance::getDesSuppScriptDistance( + BytesTrie &iter, uint64_t startState, const char *desired, const char *supported) { + // Note: The data builder verifies that there are no <*, supported> or rules. + int32_t distance = trieNext(iter, desired, false); + if (distance >= 0) { + distance = trieNext(iter, supported, true); + } + if (distance < 0) { + UStringTrieResult result = iter.resetToState64(startState).next(u'*'); // <*, *> + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + if (uprv_strcmp(desired, supported) == 0) { + distance = 0; // same script + } else { + distance = iter.getValue(); + U_ASSERT(distance >= 0); + } + if (result == USTRINGTRIE_FINAL_VALUE) { + distance |= DISTANCE_IS_FINAL; + } + } + return distance; +} + +int32_t LocaleDistance::getRegionPartitionsDistance( + BytesTrie &iter, uint64_t startState, + const char *desiredPartitions, const char *supportedPartitions, int32_t threshold) { + char desired = *desiredPartitions++; + char supported = *supportedPartitions++; + U_ASSERT(desired != 0 && supported != 0); + // See if we have single desired/supported partitions, from NUL-terminated + // partition strings without explicit length. + bool suppLengthGt1 = *supportedPartitions != 0; // gt1: more than 1 character + // equivalent to: if (desLength == 1 && suppLength == 1) + if (*desiredPartitions == 0 && !suppLengthGt1) { + // Fastpath for single desired/supported partitions. + UStringTrieResult result = iter.next(uprv_invCharToAscii(desired) | END_OF_SUBTAG); + if (USTRINGTRIE_HAS_NEXT(result)) { + result = iter.next(uprv_invCharToAscii(supported) | END_OF_SUBTAG); + if (USTRINGTRIE_HAS_VALUE(result)) { + return iter.getValue(); + } + } + return getFallbackRegionDistance(iter, startState); + } + + const char *supportedStart = supportedPartitions - 1; // for restart of inner loop + int32_t regionDistance = 0; + // Fall back to * only once, not for each pair of partition strings. + bool star = false; + for (;;) { + // Look up each desired-partition string only once, + // not for each (desired, supported) pair. + UStringTrieResult result = iter.next(uprv_invCharToAscii(desired) | END_OF_SUBTAG); + if (USTRINGTRIE_HAS_NEXT(result)) { + uint64_t desState = suppLengthGt1 ? iter.getState64() : 0; + for (;;) { + result = iter.next(uprv_invCharToAscii(supported) | END_OF_SUBTAG); + int32_t d; + if (USTRINGTRIE_HAS_VALUE(result)) { + d = iter.getValue(); + } else if (star) { + d = 0; + } else { + d = getFallbackRegionDistance(iter, startState); + star = true; + } + if (d >= threshold) { + return d; + } else if (regionDistance < d) { + regionDistance = d; + } + if ((supported = *supportedPartitions++) != 0) { + iter.resetToState64(desState); + } else { + break; + } + } + } else if (!star) { + int32_t d = getFallbackRegionDistance(iter, startState); + if (d >= threshold) { + return d; + } else if (regionDistance < d) { + regionDistance = d; + } + star = true; + } + if ((desired = *desiredPartitions++) != 0) { + iter.resetToState64(startState); + supportedPartitions = supportedStart; + supported = *supportedPartitions++; + } else { + break; + } + } + return regionDistance; +} + +int32_t LocaleDistance::getFallbackRegionDistance(BytesTrie &iter, uint64_t startState) { +#if U_DEBUG + UStringTrieResult result = +#endif + iter.resetToState64(startState).next(u'*'); // <*, *> + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + int32_t distance = iter.getValue(); + U_ASSERT(distance >= 0); + return distance; +} + +int32_t LocaleDistance::trieNext(BytesTrie &iter, const char *s, bool wantValue) { + uint8_t c; + if ((c = *s) == 0) { + return -1; // no empty subtags in the distance data + } + for (;;) { + c = uprv_invCharToAscii(c); + // EBCDIC: If *s is not an invariant character, + // then c is now 0 and will simply not match anything, which is harmless. + uint8_t next = *++s; + if (next != 0) { + if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) { + return -1; + } + } else { + // last character of this subtag + UStringTrieResult result = iter.next(c | END_OF_SUBTAG); + if (wantValue) { + if (USTRINGTRIE_HAS_VALUE(result)) { + int32_t value = iter.getValue(); + if (result == USTRINGTRIE_FINAL_VALUE) { + value |= DISTANCE_IS_FINAL; + } + return value; + } + } else { + if (USTRINGTRIE_HAS_NEXT(result)) { + return 0; + } + } + return -1; + } + c = next; + } +} + +UBool LocaleDistance::isParadigmLSR(const LSR &lsr) const { + // Linear search for a very short list (length 6 as of 2019). + // If there are many paradigm LSRs we should use a hash set. + U_ASSERT(paradigmLSRsLength <= 15); + for (int32_t i = 0; i < paradigmLSRsLength; ++i) { + if (lsr == paradigmLSRs[i]) { return true; } + } + return false; +} + +U_NAMESPACE_END diff -Nru icu-64.2/source/common/locdistance.h icu-65.1/source/common/locdistance.h --- icu-64.2/source/common/locdistance.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/locdistance.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,109 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// locdistance.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCDISTANCE_H__ +#define __LOCDISTANCE_H__ + +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "lsr.h" + +U_NAMESPACE_BEGIN + +struct LocaleDistanceData; + +/** + * Offline-built data for LocaleMatcher. + * Mostly but not only the data for mapping locales to their maximized forms. + */ +class LocaleDistance final : public UMemory { +public: + static const LocaleDistance *getSingleton(UErrorCode &errorCode); + + /** + * Finds the supported LSR with the smallest distance from the desired one. + * Equivalent LSR subtags must be normalized into a canonical form. + * + *

    Returns the index of the lowest-distance supported LSR in bits 31..8 + * (negative if none has a distance below the threshold), + * and its distance (0..ABOVE_THRESHOLD) in bits 7..0. + */ + int32_t getBestIndexAndDistance(const LSR &desired, + const LSR **supportedLSRs, int32_t supportedLSRsLength, + int32_t threshold, ULocMatchFavorSubtag favorSubtag) const; + + int32_t getParadigmLSRsLength() const { return paradigmLSRsLength; } + + UBool isParadigmLSR(const LSR &lsr) const; + + int32_t getDefaultScriptDistance() const { + return defaultScriptDistance; + } + + int32_t getDefaultDemotionPerDesiredLocale() const { + return defaultDemotionPerDesiredLocale; + } + +private: + LocaleDistance(const LocaleDistanceData &data); + LocaleDistance(const LocaleDistance &other) = delete; + LocaleDistance &operator=(const LocaleDistance &other) = delete; + + static void initLocaleDistance(UErrorCode &errorCode); + + static int32_t getDesSuppScriptDistance(BytesTrie &iter, uint64_t startState, + const char *desired, const char *supported); + + static int32_t getRegionPartitionsDistance( + BytesTrie &iter, uint64_t startState, + const char *desiredPartitions, const char *supportedPartitions, + int32_t threshold); + + static int32_t getFallbackRegionDistance(BytesTrie &iter, uint64_t startState); + + static int32_t trieNext(BytesTrie &iter, const char *s, bool wantValue); + + const char *partitionsForRegion(const LSR &lsr) const { + // ill-formed region -> one non-matching string + int32_t pIndex = regionToPartitionsIndex[lsr.regionIndex]; + return partitionArrays[pIndex]; + } + + int32_t getDefaultRegionDistance() const { + return defaultRegionDistance; + } + + // The trie maps each dlang+slang+dscript+sscript+dregion+sregion + // (encoded in ASCII with bit 7 set on the last character of each subtag) to a distance. + // There is also a trie value for each subsequence of whole subtags. + // One '*' is used for a (desired, supported) pair of "und", "Zzzz"/"", or "ZZ"/"". + BytesTrie trie; + + /** + * Maps each region to zero or more single-character partitions. + */ + const uint8_t *regionToPartitionsIndex; + const char **partitionArrays; + + /** + * Used to get the paradigm region for a cluster, if there is one. + */ + const LSR *paradigmLSRs; + int32_t paradigmLSRsLength; + + int32_t defaultLanguageDistance; + int32_t defaultScriptDistance; + int32_t defaultRegionDistance; + int32_t minRegionDistance; + int32_t defaultDemotionPerDesiredLocale; +}; + +U_NAMESPACE_END + +#endif // __LOCDISTANCE_H__ diff -Nru icu-64.2/source/common/locdspnm.cpp icu-65.1/source/common/locdspnm.cpp --- icu-64.2/source/common/locdspnm.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/locdspnm.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -291,6 +291,7 @@ UnicodeString formatCloseParen; UnicodeString formatReplaceCloseParen; UDisplayContext nameLength; + UDisplayContext substitute; // Constants for capitalization context usage types. enum CapContextUsage { @@ -337,7 +338,7 @@ UnicodeString& result) const; private: UnicodeString& localeIdName(const char* localeId, - UnicodeString& result) const; + UnicodeString& result, bool substitute) const; UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const; UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const; UnicodeString& scriptDisplayName(const char* script, UnicodeString& result, UBool skipAdjust) const; @@ -359,6 +360,7 @@ , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) , capitalizationBrkIter(NULL) , nameLength(UDISPCTX_LENGTH_FULL) + , substitute(UDISPCTX_SUBSTITUTE) { initialize(); } @@ -371,6 +373,7 @@ , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) , capitalizationBrkIter(NULL) , nameLength(UDISPCTX_LENGTH_FULL) + , substitute(UDISPCTX_SUBSTITUTE) { while (length-- > 0) { UDisplayContext value = *contexts++; @@ -385,6 +388,9 @@ case UDISPCTX_TYPE_DISPLAY_LENGTH: nameLength = value; break; + case UDISPCTX_TYPE_SUBSTITUTE_HANDLING: + substitute = value; + break; default: break; } @@ -535,6 +541,8 @@ return capitalizationContext; case UDISPCTX_TYPE_DISPLAY_LENGTH: return nameLength; + case UDISPCTX_TYPE_SUBSTITUTE_HANDLING: + return substitute; default: break; } @@ -549,7 +557,7 @@ if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL && ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) { // note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE - static UMutex capitalizationBrkIterLock = U_MUTEX_INITIALIZER; + static UMutex capitalizationBrkIterLock; Mutex lock(&capitalizationBrkIterLock); result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); } @@ -583,7 +591,7 @@ do { // loop construct is so we can break early out of search if (hasScript && hasCountry) { ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0); - localeIdName(buffer, resultName); + localeIdName(buffer, resultName, false); if (!resultName.isBogus()) { hasScript = FALSE; hasCountry = FALSE; @@ -592,7 +600,7 @@ } if (hasScript) { ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0); - localeIdName(buffer, resultName); + localeIdName(buffer, resultName, false); if (!resultName.isBogus()) { hasScript = FALSE; break; @@ -600,7 +608,7 @@ } if (hasCountry) { ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0); - localeIdName(buffer, resultName); + localeIdName(buffer, resultName, false); if (!resultName.isBogus()) { hasCountry = FALSE; break; @@ -609,7 +617,11 @@ } while (FALSE); } if (resultName.isBogus() || resultName.isEmpty()) { - localeIdName(lang, resultName); + localeIdName(lang, resultName, substitute == UDISPCTX_SUBSTITUTE); + if (resultName.isBogus()) { + result.setToBogus(); + return result; + } } UnicodeString resultRemainder; @@ -617,13 +629,28 @@ UErrorCode status = U_ZERO_ERROR; if (hasScript) { - resultRemainder.append(scriptDisplayName(script, temp, TRUE)); + UnicodeString script_str = scriptDisplayName(script, temp, TRUE); + if (script_str.isBogus()) { + result.setToBogus(); + return result; + } + resultRemainder.append(script_str); } if (hasCountry) { - appendWithSep(resultRemainder, regionDisplayName(country, temp, TRUE)); + UnicodeString region_str = regionDisplayName(country, temp, TRUE); + if (region_str.isBogus()) { + result.setToBogus(); + return result; + } + appendWithSep(resultRemainder, region_str); } if (hasVariant) { - appendWithSep(resultRemainder, variantDisplayName(variant, temp, TRUE)); + UnicodeString variant_str = variantDisplayName(variant, temp, TRUE); + if (variant_str.isBogus()) { + result.setToBogus(); + return result; + } + appendWithSep(resultRemainder, variant_str); } resultRemainder.findAndReplace(formatOpenParen, formatReplaceOpenParen); resultRemainder.findAndReplace(formatCloseParen, formatReplaceCloseParen); @@ -689,14 +716,18 @@ // private UnicodeString& LocaleDisplayNamesImpl::localeIdName(const char* localeId, - UnicodeString& result) const { + UnicodeString& result, bool substitute) const { if (nameLength == UDISPCTX_LENGTH_SHORT) { langData.getNoFallback("Languages%short", localeId, result); if (!result.isBogus()) { return result; } } - return langData.getNoFallback("Languages", localeId, result); + if (substitute) { + return langData.get("Languages", localeId, result); + } else { + return langData.getNoFallback("Languages", localeId, result); + } } UnicodeString& @@ -706,12 +737,16 @@ return result = UnicodeString(lang, -1, US_INV); } if (nameLength == UDISPCTX_LENGTH_SHORT) { - langData.get("Languages%short", lang, result); + langData.getNoFallback("Languages%short", lang, result); if (!result.isBogus()) { return adjustForUsageAndContext(kCapContextUsageLanguage, result); } } - langData.get("Languages", lang, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Languages", lang, result); + } else { + langData.getNoFallback("Languages", lang, result); + } return adjustForUsageAndContext(kCapContextUsageLanguage, result); } @@ -720,12 +755,16 @@ UnicodeString& result, UBool skipAdjust) const { if (nameLength == UDISPCTX_LENGTH_SHORT) { - langData.get("Scripts%short", script, result); + langData.getNoFallback("Scripts%short", script, result); if (!result.isBogus()) { return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result); } } - langData.get("Scripts", script, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Scripts", script, result); + } else { + langData.getNoFallback("Scripts", script, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result); } @@ -746,12 +785,16 @@ UnicodeString& result, UBool skipAdjust) const { if (nameLength == UDISPCTX_LENGTH_SHORT) { - regionData.get("Countries%short", region, result); + regionData.getNoFallback("Countries%short", region, result); if (!result.isBogus()) { return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result); } } - regionData.get("Countries", region, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + regionData.get("Countries", region, result); + } else { + regionData.getNoFallback("Countries", region, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result); } @@ -767,7 +810,11 @@ UnicodeString& result, UBool skipAdjust) const { // don't have a resource for short variant names - langData.get("Variants", variant, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Variants", variant, result); + } else { + langData.getNoFallback("Variants", variant, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageVariant, result); } @@ -782,7 +829,11 @@ UnicodeString& result, UBool skipAdjust) const { // don't have a resource for short key names - langData.get("Keys", key, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Keys", key, result); + } else { + langData.getNoFallback("Keys", key, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKey, result); } @@ -802,9 +853,8 @@ UErrorCode sts = U_ZERO_ERROR; UnicodeString ustrValue(value, -1, US_INV); int32_t len; - UBool isChoice = FALSE; const UChar *currencyName = ucurr_getName(ustrValue.getTerminatedBuffer(), - locale.getBaseName(), UCURR_LONG_NAME, &isChoice, &len, &sts); + locale.getBaseName(), UCURR_LONG_NAME, nullptr /* isChoiceFormat */, &len, &sts); if (U_FAILURE(sts)) { // Return the value as is on failure result = ustrValue; @@ -815,12 +865,16 @@ } if (nameLength == UDISPCTX_LENGTH_SHORT) { - langData.get("Types%short", key, value, result); + langData.getNoFallback("Types%short", key, value, result); if (!result.isBogus()) { return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result); } } - langData.get("Types", key, value, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Types", key, value, result); + } else { + langData.getNoFallback("Types", key, value, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result); } diff -Nru icu-64.2/source/common/locid.cpp icu-65.1/source/common/locid.cpp --- icu-64.2/source/common/locid.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/locid.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -38,19 +38,19 @@ #include "unicode/strenum.h" #include "unicode/stringpiece.h" #include "unicode/uloc.h" -#include "putilimp.h" -#include "mutex.h" -#include "umutex.h" -#include "uassert.h" + +#include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" +#include "mutex.h" +#include "putilimp.h" #include "uassert.h" +#include "ucln_cmn.h" #include "uhash.h" #include "ulocimp.h" -#include "ucln_cmn.h" +#include "umutex.h" #include "ustr_imp.h" -#include "charstr.h" -#include "bytesinkutil.h" U_CDECL_BEGIN static UBool U_CALLCONV locale_cleanup(void); @@ -62,10 +62,7 @@ static UInitOnce gLocaleCacheInitOnce = U_INITONCE_INITIALIZER; // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale. -static UMutex *gDefaultLocaleMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gDefaultLocaleMutex; static UHashtable *gDefaultLocalesHashT = NULL; static Locale *gDefaultLocale = NULL; @@ -174,7 +171,7 @@ Locale *locale_set_default_internal(const char *id, UErrorCode& status) { // Synchronize this entire function. - Mutex lock(gDefaultLocaleMutex()); + Mutex lock(&gDefaultLocaleMutex); UBool canonicalize = FALSE; @@ -711,7 +708,7 @@ Locale::getDefault() { { - Mutex lock(gDefaultLocaleMutex()); + Mutex lock(&gDefaultLocaleMutex); if (gDefaultLocale != NULL) { return *gDefaultLocale; } @@ -1399,5 +1396,7 @@ return baseName; } +Locale::Iterator::~Iterator() = default; + //eof U_NAMESPACE_END diff -Nru icu-64.2/source/common/loclikely.cpp icu-65.1/source/common/loclikely.cpp --- icu-64.2/source/common/loclikely.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/loclikely.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -807,24 +807,24 @@ return FALSE; } -#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) \ - { int32_t count = 0; \ - int32_t i; \ - for (i = 0; i < trailingLength; i++) { \ - if (trailing[i] == '-' || trailing[i] == '_') { \ - count = 0; \ - if (count > 8) { \ - goto error; \ - } \ - } else if (trailing[i] == '@') { \ - break; \ - } else if (count > 8) { \ +#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) UPRV_BLOCK_MACRO_BEGIN { \ + int32_t count = 0; \ + int32_t i; \ + for (i = 0; i < trailingLength; i++) { \ + if (trailing[i] == '-' || trailing[i] == '_') { \ + count = 0; \ + if (count > 8) { \ goto error; \ - } else { \ - count++; \ } \ + } else if (trailing[i] == '@') { \ + break; \ + } else if (count > 8) { \ + goto error; \ + } else { \ + count++; \ } \ - } + } \ +} UPRV_BLOCK_MACRO_END static void _uloc_addLikelySubtags(const char* localeID, diff -Nru icu-64.2/source/common/loclikelysubtags.cpp icu-65.1/source/common/loclikelysubtags.cpp --- icu-64.2/source/common/loclikelysubtags.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/loclikelysubtags.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,638 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// loclikelysubtags.cpp +// created: 2019may08 Markus W. Scherer + +#include +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/localpointer.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "unicode/ures.h" +#include "charstr.h" +#include "cstring.h" +#include "loclikelysubtags.h" +#include "lsr.h" +#include "uassert.h" +#include "ucln_cmn.h" +#include "uhash.h" +#include "uinvchar.h" +#include "umutex.h" +#include "uresdata.h" +#include "uresimp.h" + +U_NAMESPACE_BEGIN + +namespace { + +constexpr char PSEUDO_ACCENTS_PREFIX = '\''; // -XA, -PSACCENT +constexpr char PSEUDO_BIDI_PREFIX = '+'; // -XB, -PSBIDI +constexpr char PSEUDO_CRACKED_PREFIX = ','; // -XC, -PSCRACK + +/** + * Stores NUL-terminated strings with duplicate elimination. + * Checks for unique UTF-16 string pointers and converts to invariant characters. + */ +class UniqueCharStrings { +public: + UniqueCharStrings(UErrorCode &errorCode) : strings(nullptr) { + uhash_init(&map, uhash_hashUChars, uhash_compareUChars, uhash_compareLong, &errorCode); + if (U_FAILURE(errorCode)) { return; } + strings = new CharString(); + if (strings == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + } + } + ~UniqueCharStrings() { + uhash_close(&map); + delete strings; + } + + /** Returns/orphans the CharString that contains all strings. */ + CharString *orphanCharStrings() { + CharString *result = strings; + strings = nullptr; + return result; + } + + /** Adds a string and returns a unique number for it. */ + int32_t add(const UnicodeString &s, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return 0; } + if (isFrozen) { + errorCode = U_NO_WRITE_PERMISSION; + return 0; + } + // The string points into the resource bundle. + const char16_t *p = s.getBuffer(); + int32_t oldIndex = uhash_geti(&map, p); + if (oldIndex != 0) { // found duplicate + return oldIndex; + } + // Explicit NUL terminator for the previous string. + // The strings object is also terminated with one implicit NUL. + strings->append(0, errorCode); + int32_t newIndex = strings->length(); + strings->appendInvariantChars(s, errorCode); + uhash_puti(&map, const_cast(p), newIndex, &errorCode); + return newIndex; + } + + void freeze() { isFrozen = true; } + + /** + * Returns a string pointer for its unique number, if this object is frozen. + * Otherwise nullptr. + */ + const char *get(int32_t i) const { + U_ASSERT(isFrozen); + return isFrozen && i > 0 ? strings->data() + i : nullptr; + } + +private: + UHashtable map; + CharString *strings; + bool isFrozen = false; +}; + +} // namespace + +LocaleDistanceData::LocaleDistanceData(LocaleDistanceData &&data) : + distanceTrieBytes(data.distanceTrieBytes), + regionToPartitions(data.regionToPartitions), + partitions(data.partitions), + paradigms(data.paradigms), paradigmsLength(data.paradigmsLength), + distances(data.distances) { + data.partitions = nullptr; + data.paradigms = nullptr; +} + +LocaleDistanceData::~LocaleDistanceData() { + uprv_free(partitions); + delete[] paradigms; +} + +// TODO(ICU-20777): Rename to just LikelySubtagsData. +struct XLikelySubtagsData { + UResourceBundle *langInfoBundle = nullptr; + UniqueCharStrings strings; + CharStringMap languageAliases; + CharStringMap regionAliases; + const uint8_t *trieBytes = nullptr; + LSR *lsrs = nullptr; + int32_t lsrsLength = 0; + + LocaleDistanceData distanceData; + + XLikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {} + + ~XLikelySubtagsData() { + ures_close(langInfoBundle); + delete[] lsrs; + } + + void load(UErrorCode &errorCode) { + langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode); + if (U_FAILURE(errorCode)) { return; } + StackUResourceBundle stackTempBundle; + ResourceDataValue value; + ures_getValueWithFallback(langInfoBundle, "likely", stackTempBundle.getAlias(), + value, errorCode); + ResourceTable likelyTable = value.getTable(errorCode); + if (U_FAILURE(errorCode)) { return; } + + // Read all strings in the resource bundle and convert them to invariant char *. + LocalMemory languageIndexes, regionIndexes, lsrSubtagIndexes; + int32_t languagesLength = 0, regionsLength = 0, lsrSubtagsLength = 0; + if (!readStrings(likelyTable, "languageAliases", value, + languageIndexes, languagesLength, errorCode) || + !readStrings(likelyTable, "regionAliases", value, + regionIndexes, regionsLength, errorCode) || + !readStrings(likelyTable, "lsrs", value, + lsrSubtagIndexes,lsrSubtagsLength, errorCode)) { + return; + } + if ((languagesLength & 1) != 0 || + (regionsLength & 1) != 0 || + (lsrSubtagsLength % 3) != 0) { + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + if (lsrSubtagsLength == 0) { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } + + if (!likelyTable.findValue("trie", value)) { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } + int32_t length; + trieBytes = value.getBinary(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + + // Also read distance/matcher data if available, + // to open & keep only one resource bundle pointer + // and to use one single UniqueCharStrings. + UErrorCode matchErrorCode = U_ZERO_ERROR; + ures_getValueWithFallback(langInfoBundle, "match", stackTempBundle.getAlias(), + value, matchErrorCode); + LocalMemory partitionIndexes, paradigmSubtagIndexes; + int32_t partitionsLength = 0, paradigmSubtagsLength = 0; + if (U_SUCCESS(matchErrorCode)) { + ResourceTable matchTable = value.getTable(errorCode); + if (U_FAILURE(errorCode)) { return; } + + if (matchTable.findValue("trie", value)) { + distanceData.distanceTrieBytes = value.getBinary(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + } + + if (matchTable.findValue("regionToPartitions", value)) { + distanceData.regionToPartitions = value.getBinary(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + if (length < LSR::REGION_INDEX_LIMIT) { + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + } + + if (!readStrings(matchTable, "partitions", value, + partitionIndexes, partitionsLength, errorCode) || + !readStrings(matchTable, "paradigms", value, + paradigmSubtagIndexes, paradigmSubtagsLength, errorCode)) { + return; + } + if ((paradigmSubtagsLength % 3) != 0) { + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + + if (matchTable.findValue("distances", value)) { + distanceData.distances = value.getIntVector(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + if (length < 4) { // LocaleDistance IX_LIMIT + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + } + } else if (matchErrorCode == U_MISSING_RESOURCE_ERROR) { + // ok for likely subtags + } else { // error other than missing resource + errorCode = matchErrorCode; + return; + } + + // Fetch & store invariant-character versions of strings + // only after we have collected and de-duplicated all of them. + strings.freeze(); + + languageAliases = CharStringMap(languagesLength / 2, errorCode); + for (int32_t i = 0; i < languagesLength; i += 2) { + languageAliases.put(strings.get(languageIndexes[i]), + strings.get(languageIndexes[i + 1]), errorCode); + } + + regionAliases = CharStringMap(regionsLength / 2, errorCode); + for (int32_t i = 0; i < regionsLength; i += 2) { + regionAliases.put(strings.get(regionIndexes[i]), + strings.get(regionIndexes[i + 1]), errorCode); + } + if (U_FAILURE(errorCode)) { return; } + + lsrsLength = lsrSubtagsLength / 3; + lsrs = new LSR[lsrsLength]; + if (lsrs == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t i = 0, j = 0; i < lsrSubtagsLength; i += 3, ++j) { + lsrs[j] = LSR(strings.get(lsrSubtagIndexes[i]), + strings.get(lsrSubtagIndexes[i + 1]), + strings.get(lsrSubtagIndexes[i + 2])); + } + + if (partitionsLength > 0) { + distanceData.partitions = static_cast( + uprv_malloc(partitionsLength * sizeof(const char *))); + if (distanceData.partitions == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t i = 0; i < partitionsLength; ++i) { + distanceData.partitions[i] = strings.get(partitionIndexes[i]); + } + } + + if (paradigmSubtagsLength > 0) { + distanceData.paradigmsLength = paradigmSubtagsLength / 3; + LSR *paradigms = new LSR[distanceData.paradigmsLength]; + if (paradigms == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t i = 0, j = 0; i < paradigmSubtagsLength; i += 3, ++j) { + paradigms[j] = LSR(strings.get(paradigmSubtagIndexes[i]), + strings.get(paradigmSubtagIndexes[i + 1]), + strings.get(paradigmSubtagIndexes[i + 2])); + } + distanceData.paradigms = paradigms; + } + } + +private: + bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value, + LocalMemory &indexes, int32_t &length, UErrorCode &errorCode) { + if (table.findValue(key, value)) { + ResourceArray stringArray = value.getArray(errorCode); + if (U_FAILURE(errorCode)) { return false; } + length = stringArray.getSize(); + if (length == 0) { return true; } + int32_t *rawIndexes = indexes.allocateInsteadAndCopy(length); + if (rawIndexes == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + for (int i = 0; i < length; ++i) { + stringArray.getValue(i, value); // returns TRUE because i < length + rawIndexes[i] = strings.add(value.getUnicodeString(errorCode), errorCode); + if (U_FAILURE(errorCode)) { return false; } + } + } + return true; + } +}; + +namespace { + +XLikelySubtags *gLikelySubtags = nullptr; +UInitOnce gInitOnce = U_INITONCE_INITIALIZER; + +UBool U_CALLCONV cleanup() { + delete gLikelySubtags; + gLikelySubtags = nullptr; + gInitOnce.reset(); + return TRUE; +} + +} // namespace + +void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { + // This function is invoked only via umtx_initOnce(). + U_ASSERT(gLikelySubtags == nullptr); + XLikelySubtagsData data(errorCode); + data.load(errorCode); + if (U_FAILURE(errorCode)) { return; } + gLikelySubtags = new XLikelySubtags(data); + if (gLikelySubtags == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup); +} + +const XLikelySubtags *XLikelySubtags::getSingleton(UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode); + return gLikelySubtags; +} + +XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) : + langInfoBundle(data.langInfoBundle), + strings(data.strings.orphanCharStrings()), + languageAliases(std::move(data.languageAliases)), + regionAliases(std::move(data.regionAliases)), + trie(data.trieBytes), + lsrs(data.lsrs), +#if U_DEBUG + lsrsLength(data.lsrsLength), +#endif + distanceData(std::move(data.distanceData)) { + data.langInfoBundle = nullptr; + data.lsrs = nullptr; + + // Cache the result of looking up language="und" encoded as "*", and "und-Zzzz" ("**"). + UStringTrieResult result = trie.next(u'*'); + U_ASSERT(USTRINGTRIE_HAS_NEXT(result)); + trieUndState = trie.getState64(); + result = trie.next(u'*'); + U_ASSERT(USTRINGTRIE_HAS_NEXT(result)); + trieUndZzzzState = trie.getState64(); + result = trie.next(u'*'); + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + defaultLsrIndex = trie.getValue(); + trie.reset(); + + for (char16_t c = u'a'; c <= u'z'; ++c) { + result = trie.next(c); + if (result == USTRINGTRIE_NO_VALUE) { + trieFirstLetterStates[c - u'a'] = trie.getState64(); + } + trie.reset(); + } +} + +XLikelySubtags::~XLikelySubtags() { + ures_close(langInfoBundle); + delete strings; + delete[] lsrs; +} + +LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const { + const char *name = locale.getName(); + if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=") + // Private use language tag x-subtag-subtag... + return LSR(name, "", ""); + } + return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), + locale.getVariant(), errorCode); +} + +namespace { + +const char *getCanonical(const CharStringMap &aliases, const char *alias) { + const char *canonical = aliases.get(alias); + return canonical == nullptr ? alias : canonical; +} + +} // namespace + +LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region, + const char *variant, UErrorCode &errorCode) const { + // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. + // They should match only themselves, + // not other locales with what looks like the same language and script subtags. + char c1; + if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { + switch (c1) { + case 'A': + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, errorCode); + case 'B': + return LSR(PSEUDO_BIDI_PREFIX, language, script, region, errorCode); + case 'C': + return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, errorCode); + default: // normal locale + break; + } + } + + if (variant[0] == 'P' && variant[1] == 'S') { + if (uprv_strcmp(variant, "PSACCENT") == 0) { + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, + *region == 0 ? "XA" : region, errorCode); + } else if (uprv_strcmp(variant, "PSBIDI") == 0) { + return LSR(PSEUDO_BIDI_PREFIX, language, script, + *region == 0 ? "XB" : region, errorCode); + } else if (uprv_strcmp(variant, "PSCRACK") == 0) { + return LSR(PSEUDO_CRACKED_PREFIX, language, script, + *region == 0 ? "XC" : region, errorCode); + } + // else normal locale + } + + language = getCanonical(languageAliases, language); + // (We have no script mappings.) + region = getCanonical(regionAliases, region); + return maximize(language, script, region); +} + +LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region) const { + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + if (uprv_strcmp(script, "Zzzz") == 0) { + script = ""; + } + if (uprv_strcmp(region, "ZZ") == 0) { + region = ""; + } + if (*script != 0 && *region != 0 && *language != 0) { + return LSR(language, script, region); // already maximized + } + + uint32_t retainOldMask = 0; + BytesTrie iter(trie); + uint64_t state; + int32_t value; + // Small optimization: Array lookup for first language letter. + int32_t c0; + if (0 <= (c0 = uprv_lowerOrdinal(language[0])) && c0 <= 25 && + language[1] != 0 && // language.length() >= 2 + (state = trieFirstLetterStates[c0]) != 0) { + value = trieNext(iter.resetToState64(state), language, 1); + } else { + value = trieNext(iter, language, 0); + } + if (value >= 0) { + if (*language != 0) { + retainOldMask |= 4; + } + state = iter.getState64(); + } else { + retainOldMask |= 4; + iter.resetToState64(trieUndState); // "und" ("*") + state = 0; + } + + if (value > 0) { + // Intermediate or final value from just language. + if (value == SKIP_SCRIPT) { + value = 0; + } + if (*script != 0) { + retainOldMask |= 2; + } + } else { + value = trieNext(iter, script, 0); + if (value >= 0) { + if (*script != 0) { + retainOldMask |= 2; + } + state = iter.getState64(); + } else { + retainOldMask |= 2; + if (state == 0) { + iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**") + } else { + iter.resetToState64(state); + value = trieNext(iter, "", 0); + U_ASSERT(value >= 0); + state = iter.getState64(); + } + } + } + + if (value > 0) { + // Final value from just language or language+script. + if (*region != 0) { + retainOldMask |= 1; + } + } else { + value = trieNext(iter, region, 0); + if (value >= 0) { + if (*region != 0) { + retainOldMask |= 1; + } + } else { + retainOldMask |= 1; + if (state == 0) { + value = defaultLsrIndex; + } else { + iter.resetToState64(state); + value = trieNext(iter, "", 0); + U_ASSERT(value > 0); + } + } + } + U_ASSERT(value < lsrsLength); + const LSR &result = lsrs[value]; + + if (*language == 0) { + language = "und"; + } + + if (retainOldMask == 0) { + // Quickly return a copy of the lookup-result LSR + // without new allocation of the subtags. + return LSR(result.language, result.script, result.region); + } + if ((retainOldMask & 4) == 0) { + language = result.language; + } + if ((retainOldMask & 2) == 0) { + script = result.script; + } + if ((retainOldMask & 1) == 0) { + region = result.region; + } + return LSR(language, script, region); +} + +int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { + UStringTrieResult result; + uint8_t c; + if ((c = s[i]) == 0) { + result = iter.next(u'*'); + } else { + for (;;) { + c = uprv_invCharToAscii(c); + // EBCDIC: If s[i] is not an invariant character, + // then c is now 0 and will simply not match anything, which is harmless. + uint8_t next = s[++i]; + if (next != 0) { + if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) { + return -1; + } + } else { + // last character of this subtag + result = iter.next(c | 0x80); + break; + } + c = next; + } + } + switch (result) { + case USTRINGTRIE_NO_MATCH: return -1; + case USTRINGTRIE_NO_VALUE: return 0; + case USTRINGTRIE_INTERMEDIATE_VALUE: + U_ASSERT(iter.getValue() == SKIP_SCRIPT); + return SKIP_SCRIPT; + case USTRINGTRIE_FINAL_VALUE: return iter.getValue(); + default: return -1; + } +} + +// TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code +// in loclikely.cpp to this new code, including activating this +// minimizeSubtags() function. The LocaleMatcher does not minimize. +#if 0 +LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn, + const char *regionIn, ULocale.Minimize fieldToFavor, + UErrorCode &errorCode) const { + LSR result = maximize(languageIn, scriptIn, regionIn); + + // We could try just a series of checks, like: + // LSR result2 = addLikelySubtags(languageIn, "", ""); + // if result.equals(result2) return result2; + // However, we can optimize 2 of the cases: + // (languageIn, "", "") + // (languageIn, "", regionIn) + + // value00 = lookup(result.language, "", "") + BytesTrie iter = new BytesTrie(trie); + int value = trieNext(iter, result.language, 0); + U_ASSERT(value >= 0); + if (value == 0) { + value = trieNext(iter, "", 0); + U_ASSERT(value >= 0); + if (value == 0) { + value = trieNext(iter, "", 0); + } + } + U_ASSERT(value > 0); + LSR value00 = lsrs[value]; + boolean favorRegionOk = false; + if (result.script.equals(value00.script)) { //script is default + if (result.region.equals(value00.region)) { + return new LSR(result.language, "", ""); + } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { + return new LSR(result.language, "", result.region); + } else { + favorRegionOk = true; + } + } + + // The last case is not as easy to optimize. + // Maybe do later, but for now use the straightforward code. + LSR result2 = maximize(languageIn, scriptIn, ""); + if (result2.equals(result)) { + return new LSR(result.language, result.script, ""); + } else if (favorRegionOk) { + return new LSR(result.language, "", result.region); + } + return result; +} +#endif + +U_NAMESPACE_END diff -Nru icu-64.2/source/common/loclikelysubtags.h icu-65.1/source/common/loclikelysubtags.h --- icu-64.2/source/common/loclikelysubtags.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/loclikelysubtags.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,143 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// loclikelysubtags.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCLIKELYSUBTAGS_H__ +#define __LOCLIKELYSUBTAGS_H__ + +#include +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "unicode/ures.h" +#include "lsr.h" +#include "uhash.h" + +U_NAMESPACE_BEGIN + +struct XLikelySubtagsData; + +/** + * Map of const char * keys & values. + * Stores pointers as is: Does not own/copy/adopt/release strings. + */ +class CharStringMap final : public UMemory { +public: + /** Constructs an unusable non-map. */ + CharStringMap() : map(nullptr) {} + CharStringMap(int32_t size, UErrorCode &errorCode) { + map = uhash_openSize(uhash_hashChars, uhash_compareChars, uhash_compareChars, + size, &errorCode); + } + CharStringMap(CharStringMap &&other) U_NOEXCEPT : map(other.map) { + other.map = nullptr; + } + CharStringMap(const CharStringMap &other) = delete; + ~CharStringMap() { + uhash_close(map); + } + + CharStringMap &operator=(CharStringMap &&other) U_NOEXCEPT { + map = other.map; + other.map = nullptr; + return *this; + } + CharStringMap &operator=(const CharStringMap &other) = delete; + + const char *get(const char *key) const { return static_cast(uhash_get(map, key)); } + void put(const char *key, const char *value, UErrorCode &errorCode) { + uhash_put(map, const_cast(key), const_cast(value), &errorCode); + } + +private: + UHashtable *map; +}; + +struct LocaleDistanceData { + LocaleDistanceData() = default; + LocaleDistanceData(LocaleDistanceData &&data); + ~LocaleDistanceData(); + + const uint8_t *distanceTrieBytes = nullptr; + const uint8_t *regionToPartitions = nullptr; + const char **partitions = nullptr; + const LSR *paradigms = nullptr; + int32_t paradigmsLength = 0; + const int32_t *distances = nullptr; + +private: + LocaleDistanceData &operator=(const LocaleDistanceData &) = delete; +}; + +// TODO(ICU-20777): Rename to just LikelySubtags. +class XLikelySubtags final : public UMemory { +public: + ~XLikelySubtags(); + + static constexpr int32_t SKIP_SCRIPT = 1; + + // VisibleForTesting + static const XLikelySubtags *getSingleton(UErrorCode &errorCode); + + // VisibleForTesting + LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const; + + // TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code + // in loclikely.cpp to this new code, including activating this + // minimizeSubtags() function. The LocaleMatcher does not minimize. +#if 0 + LSR minimizeSubtags(const char *languageIn, const char *scriptIn, const char *regionIn, + ULocale.Minimize fieldToFavor, UErrorCode &errorCode) const; +#endif + + // visible for LocaleDistance + const LocaleDistanceData &getDistanceData() const { return distanceData; } + +private: + XLikelySubtags(XLikelySubtagsData &data); + XLikelySubtags(const XLikelySubtags &other) = delete; + XLikelySubtags &operator=(const XLikelySubtags &other) = delete; + + static void initLikelySubtags(UErrorCode &errorCode); + + LSR makeMaximizedLsr(const char *language, const char *script, const char *region, + const char *variant, UErrorCode &errorCode) const; + + /** + * Raw access to addLikelySubtags. Input must be in canonical format, eg "en", not "eng" or "EN". + */ + LSR maximize(const char *language, const char *script, const char *region) const; + + static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i); + + UResourceBundle *langInfoBundle; + // We could store the strings by value, except that if there were few enough strings, + // moving the contents could copy it to a different array, + // invalidating the pointers stored in the maps. + CharString *strings; + CharStringMap languageAliases; + CharStringMap regionAliases; + + // The trie maps each lang+script+region (encoded in ASCII) to an index into lsrs. + // There is also a trie value for each intermediate lang and lang+script. + // '*' is used instead of "und", "Zzzz"/"" and "ZZ"/"". + BytesTrie trie; + uint64_t trieUndState; + uint64_t trieUndZzzzState; + int32_t defaultLsrIndex; + uint64_t trieFirstLetterStates[26]; + const LSR *lsrs; +#if U_DEBUG + int32_t lsrsLength; +#endif + + // distance/matcher data: see comment in XLikelySubtagsData::load() + LocaleDistanceData distanceData; +}; + +U_NAMESPACE_END + +#endif // __LOCLIKELYSUBTAGS_H__ diff -Nru icu-64.2/source/common/lsr.cpp icu-65.1/source/common/lsr.cpp --- icu-64.2/source/common/lsr.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/lsr.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,101 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// lsr.cpp +// created: 2019may08 Markus W. Scherer + +#include "unicode/utypes.h" +#include "charstr.h" +#include "cmemory.h" +#include "cstring.h" +#include "lsr.h" +#include "uinvchar.h" +#include "ustr_imp.h" + +U_NAMESPACE_BEGIN + +LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode) : + language(nullptr), script(nullptr), region(r), + regionIndex(indexForRegion(region)) { + if (U_SUCCESS(errorCode)) { + CharString langScript; + langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode); + int32_t scriptOffset = langScript.length(); + langScript.append(prefix, errorCode).append(scr, errorCode); + owned = langScript.cloneData(errorCode); + if (U_SUCCESS(errorCode)) { + language = owned; + script = owned + scriptOffset; + } + } +} + +LSR::LSR(LSR &&other) U_NOEXCEPT : + language(other.language), script(other.script), region(other.region), owned(other.owned), + regionIndex(other.regionIndex), hashCode(other.hashCode) { + if (owned != nullptr) { + other.language = other.script = ""; + other.owned = nullptr; + other.hashCode = 0; + } +} + +void LSR::deleteOwned() { + uprv_free(owned); +} + +LSR &LSR::operator=(LSR &&other) U_NOEXCEPT { + this->~LSR(); + language = other.language; + script = other.script; + region = other.region; + regionIndex = other.regionIndex; + owned = other.owned; + hashCode = other.hashCode; + if (owned != nullptr) { + other.language = other.script = ""; + other.owned = nullptr; + other.hashCode = 0; + } + return *this; +} + +UBool LSR::operator==(const LSR &other) const { + return + uprv_strcmp(language, other.language) == 0 && + uprv_strcmp(script, other.script) == 0 && + regionIndex == other.regionIndex && + // Compare regions if both are ill-formed (and their indexes are 0). + (regionIndex > 0 || uprv_strcmp(region, other.region) == 0); +} + +int32_t LSR::indexForRegion(const char *region) { + int32_t c = region[0]; + int32_t a = c - '0'; + if (0 <= a && a <= 9) { // digits: "419" + int32_t b = region[1] - '0'; + if (b < 0 || 9 < b) { return 0; } + c = region[2] - '0'; + if (c < 0 || 9 < c || region[3] != 0) { return 0; } + return (10 * a + b) * 10 + c + 1; + } else { // letters: "DE" + a = uprv_upperOrdinal(c); + if (a < 0 || 25 < a) { return 0; } + int32_t b = uprv_upperOrdinal(region[1]); + if (b < 0 || 25 < b || region[2] != 0) { return 0; } + return 26 * a + b + 1001; + } + return 0; +} + +LSR &LSR::setHashCode() { + if (hashCode == 0) { + hashCode = + (ustr_hashCharsN(language, static_cast(uprv_strlen(language))) * 37 + + ustr_hashCharsN(script, static_cast(uprv_strlen(script)))) * 37 + + regionIndex; + } + return *this; +} + +U_NAMESPACE_END diff -Nru icu-64.2/source/common/lsr.h icu-65.1/source/common/lsr.h --- icu-64.2/source/common/lsr.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/lsr.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,72 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// lsr.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LSR_H__ +#define __LSR_H__ + +#include "unicode/utypes.h" +#include "unicode/uobject.h" +#include "cstring.h" + +U_NAMESPACE_BEGIN + +struct LSR final : public UMemory { + static constexpr int32_t REGION_INDEX_LIMIT = 1001 + 26 * 26; + + const char *language; + const char *script; + const char *region; + char *owned = nullptr; + /** Index for region, 0 if ill-formed. @see indexForRegion */ + int32_t regionIndex = 0; + /** Only set for LSRs that will be used in a hash table. */ + int32_t hashCode = 0; + + LSR() : language("und"), script(""), region("") {} + + /** Constructor which aliases all subtag pointers. */ + LSR(const char *lang, const char *scr, const char *r) : + language(lang), script(scr), region(r), + regionIndex(indexForRegion(region)) {} + /** + * Constructor which prepends the prefix to the language and script, + * copies those into owned memory, and aliases the region. + */ + LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode); + LSR(LSR &&other) U_NOEXCEPT; + LSR(const LSR &other) = delete; + inline ~LSR() { + // Pure inline code for almost all instances. + if (owned != nullptr) { + deleteOwned(); + } + } + + LSR &operator=(LSR &&other) U_NOEXCEPT; + LSR &operator=(const LSR &other) = delete; + + /** + * Returns a positive index (>0) for a well-formed region code. + * Do not rely on a particular region->index mapping; it may change. + * Returns 0 for ill-formed strings. + */ + static int32_t indexForRegion(const char *region); + + UBool operator==(const LSR &other) const; + + inline UBool operator!=(const LSR &other) const { + return !operator==(other); + } + + LSR &setHashCode(); + +private: + void deleteOwned(); +}; + +U_NAMESPACE_END + +#endif // __LSR_H__ diff -Nru icu-64.2/source/common/Makefile.in icu-65.1/source/common/Makefile.in --- icu-64.2/source/common/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -88,8 +88,9 @@ ucnv_ext.o ucnvmbcs.o ucnv2022.o ucnvhz.o ucnv_lmb.o ucnvisci.o ucnvdisp.o ucnv_set.o ucnv_ct.o \ resource.o uresbund.o ures_cnv.o uresdata.o resbund.o resbund_cnv.o \ ucurr.o \ -localebuilder.o \ +localebuilder.o localeprioritylist.o \ messagepattern.o ucat.o locmap.o uloc.o locid.o locutil.o locavailable.o locdispnames.o locdspnm.o loclikely.o locresdata.o \ +lsr.o loclikelysubtags.o locdistance.o localematcher.o \ bytestream.o stringpiece.o bytesinkutil.o \ stringtriebuilder.o bytestriebuilder.o \ bytestrie.o bytestrieiterator.o \ @@ -115,7 +116,8 @@ sharedobject.o simpleformatter.o unifiedcache.o uloc_keytype.o \ ubiditransform.o \ pluralmap.o \ -static_unicode_sets.o +static_unicode_sets.o \ +restrace.o ## Header files to install HEADERS = $(srcdir)/unicode/*.h diff -Nru icu-64.2/source/common/mutex.h icu-65.1/source/common/mutex.h --- icu-64.2/source/common/mutex.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/mutex.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,50 +28,48 @@ U_NAMESPACE_BEGIN -//---------------------------------------------------------------------------- -// Code within that accesses shared static or global data should -// should instantiate a Mutex object while doing so. You should make your own -// private mutex where possible. - -// For example: -// -// UMutex myMutex = U_MUTEX_INITIALIZER; -// -// void Function(int arg1, int arg2) -// { -// static Object* foo; // Shared read-write object -// Mutex mutex(&myMutex); // or no args for the global lock -// foo->Method(); -// // When 'mutex' goes out of scope and gets destroyed here, the lock is released -// } -// -// Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function -// returning a Mutex. This is a common mistake which silently slips through the -// compiler!! -// +/** + * Mutex is a helper class for convenient locking and unlocking of a UMutex. + * + * Creating a local scope Mutex will lock a UMutex, holding the lock until the Mutex + * goes out of scope. + * + * If no UMutex is specified, the ICU global mutex is implied. + * + * For example: + * + * static UMutex myMutex; + * + * void Function(int arg1, int arg2) + * { + * static Object* foo; // Shared read-write object + * Mutex mutex(&myMutex); // or no args for the global lock + * foo->Method(); + * // When 'mutex' goes out of scope and gets destroyed here, the lock is released + * } + * + * Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function + * returning a Mutex. This is a common mistake which silently slips through the + * compiler!! + */ class U_COMMON_API Mutex : public UMemory { public: - inline Mutex(UMutex *mutex = NULL); - inline ~Mutex(); + Mutex(UMutex *mutex = nullptr) : fMutex(mutex) { + umtx_lock(fMutex); + } + ~Mutex() { + umtx_unlock(fMutex); + } + + Mutex(const Mutex &other) = delete; // forbid assigning of this class + Mutex &operator=(const Mutex &other) = delete; // forbid copying of this class + void *operator new(size_t s) = delete; // forbid heap allocation. Locals only. private: - UMutex *fMutex; - - Mutex(const Mutex &other); // forbid copying of this class - Mutex &operator=(const Mutex &other); // forbid copying of this class + UMutex *fMutex; }; -inline Mutex::Mutex(UMutex *mutex) - : fMutex(mutex) -{ - umtx_lock(fMutex); -} - -inline Mutex::~Mutex() -{ - umtx_unlock(fMutex); -} U_NAMESPACE_END diff -Nru icu-64.2/source/common/normalizer2impl.h icu-65.1/source/common/normalizer2impl.h --- icu-64.2/source/common/normalizer2impl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/normalizer2impl.h 2019-10-03 11:16:41.000000000 +0000 @@ -245,9 +245,7 @@ */ class U_COMMON_API Normalizer2Impl : public UObject { public: - Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { - fCanonIterDataInitOnce.reset(); - } + Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { } virtual ~Normalizer2Impl(); void init(const int32_t *inIndexes, const UCPTrie *inTrie, @@ -723,7 +721,7 @@ const uint16_t *extraData; // mappings and/or compositions for yesYes, yesNo & noNo characters const uint8_t *smallFCD; // [0x100] one bit per 32 BMP code points, set if any FCD!=0 - UInitOnce fCanonIterDataInitOnce; + UInitOnce fCanonIterDataInitOnce = U_INITONCE_INITIALIZER; CanonIterData *fCanonIterData; }; diff -Nru icu-64.2/source/common/putil.cpp icu-65.1/source/common/putil.cpp --- icu-64.2/source/common/putil.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/putil.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -249,7 +249,7 @@ } static UDate getUTCtime_fake() { - static UMutex fakeClockMutex = U_MUTEX_INTIALIZER; + static UMutex fakeClockMutex; umtx_lock(&fakeClockMutex); if(!fakeClock_set) { UDate real = getUTCtime_real(); @@ -1315,11 +1315,10 @@ # endif #endif -#if U_PLATFORM_HAS_WINUWP_API != 0 +#if defined(ICU_DATA_DIR_WINDOWS) // Helper function to get the ICU Data Directory under the Windows directory location. static BOOL U_CALLCONV getIcuDataDirectoryUnderWindowsDirectory(char* directoryBuffer, UINT bufferLength) { -#if defined(ICU_DATA_DIR_WINDOWS) wchar_t windowsPath[MAX_PATH]; char windowsPathUtf8[MAX_PATH]; @@ -1346,7 +1345,6 @@ } } } -#endif return FALSE; } @@ -1380,9 +1378,9 @@ */ # if !defined(ICU_NO_USER_DATA_OVERRIDE) && !UCONFIG_NO_FILE_IO /* First try to get the environment variable */ -# if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP does not support getenv +# if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP does not support getenv path=getenv("ICU_DATA"); -# endif +# endif # endif /* ICU_DATA_DIR may be set as a compile option. @@ -1411,7 +1409,7 @@ } #endif -#if U_PLATFORM_HAS_WINUWP_API != 0 && defined(ICU_DATA_DIR_WINDOWS) +#if defined(ICU_DATA_DIR_WINDOWS) char datadir_path_buffer[MAX_PATH]; if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { path = datadir_path_buffer; @@ -1461,12 +1459,17 @@ const char *dir = ""; -#if U_PLATFORM_HAS_WINUWP_API != 0 - // The UWP version does not support the environment variable setting, but can possibly pick them up from the Windows directory. +#if U_PLATFORM_HAS_WINUWP_API == 1 +// The UWP version does not support the environment variable setting. + +# if defined(ICU_DATA_DIR_WINDOWS) + // When using the Windows system data, we can possibly pick up time zone data from the Windows directory. char datadir_path_buffer[MAX_PATH]; if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { dir = datadir_path_buffer; } +# endif + #else dir = getenv("ICU_TIMEZONE_FILES_DIR"); #endif // U_PLATFORM_HAS_WINUWP_API @@ -1560,6 +1563,10 @@ { /* Nothing worked. Give it a nice POSIX default value. */ posixID = "en_US_POSIX"; + // Note: this test will not catch 'C.UTF-8', + // that will be handled in uprv_getDefaultLocaleID(). + // Leave this mapping here for the uprv_getPOSIXIDForDefaultCodepage() + // caller which expects to see "en_US_POSIX" in many branches. } return posixID; } @@ -1631,8 +1638,8 @@ } // Copy the ID into owned memory. - // Over-allocate in case we replace "@" with "__". - char *correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID) + 1 + 1)); + // Over-allocate in case we replace "C" with "en_US_POSIX" (+10), + null termination + char *correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID) + 10 + 1)); if (correctedPOSIXLocale == nullptr) { return nullptr; } @@ -1641,11 +1648,18 @@ char *limit; if ((limit = uprv_strchr(correctedPOSIXLocale, '.')) != nullptr) { *limit = 0; - if ((limit = uprv_strchr(correctedPOSIXLocale, '@')) != nullptr) { - *limit = 0; - } + } + if ((limit = uprv_strchr(correctedPOSIXLocale, '@')) != nullptr) { + *limit = 0; } + if ((uprv_strcmp("C", correctedPOSIXLocale) == 0) // no @ variant + || (uprv_strcmp("POSIX", correctedPOSIXLocale) == 0)) { + // Raw input was C.* or POSIX.*, Give it a nice POSIX default value. + // (The "C"/"POSIX" case is handled in uprv_getPOSIXIDForCategory()) + uprv_strcpy(correctedPOSIXLocale, "en_US_POSIX"); + } + /* Note that we scan the *uncorrected* ID. */ const char *p; if ((p = uprv_strrchr(posixID, '@')) != nullptr) { @@ -1668,7 +1682,7 @@ if ((q = uprv_strchr(p, '.')) != nullptr) { /* How big will the resulting string be? */ int32_t len = (int32_t)(uprv_strlen(correctedPOSIXLocale) + (q-p)); - uprv_strncat(correctedPOSIXLocale, p, q-p); + uprv_strncat(correctedPOSIXLocale, p, q-p); // do not include charset correctedPOSIXLocale[len] = 0; } else { @@ -2053,7 +2067,7 @@ static char codepage[64]; DWORD codepageNumber = 0; -#if U_PLATFORM_HAS_WINUWP_API > 0 +#if U_PLATFORM_HAS_WINUWP_API == 1 // UWP doesn't have a direct API to get the default ACP as Microsoft would rather // have folks use Unicode than a "system" code page, however this is the same // codepage as the system default locale codepage. (FWIW, the system locale is diff -Nru icu-64.2/source/common/putilimp.h icu-65.1/source/common/putilimp.h --- icu-64.2/source/common/putilimp.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/putilimp.h 2019-10-03 11:16:41.000000000 +0000 @@ -179,76 +179,6 @@ /** @} */ /*===========================================================================*/ -/** @{ GCC built in functions for atomic memory operations */ -/*===========================================================================*/ - -/** - * \def U_HAVE_GCC_ATOMICS - * @internal - */ -#ifdef U_HAVE_GCC_ATOMICS - /* Use the predefined value. */ -#elif U_PLATFORM == U_PF_MINGW - #define U_HAVE_GCC_ATOMICS 0 -#elif U_GCC_MAJOR_MINOR >= 404 || defined(__clang__) - /* TODO: Intel icc and IBM xlc on AIX also support gcc atomics. (Intel originated them.) - * Add them for these compilers. - * Note: Clang sets __GNUC__ defines for version 4.2, so misses the 4.4 test here. - */ -# define U_HAVE_GCC_ATOMICS 1 -#else -# define U_HAVE_GCC_ATOMICS 0 -#endif - -/** @} */ - -/** - * \def U_HAVE_STD_ATOMICS - * Defines whether to use the C++11 std::atomic functions. - * If false, ICU will fall back to compiler or platform specific alternatives. - * Note: support for these fall back options for atomics will be removed in a future version - * of ICU, and the use of C++ 11 atomics will be required. - * @internal - */ -#ifdef U_HAVE_STD_ATOMICS - /* Use the predefined value. */ -#else -# define U_HAVE_STD_ATOMICS 1 -#endif - -/** - * \def U_HAVE_CLANG_ATOMICS - * Defines whether Clang c11 style built-in atomics are available. - * These are used in preference to gcc atomics when both are available. - */ -#ifdef U_HAVE_CLANG_ATOMICS - /* Use the predefined value. */ -#elif __has_builtin(__c11_atomic_load) && \ - __has_builtin(__c11_atomic_store) && \ - __has_builtin(__c11_atomic_fetch_add) && \ - __has_builtin(__c11_atomic_fetch_sub) -# define U_HAVE_CLANG_ATOMICS 1 -#else -# define U_HAVE_CLANG_ATOMICS 0 -#endif - - -/** - * \def U_HAVE_STD_MUTEX - * Defines whether to use the C++11 std::mutex functions. - * If false, ICU will fall back to compiler or platform specific alternatives. - * std::mutex is preferred, and used by default unless this setting is overridden. - * Note: support for other options for mutexes will be removed in a future version - * of ICU, and the use of std::mutex will be required. - * @internal - */ -#ifdef U_HAVE_STD_MUTEX - /* Use the predefined value. */ -#else -# define U_HAVE_STD_MUTEX 1 -#endif - -/*===========================================================================*/ /** @{ Programs used by ICU code */ /*===========================================================================*/ diff -Nru icu-64.2/source/common/rbbi_cache.cpp icu-65.1/source/common/rbbi_cache.cpp --- icu-64.2/source/common/rbbi_cache.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/rbbi_cache.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -519,7 +519,7 @@ // The initial handleNext() only advanced by a single code point. Go again. position = fBI->handleNext(); // Safe rules identify safe pairs. } - }; + } positionStatusIdx = fBI->fRuleStatusIndex; } } while (position >= fromPosition); diff -Nru icu-64.2/source/common/rbbi.cpp icu-65.1/source/common/rbbi.cpp --- icu-64.2/source/common/rbbi.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/rbbi.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -323,8 +323,8 @@ // Virtual function: does the right thing with subclasses. // //----------------------------------------------------------------------------- -BreakIterator* -RuleBasedBreakIterator::clone(void) const { +RuleBasedBreakIterator* +RuleBasedBreakIterator::clone() const { return new RuleBasedBreakIterator(*this); } @@ -352,7 +352,7 @@ // or have a different iteration position. // Note that fText's position is always the same as the break iterator's position. return FALSE; - }; + } if (!(fPosition == that2.fPosition && fRuleStatusIndex == that2.fRuleStatusIndex && @@ -1079,10 +1079,8 @@ } -BreakIterator * RuleBasedBreakIterator::createBufferClone(void * /*stackBuffer*/, - int32_t &bufferSize, - UErrorCode &status) -{ +RuleBasedBreakIterator *RuleBasedBreakIterator::createBufferClone( + void * /*stackBuffer*/, int32_t &bufferSize, UErrorCode &status) { if (U_FAILURE(status)){ return NULL; } diff -Nru icu-64.2/source/common/resbund.cpp icu-65.1/source/common/resbund.cpp --- icu-64.2/source/common/resbund.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/resbund.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -51,6 +51,7 @@ #include "unicode/utypes.h" #include "unicode/resbund.h" +#include "cmemory.h" #include "mutex.h" #include "uassert.h" #include "umutex.h" @@ -377,7 +378,7 @@ } const Locale &ResourceBundle::getLocale(void) const { - static UMutex gLocaleLock = U_MUTEX_INITIALIZER; + static UMutex gLocaleLock; Mutex lock(&gLocaleLock); if (fLocale != NULL) { return *fLocale; diff -Nru icu-64.2/source/common/resource.h icu-65.1/source/common/resource.h --- icu-64.2/source/common/resource.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/resource.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,7 @@ #include "unicode/utypes.h" #include "unicode/unistr.h" #include "unicode/ures.h" +#include "restrace.h" struct ResourceData; @@ -47,8 +48,10 @@ ResourceArray() : items16(NULL), items32(NULL), length(0) {} /** Only for implementation use. @internal */ - ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len) : - items16(i16), items32(i32), length(len) {} + ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len, + const ResourceTracer& traceInfo) : + items16(i16), items32(i32), length(len), + fTraceInfo(traceInfo) {} /** * @return The number of items in the array resource. @@ -68,6 +71,7 @@ const uint16_t *items16; const uint32_t *items32; int32_t length; + ResourceTracer fTraceInfo; }; /** @@ -80,27 +84,37 @@ /** Only for implementation use. @internal */ ResourceTable(const uint16_t *k16, const int32_t *k32, - const uint16_t *i16, const uint32_t *i32, int32_t len) : - keys16(k16), keys32(k32), items16(i16), items32(i32), length(len) {} + const uint16_t *i16, const uint32_t *i32, int32_t len, + const ResourceTracer& traceInfo) : + keys16(k16), keys32(k32), items16(i16), items32(i32), length(len), + fTraceInfo(traceInfo) {} /** * @return The number of items in the array resource. */ int32_t getSize() const { return length; } /** - * @param i Array item index. + * @param i Table item index. * @param key Output-only, receives the key of the i'th item. * @param value Output-only, receives the value of the i'th item. * @return TRUE if i is non-negative and less than getSize(). */ UBool getKeyAndValue(int32_t i, const char *&key, ResourceValue &value) const; + /** + * @param key Key string to find in the table. + * @param value Output-only, receives the value of the item with that key. + * @return TRUE if the table contains the key. + */ + UBool findValue(const char *key, ResourceValue &value) const; + private: const uint16_t *keys16; const int32_t *keys32; const uint16_t *items16; const uint32_t *items32; int32_t length; + ResourceTracer fTraceInfo; }; /** diff -Nru icu-64.2/source/common/restrace.cpp icu-65.1/source/common/restrace.cpp --- icu-64.2/source/common/restrace.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/restrace.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,130 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if U_ENABLE_TRACING + +#include "restrace.h" +#include "charstr.h" +#include "cstring.h" +#include "utracimp.h" +#include "uresimp.h" +#include "uassert.h" +#include "util.h" + +U_NAMESPACE_BEGIN + +ResourceTracer::~ResourceTracer() = default; + +void ResourceTracer::trace(const char* resType) const { + U_ASSERT(fResB || fParent); + UTRACE_ENTRY(UTRACE_UDATA_RESOURCE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + getFilePath(filePath, status); + + CharString resPath; + getResPath(resPath, status); + + // The longest type ("intvector") is 9 chars + const char kSpaces[] = " "; + CharString format; + format.append(kSpaces, sizeof(kSpaces) - 1 - uprv_strlen(resType), status); + format.append("(%s) %s @ %s", status); + + UTRACE_DATA3(UTRACE_VERBOSE, + format.data(), + resType, + filePath.data(), + resPath.data()); + UTRACE_EXIT_STATUS(status); +} + +void ResourceTracer::traceOpen() const { + U_ASSERT(fResB); + UTRACE_ENTRY(UTRACE_UDATA_BUNDLE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + UTRACE_DATA1(UTRACE_VERBOSE, "%s", getFilePath(filePath, status).data()); + UTRACE_EXIT_STATUS(status); +} + +CharString& ResourceTracer::getFilePath(CharString& output, UErrorCode& status) const { + if (fResB) { + output.append(fResB->fData->fPath, status); + output.append('/', status); + output.append(fResB->fData->fName, status); + output.append(".res", status); + } else { + fParent->getFilePath(output, status); + } + return output; +} + +CharString& ResourceTracer::getResPath(CharString& output, UErrorCode& status) const { + if (fResB) { + output.append('/', status); + output.append(fResB->fResPath, status); + // removing the trailing / + U_ASSERT(output[output.length()-1] == '/'); + output.truncate(output.length()-1); + } else { + fParent->getResPath(output, status); + } + if (fKey) { + output.append('/', status); + output.append(fKey, status); + } + if (fIndex != -1) { + output.append('[', status); + UnicodeString indexString; + ICU_Utility::appendNumber(indexString, fIndex); + output.appendInvariantChars(indexString, status); + output.append(']', status); + } + return output; +} + +void FileTracer::traceOpen(const char* path, const char* type, const char* name) { + if (uprv_strcmp(type, "res") == 0) { + traceOpenResFile(path, name); + } else { + traceOpenDataFile(path, type, name); + } +} + +void FileTracer::traceOpenDataFile(const char* path, const char* type, const char* name) { + UTRACE_ENTRY(UTRACE_UDATA_DATA_FILE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + filePath.append(path, status); + filePath.append('/', status); + filePath.append(name, status); + filePath.append('.', status); + filePath.append(type, status); + + UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data()); + UTRACE_EXIT_STATUS(status); +} + +void FileTracer::traceOpenResFile(const char* path, const char* name) { + UTRACE_ENTRY(UTRACE_UDATA_RES_FILE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + filePath.append(path, status); + filePath.append('/', status); + filePath.append(name, status); + filePath.append(".res", status); + + UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data()); + UTRACE_EXIT_STATUS(status); +} + +U_NAMESPACE_END + +#endif // U_ENABLE_TRACING diff -Nru icu-64.2/source/common/restrace.h icu-65.1/source/common/restrace.h --- icu-64.2/source/common/restrace.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/restrace.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,147 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef __RESTRACE_H__ +#define __RESTRACE_H__ + +#include "unicode/utypes.h" + +#if U_ENABLE_TRACING + +struct UResourceBundle; + +U_NAMESPACE_BEGIN + +class CharString; + +/** + * Instances of this class store information used to trace reads from resource + * bundles when ICU is built with --enable-tracing. + * + * All arguments of type const UResourceBundle*, const char*, and + * const ResourceTracer& are stored as pointers. The caller must retain + * ownership for the lifetime of this ResourceTracer. + * + * Exported as U_COMMON_API for Windows because it is a value field + * in other exported types. + */ +class U_COMMON_API ResourceTracer { +public: + ResourceTracer() : + fResB(nullptr), + fParent(nullptr), + fKey(nullptr), + fIndex(-1) {} + + ResourceTracer(const UResourceBundle* resB) : + fResB(resB), + fParent(nullptr), + fKey(nullptr), + fIndex(-1) {} + + ResourceTracer(const UResourceBundle* resB, const char* key) : + fResB(resB), + fParent(nullptr), + fKey(key), + fIndex(-1) {} + + ResourceTracer(const UResourceBundle* resB, int32_t index) : + fResB(resB), + fParent(nullptr), + fKey(nullptr), + fIndex(index) {} + + ResourceTracer(const ResourceTracer& parent, const char* key) : + fResB(nullptr), + fParent(&parent), + fKey(key), + fIndex(-1) {} + + ResourceTracer(const ResourceTracer& parent, int32_t index) : + fResB(nullptr), + fParent(&parent), + fKey(nullptr), + fIndex(index) {} + + ~ResourceTracer(); + + void trace(const char* type) const; + void traceOpen() const; + + /** + * Calls trace() if the resB or parent provided to the constructor was + * non-null; otherwise, does nothing. + */ + void maybeTrace(const char* type) const { + if (fResB || fParent) { + trace(type); + } + } + +private: + const UResourceBundle* fResB; + const ResourceTracer* fParent; + const char* fKey; + int32_t fIndex; + + CharString& getFilePath(CharString& output, UErrorCode& status) const; + + CharString& getResPath(CharString& output, UErrorCode& status) const; +}; + +/** + * This class provides methods to trace data file reads when ICU is built + * with --enable-tracing. + */ +class FileTracer { +public: + static void traceOpen(const char* path, const char* type, const char* name); + +private: + static void traceOpenDataFile(const char* path, const char* type, const char* name); + static void traceOpenResFile(const char* path, const char* name); +}; + +U_NAMESPACE_END + +#else // U_ENABLE_TRACING + +U_NAMESPACE_BEGIN + +/** + * Default trivial implementation when --enable-tracing is not used. + */ +class U_COMMON_API ResourceTracer { +public: + ResourceTracer() {} + + ResourceTracer(const void*) {} + + ResourceTracer(const void*, const char*) {} + + ResourceTracer(const void*, int32_t) {} + + ResourceTracer(const ResourceTracer&, const char*) {} + + ResourceTracer(const ResourceTracer&, int32_t) {} + + void trace(const char*) const {} + + void traceOpen() const {} + + void maybeTrace(const char*) const {} +}; + +/** + * Default trivial implementation when --enable-tracing is not used. + */ +class FileTracer { +public: + static void traceOpen(const char*, const char*, const char*) {} +}; + +U_NAMESPACE_END + +#endif // U_ENABLE_TRACING + +#endif //__RESTRACE_H__ diff -Nru icu-64.2/source/common/schriter.cpp icu-65.1/source/common/schriter.cpp --- icu-64.2/source/common/schriter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/schriter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -101,7 +101,7 @@ && end == realThat.end; } -CharacterIterator* +StringCharacterIterator* StringCharacterIterator::clone() const { return new StringCharacterIterator(*this); } diff -Nru icu-64.2/source/common/serv.cpp icu-65.1/source/common/serv.cpp --- icu-64.2/source/common/serv.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/serv.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -333,10 +333,7 @@ ****************************************************************** */ -static UMutex *lock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex lock; ICUService::ICUService() : name() @@ -361,7 +358,7 @@ ICUService::~ICUService() { { - Mutex mutex(lock()); + Mutex mutex(&lock); clearCaches(); delete factories; factories = NULL; @@ -452,7 +449,7 @@ // if factory is not null, we're calling from within the mutex, // and since some unix machines don't have reentrant mutexes we // need to make sure not to try to lock it again. - XMutex mutex(lock(), factory != NULL); + XMutex mutex(&lock, factory != NULL); if (serviceCache == NULL) { ncthis->serviceCache = new Hashtable(status); @@ -618,7 +615,7 @@ } { - Mutex mutex(lock()); + Mutex mutex(&lock); const Hashtable* map = getVisibleIDMap(status); if (map != NULL) { ICUServiceKey* fallbackKey = createKey(matchID, status); @@ -695,7 +692,7 @@ { { UErrorCode status = U_ZERO_ERROR; - Mutex mutex(lock()); + Mutex mutex(&lock); const Hashtable* map = getVisibleIDMap(status); if (map != NULL) { ICUServiceFactory* f = (ICUServiceFactory*)map->get(id); @@ -747,7 +744,7 @@ result.setDeleter(userv_deleteStringPair); if (U_SUCCESS(status)) { ICUService* ncthis = (ICUService*)this; // cast away semantic const - Mutex mutex(lock()); + Mutex mutex(&lock); if (dnCache != NULL && dnCache->locale != locale) { delete dnCache; @@ -852,7 +849,7 @@ ICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status) { if (U_SUCCESS(status) && factoryToAdopt != NULL) { - Mutex mutex(lock()); + Mutex mutex(&lock); if (factories == NULL) { factories = new UVector(deleteUObject, NULL, status); @@ -883,7 +880,7 @@ ICUServiceFactory *factory = (ICUServiceFactory*)rkey; UBool result = FALSE; if (factory != NULL && factories != NULL) { - Mutex mutex(lock()); + Mutex mutex(&lock); if (factories->removeElement(factory)) { clearCaches(); @@ -903,7 +900,7 @@ ICUService::reset() { { - Mutex mutex(lock()); + Mutex mutex(&lock); reInitializeFactories(); clearCaches(); } diff -Nru icu-64.2/source/common/servls.cpp icu-65.1/source/common/servls.cpp --- icu-64.2/source/common/servls.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/servls.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -263,7 +263,7 @@ { const Locale& loc = Locale::getDefault(); ICULocaleService* ncThis = (ICULocaleService*)this; - static UMutex llock = U_MUTEX_INITIALIZER; + static UMutex llock; { Mutex mutex(&llock); if (loc != fallbackLocale) { diff -Nru icu-64.2/source/common/servnotf.cpp icu-65.1/source/common/servnotf.cpp --- icu-64.2/source/common/servnotf.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/servnotf.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -21,10 +21,7 @@ EventListener::~EventListener() {} UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener) -static UMutex *notifyLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex notifyLock; ICUNotifier::ICUNotifier(void) : listeners(NULL) @@ -33,7 +30,7 @@ ICUNotifier::~ICUNotifier(void) { { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); delete listeners; listeners = NULL; } @@ -50,7 +47,7 @@ } if (acceptsListener(*l)) { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); if (listeners == NULL) { listeners = new UVector(5, status); } else { @@ -83,7 +80,7 @@ } { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); if (listeners != NULL) { // identity equality check for (int i = 0, e = listeners->size(); i < e; ++i) { @@ -106,7 +103,7 @@ ICUNotifier::notifyChanged(void) { if (listeners != NULL) { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); if (listeners != NULL) { for (int i = 0, e = listeners->size(); i < e; ++i) { EventListener* el = (EventListener*)listeners->elementAt(i); diff -Nru icu-64.2/source/common/uarrsort.cpp icu-65.1/source/common/uarrsort.cpp --- icu-64.2/source/common/uarrsort.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uarrsort.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -34,6 +34,10 @@ STACK_ITEM_SIZE=200 }; +static constexpr int32_t sizeInMaxAlignTs(int32_t sizeInBytes) { + return (sizeInBytes + sizeof(max_align_t) - 1) / sizeof(max_align_t); +} + /* UComparator convenience implementations ---------------------------------- */ U_CAPI int32_t U_EXPORT2 @@ -134,25 +138,15 @@ static void insertionSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { - UAlignedMemory v[STACK_ITEM_SIZE/sizeof(UAlignedMemory)+1]; - void *pv; - /* allocate an intermediate item variable (v) */ - if(itemSize<=STACK_ITEM_SIZE) { - pv=v; - } else { - pv=uprv_malloc(itemSize); - if(pv==NULL) { - *pErrorCode=U_MEMORY_ALLOCATION_ERROR; - return; - } + icu::MaybeStackArray v; + if (sizeInMaxAlignTs(itemSize) > v.getCapacity() && + v.resize(sizeInMaxAlignTs(itemSize)) == nullptr) { + *pErrorCode = U_MEMORY_ALLOCATION_ERROR; + return; } - doInsertionSort(array, length, itemSize, cmp, context, pv); - - if(pv!=v) { - uprv_free(pv); - } + doInsertionSort(array, length, itemSize, cmp, context, v.getAlias()); } /* QuickSort ---------------------------------------------------------------- */ @@ -238,26 +232,16 @@ static void quickSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { - UAlignedMemory xw[(2*STACK_ITEM_SIZE)/sizeof(UAlignedMemory)+1]; - void *p; - /* allocate two intermediate item variables (x and w) */ - if(itemSize<=STACK_ITEM_SIZE) { - p=xw; - } else { - p=uprv_malloc(2*itemSize); - if(p==NULL) { - *pErrorCode=U_MEMORY_ALLOCATION_ERROR; - return; - } + icu::MaybeStackArray xw; + if(sizeInMaxAlignTs(itemSize)*2 > xw.getCapacity() && + xw.resize(sizeInMaxAlignTs(itemSize) * 2) == nullptr) { + *pErrorCode=U_MEMORY_ALLOCATION_ERROR; + return; } - subQuickSort(array, 0, length, itemSize, - cmp, context, p, (char *)p+itemSize); - - if(p!=xw) { - uprv_free(p); - } + subQuickSort(array, 0, length, itemSize, cmp, context, + xw.getAlias(), xw.getAlias() + sizeInMaxAlignTs(itemSize)); } /* uprv_sortArray() API ----------------------------------------------------- */ diff -Nru icu-64.2/source/common/ubidiimp.h icu-65.1/source/common/ubidiimp.h --- icu-64.2/source/common/ubidiimp.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ubidiimp.h 2019-10-03 11:16:41.000000000 +0000 @@ -198,8 +198,8 @@ /* in a Run, logicalStart will get this bit set if the run level is odd */ #define INDEX_ODD_BIT (1UL<<31) -#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)(level)<<31)) -#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)(level)<<31)) +#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)((level)&1)<<31)) +#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)((level)&1)<<31)) #define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT) #define GET_INDEX(x) ((x)&~INDEX_ODD_BIT) @@ -387,41 +387,49 @@ } BidiMemoryForAllocation; /* Macros for initial checks at function entry */ -#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) \ - if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue -#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) \ - if(!IS_VALID_PARA(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return retvalue; \ - } -#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) \ - if(!IS_VALID_PARA_OR_LINE(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return retvalue; \ - } -#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) \ - if((arg)<(start) || (arg)>=(limit)) { \ - (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ - return retvalue; \ - } - -#define RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrcode) \ - if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return -#define RETURN_VOID_IF_NOT_VALID_PARA(bidi, errcode) \ - if(!IS_VALID_PARA(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return; \ - } -#define RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode) \ - if(!IS_VALID_PARA_OR_LINE(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return; \ - } -#define RETURN_VOID_IF_BAD_RANGE(arg, start, limit, errcode) \ - if((arg)<(start) || (arg)>=(limit)) { \ - (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ - return; \ - } +#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue; \ +} UPRV_BLOCK_MACRO_END +#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return retvalue; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA_OR_LINE(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return retvalue; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if((arg)<(start) || (arg)>=(limit)) { \ + (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ + return retvalue; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrcode) UPRV_BLOCK_MACRO_BEGIN { \ + if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return; \ +} UPRV_BLOCK_MACRO_END +#define RETURN_VOID_IF_NOT_VALID_PARA(bidi, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA_OR_LINE(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_VOID_IF_BAD_RANGE(arg, start, limit, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if((arg)<(start) || (arg)>=(limit)) { \ + (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END /* helper function to (re)allocate memory if allowed */ U_CFUNC UBool diff -Nru icu-64.2/source/common/ubiditransform.cpp icu-65.1/source/common/ubiditransform.cpp --- icu-64.2/source/common/ubiditransform.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ubiditransform.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -31,11 +31,11 @@ #define SHAPE_LOGICAL U_SHAPE_TEXT_DIRECTION_LOGICAL #define SHAPE_VISUAL U_SHAPE_TEXT_DIRECTION_VISUAL_LTR -#define CHECK_LEN(STR, LEN, ERROR) { \ - if (LEN == 0) return 0; \ - if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \ - if (LEN == -1) LEN = u_strlen(STR); \ - } +#define CHECK_LEN(STR, LEN, ERROR) UPRV_BLOCK_MACRO_BEGIN { \ + if (LEN == 0) return 0; \ + if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \ + if (LEN == -1) LEN = u_strlen(STR); \ +} UPRV_BLOCK_MACRO_END #define MAX_ACTIONS 7 diff -Nru icu-64.2/source/common/ucase.cpp icu-65.1/source/common/ucase.cpp --- icu-64.2/source/common/ucase.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucase.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -116,7 +116,7 @@ * moved to the last uint16_t of the value, use +1 for beginning of next slot * @param value (out) int32_t or uint32_t output if hasSlot, otherwise not modified */ -#define GET_SLOT_VALUE(excWord, idx, pExc16, value) \ +#define GET_SLOT_VALUE(excWord, idx, pExc16, value) UPRV_BLOCK_MACRO_BEGIN { \ if(((excWord)&UCASE_EXC_DOUBLE_SLOTS)==0) { \ (pExc16)+=SLOT_OFFSET(excWord, idx); \ (value)=*pExc16; \ @@ -124,7 +124,8 @@ (pExc16)+=2*SLOT_OFFSET(excWord, idx); \ (value)=*pExc16++; \ (value)=((value)<<16)|*pExc16; \ - } + } \ +} UPRV_BLOCK_MACRO_END /* simple case mappings ----------------------------------------------------- */ diff -Nru icu-64.2/source/common/uchar.cpp icu-65.1/source/common/uchar.cpp --- icu-64.2/source/common/uchar.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uchar.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -40,7 +40,7 @@ /* constants and macros for access to the data ------------------------------ */ /* getting a uint32_t properties word from the data */ -#define GET_PROPS(c, result) ((result)=UTRIE2_GET16(&propsTrie, c)); +#define GET_PROPS(c, result) ((result)=UTRIE2_GET16(&propsTrie, c)) /* API functions ------------------------------------------------------------ */ diff -Nru icu-64.2/source/common/uchriter.cpp icu-65.1/source/common/uchriter.cpp --- icu-64.2/source/common/uchriter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uchriter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -89,7 +89,7 @@ return ustr_hashUCharsN(text, textLength) ^ pos ^ begin ^ end; } -CharacterIterator* +UCharCharacterIterator* UCharCharacterIterator::clone() const { return new UCharCharacterIterator(*this); } diff -Nru icu-64.2/source/common/ucln_cmn.cpp icu-65.1/source/common/ucln_cmn.cpp --- icu-64.2/source/common/ucln_cmn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucln_cmn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -65,9 +65,20 @@ ucln_common_registerCleanup(ECleanupCommonType type, cleanupFunc *func) { + // Thread safety messiness: From ticket 10295, calls to registerCleanup() may occur + // concurrently. Although such cases should be storing the same value, they raise errors + // from the thread sanity checker. Doing the store within a mutex avoids those. + // BUT that can trigger a recursive entry into std::call_once() in umutex.cpp when this code, + // running from the call_once function, tries to grab the ICU global mutex, which + // re-enters the mutex init path. So, work-around by special casing UCLN_COMMON_MUTEX, not + // using the ICU global mutex for it. + // + // No other point in ICU uses std::call_once(). + U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT); - if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) - { + if (type == UCLN_COMMON_MUTEX) { + gCommonCleanupFunctions[type] = func; + } else if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) { icu::Mutex m; // See ticket 10295 for discussion. gCommonCleanupFunctions[type] = func; } diff -Nru icu-64.2/source/common/ucln_cmn.h icu-65.1/source/common/ucln_cmn.h --- icu-64.2/source/common/ucln_cmn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucln_cmn.h 2019-10-03 11:16:41.000000000 +0000 @@ -22,8 +22,6 @@ /* These are the cleanup functions for various APIs. */ /* @return true if cleanup complete successfully.*/ -U_CFUNC UBool umtx_cleanup(void); - U_CFUNC UBool utrace_cleanup(void); U_CFUNC UBool ucln_lib_cleanup(void); @@ -41,6 +39,8 @@ UCLN_COMMON_LOCALE_KEY_TYPE, UCLN_COMMON_LOCALE, UCLN_COMMON_LOCALE_AVAILABLE, + UCLN_COMMON_LIKELY_SUBTAGS, + UCLN_COMMON_LOCALE_DISTANCE, UCLN_COMMON_ULOC, UCLN_COMMON_CURRENCY, UCLN_COMMON_LOADED_NORMALIZER2, @@ -62,6 +62,7 @@ */ UCLN_COMMON_UNIFIED_CACHE, UCLN_COMMON_URES, + UCLN_COMMON_MUTEX, // Mutexes should be the last to be cleaned up. UCLN_COMMON_COUNT /* This must be last */ } ECleanupCommonType; diff -Nru icu-64.2/source/common/ucnv2022.cpp icu-65.1/source/common/ucnv2022.cpp --- icu-64.2/source/common/ucnv2022.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnv2022.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -3571,20 +3571,11 @@ /* * Structure for cloning an ISO 2022 converter into a single memory block. - * ucnv_safeClone() of the converter will align the entire cloneStruct, - * and then ucnv_safeClone() of the sub-converter may additionally align - * currentConverter inside the cloneStruct, for which we need the deadSpace - * after currentConverter. - * This is because UAlignedMemory may be larger than the actually - * necessary alignment size for the platform. - * The other cloneStruct fields will not be moved around, - * and are aligned properly with cloneStruct's alignment. */ struct cloneStruct { UConverter cnv; UConverter currentConverter; - UAlignedMemory deadSpace; UConverterDataISO2022 mydata; }; @@ -3602,6 +3593,10 @@ UConverterDataISO2022 *cnvData; int32_t i, size; + if (U_FAILURE(*status)){ + return nullptr; + } + if (*pBufferSize == 0) { /* 'preflighting' request - set needed size into *pBufferSize */ *pBufferSize = (int32_t)sizeof(struct cloneStruct); return NULL; @@ -3619,7 +3614,7 @@ /* share the subconverters */ if(cnvData->currentConverter != NULL) { - size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */ + size = (int32_t)sizeof(UConverter); localClone->mydata.currentConverter = ucnv_safeClone(cnvData->currentConverter, &localClone->currentConverter, diff -Nru icu-64.2/source/common/ucnv_bld.cpp icu-65.1/source/common/ucnv_bld.cpp --- icu-64.2/source/common/ucnv_bld.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnv_bld.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -194,10 +194,7 @@ /*initializes some global variables */ static UHashtable *SHARED_DATA_HASHTABLE = NULL; -static icu::UMutex *cnvCacheMutex() { /* Mutex for synchronizing cnv cache access. */ - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UMutex cnvCacheMutex; /* Note: the global mutex is used for */ /* reference count updates. */ @@ -602,9 +599,9 @@ ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData) { if(sharedData != NULL && sharedData->isReferenceCounted) { - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); ucnv_unload(sharedData); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); } } @@ -612,9 +609,9 @@ ucnv_incrementRefCount(UConverterSharedData *sharedData) { if(sharedData != NULL && sharedData->isReferenceCounted) { - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); sharedData->referenceCounter++; - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); } } @@ -815,9 +812,9 @@ pArgs->nestedLoads=1; pArgs->pkg=NULL; - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); mySharedConverterData = ucnv_load(pArgs, err); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); if (U_FAILURE (*err) || (mySharedConverterData == NULL)) { return NULL; @@ -1064,7 +1061,7 @@ * because the sequence of looking up in the cache + incrementing * is protected by cnvCacheMutex. */ - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); /* * double loop: A delta/extension-only converter has a pointer to its base table's * shared data; the first iteration of the outer loop may see the delta converter @@ -1093,7 +1090,7 @@ } } } while(++i == 1 && remaining > 0); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining); @@ -1199,7 +1196,7 @@ } algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name); - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); gDefaultAlgorithmicSharedData = algorithmicSharedData; gDefaultConverterContainsOption = containsOption; @@ -1215,7 +1212,7 @@ ucnv_enableCleanup(); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); } #endif @@ -1240,7 +1237,7 @@ but ucnv_setDefaultName is not thread safe. */ { - icu::Mutex lock(cnvCacheMutex()); + icu::Mutex lock(&cnvCacheMutex); name = gDefaultConverterName; } if(name==NULL) { diff -Nru icu-64.2/source/common/ucnvbocu.cpp icu-65.1/source/common/ucnvbocu.cpp --- icu-64.2/source/common/ucnvbocu.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnvbocu.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -202,14 +202,14 @@ * @param d Divisor. * @param m Output variable for the rest (modulo result). */ -#define NEGDIVMOD(n, d, m) { \ +#define NEGDIVMOD(n, d, m) UPRV_BLOCK_MACRO_BEGIN { \ (m)=(n)%(d); \ (n)/=(d); \ if((m)<0) { \ --(n); \ (m)+=(d); \ } \ -} +} UPRV_BLOCK_MACRO_END /* Faster versions of packDiff() for single-byte-encoded diff values. */ diff -Nru icu-64.2/source/common/ucnv.cpp icu-65.1/source/common/ucnv.cpp --- icu-64.2/source/common/ucnv.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnv.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -25,6 +25,8 @@ #if !UCONFIG_NO_CONVERSION +#include + #include "unicode/ustring.h" #include "unicode/ucnv.h" #include "unicode/ucnv_err.h" @@ -158,7 +160,6 @@ UConverter *localConverter, *allocatedConverter; int32_t stackBufferSize; int32_t bufferSizeNeeded; - char *stackBufferChars = (char *)stackBuffer; UErrorCode cbErr; UConverterToUnicodeArgs toUArgs = { sizeof(UConverterToUnicodeArgs), @@ -224,23 +225,22 @@ } } - - /* Pointers on 64-bit platforms need to be aligned - * on a 64-bit boundary in memory. + /* Adjust (if necessary) the stackBuffer pointer to be aligned correctly for a UConverter. + * TODO(Jira ICU-20736) Redo this using std::align() once g++4.9 compatibility is no longer needed. */ - if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) { - int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars); - if(stackBufferSize > offsetUp) { - stackBufferSize -= offsetUp; - stackBufferChars += offsetUp; + if (stackBuffer) { + uintptr_t p = reinterpret_cast(stackBuffer); + uintptr_t aligned_p = (p + alignof(UConverter) - 1) & ~(alignof(UConverter) - 1); + ptrdiff_t pointerAdjustment = aligned_p - p; + if (bufferSizeNeeded + pointerAdjustment <= stackBufferSize) { + stackBuffer = reinterpret_cast(aligned_p); + stackBufferSize -= pointerAdjustment; } else { /* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */ stackBufferSize = 1; } } - stackBuffer = (void *)stackBufferChars; - /* Now, see if we must allocate any memory */ if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL) { @@ -475,7 +475,7 @@ const UChar *s, int32_t length, UErrorCode *err) { - UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1]; + alignas(UConverter) char cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE]; char chars[UCNV_ERROR_BUFFER_LENGTH]; UConverter *clone; diff -Nru icu-64.2/source/common/ucnvhz.cpp icu-65.1/source/common/ucnvhz.cpp --- icu-64.2/source/common/ucnvhz.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnvhz.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -38,7 +38,7 @@ #define ESC_LEN 2 -#define CONCAT_ESCAPE_MACRO( args, targetIndex,targetLength,strToAppend, err, len,sourceIndex){ \ +#define CONCAT_ESCAPE_MACRO(args, targetIndex,targetLength,strToAppend, err, len,sourceIndex) UPRV_BLOCK_MACRO_BEGIN { \ while(len-->0){ \ if(targetIndex < targetLength){ \ args->target[targetIndex] = (unsigned char) *strToAppend; \ @@ -53,7 +53,7 @@ } \ strToAppend++; \ } \ -} +} UPRV_BLOCK_MACRO_END typedef struct{ @@ -518,19 +518,11 @@ /* * Structure for cloning an HZ converter into a single memory block. - * ucnv_safeClone() of the HZ converter will align the entire cloneHZStruct, - * and then ucnv_safeClone() of the sub-converter may additionally align - * subCnv inside the cloneHZStruct, for which we need the deadSpace after - * subCnv. This is because UAlignedMemory may be larger than the actually - * necessary alignment size for the platform. - * The other cloneHZStruct fields will not be moved around, - * and are aligned properly with cloneHZStruct's alignment. */ struct cloneHZStruct { UConverter cnv; UConverter subCnv; - UAlignedMemory deadSpace; UConverterDataHZ mydata; }; @@ -545,12 +537,12 @@ int32_t size, bufferSizeNeeded = sizeof(struct cloneHZStruct); if (U_FAILURE(*status)){ - return 0; + return nullptr; } if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */ *pBufferSize = bufferSizeNeeded; - return 0; + return nullptr; } localClone = (struct cloneHZStruct *)stackBuffer; @@ -561,7 +553,7 @@ localClone->cnv.isExtraLocal = TRUE; /* deep-clone the sub-converter */ - size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */ + size = (int32_t)sizeof(UConverter); ((UConverterDataHZ*)localClone->cnv.extraInfo)->gbConverter = ucnv_safeClone(((UConverterDataHZ*)cnv->extraInfo)->gbConverter, &localClone->subCnv, &size, status); diff -Nru icu-64.2/source/common/ucnvisci.cpp icu-65.1/source/common/ucnvisci.cpp --- icu-64.2/source/common/ucnvisci.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnvisci.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -831,7 +831,7 @@ }; -#define WRITE_TO_TARGET_FROM_U(args,offsets,source,target,targetLimit,targetByteUnit,err){ \ +#define WRITE_TO_TARGET_FROM_U(args,offsets,source,target,targetLimit,targetByteUnit,err) UPRV_BLOCK_MACRO_BEGIN { \ int32_t offset = (int32_t)(source - args->source-1); \ /* write the targetUniChar to target */ \ if(target < targetLimit){ \ @@ -884,7 +884,7 @@ (uint8_t) (targetByteUnit); \ *err = U_BUFFER_OVERFLOW_ERROR; \ } \ -} +} UPRV_BLOCK_MACRO_END /* Rules: * Explicit Halant : @@ -1119,7 +1119,7 @@ { GURMUKHI, PNJ_MASK } }; -#define WRITE_TO_TARGET_TO_U(args,source,target,offsets,offset,targetUniChar,delta, err){\ +#define WRITE_TO_TARGET_TO_U(args,source,target,offsets,offset,targetUniChar,delta, err) UPRV_BLOCK_MACRO_BEGIN { \ /* add offset to current Indic Block */ \ if(targetUniChar>ASCII_END && \ targetUniChar != ZWJ && \ @@ -1140,9 +1140,9 @@ (UChar)targetUniChar; \ *err = U_BUFFER_OVERFLOW_ERROR; \ } \ -} +} UPRV_BLOCK_MACRO_END -#define GET_MAPPING(sourceChar,targetUniChar,data){ \ +#define GET_MAPPING(sourceChar,targetUniChar,data) UPRV_BLOCK_MACRO_BEGIN { \ targetUniChar = toUnicodeTable[(sourceChar)] ; \ /* is the code point valid in current script? */ \ if(sourceChar> ASCII_END && \ @@ -1153,7 +1153,7 @@ targetUniChar=missingCharMarker; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /*********** * Rules for ISCII to Unicode converter diff -Nru icu-64.2/source/common/ucnv_lmb.cpp icu-65.1/source/common/ucnv_lmb.cpp --- icu-64.2/source/common/ucnv_lmb.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnv_lmb.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1107,11 +1107,13 @@ all input as required by ICU converter semantics. */ -#define CHECK_SOURCE_LIMIT(index) \ - if (args->source+index > args->sourceLimit){\ - *err = U_TRUNCATED_CHAR_FOUND;\ - args->source = args->sourceLimit;\ - return 0xffff;} +#define CHECK_SOURCE_LIMIT(index) UPRV_BLOCK_MACRO_BEGIN { \ + if (args->source+index > args->sourceLimit) { \ + *err = U_TRUNCATED_CHAR_FOUND; \ + args->source = args->sourceLimit; \ + return 0xffff; \ + } \ +} UPRV_BLOCK_MACRO_END /* Return the Unicode representation for the current LMBCS character */ diff -Nru icu-64.2/source/common/ucnvsel.cpp icu-65.1/source/common/ucnvsel.cpp --- icu-64.2/source/common/ucnvsel.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucnvsel.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -691,36 +691,36 @@ /* internal function! */ static UEnumeration *selectForMask(const UConverterSelector* sel, - uint32_t *mask, UErrorCode *status) { + uint32_t *theMask, UErrorCode *status) { + LocalMemory mask(theMask); // this is the context we will use. Store a table of indices to which // encodings are legit. - struct Enumerator* result = (Enumerator*)uprv_malloc(sizeof(Enumerator)); - if (result == NULL) { - uprv_free(mask); + LocalMemory result(static_cast(uprv_malloc(sizeof(Enumerator)))); + if (result.isNull()) { *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - result->index = NULL; // this will be allocated later! + result->index = nullptr; // this will be allocated later! result->length = result->cur = 0; result->sel = sel; - UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration)); - if (en == NULL) { + LocalMemory en(static_cast(uprv_malloc(sizeof(UEnumeration)))); + if (en.isNull()) { // TODO(markus): Combine Enumerator and UEnumeration into one struct. - uprv_free(mask); - uprv_free(result); *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - memcpy(en, &defaultEncodings, sizeof(UEnumeration)); - en->context = result; - + memcpy(en.getAlias(), &defaultEncodings, sizeof(UEnumeration)); + int32_t columns = (sel->encodingsCount+31)/32; - int16_t numOnes = countOnes(mask, columns); + int16_t numOnes = countOnes(mask.getAlias(), columns); // now, we know the exact space we need for index if (numOnes > 0) { - result->index = (int16_t*) uprv_malloc(numOnes * sizeof(int16_t)); - + result->index = static_cast(uprv_malloc(numOnes * sizeof(int16_t))); + if (result->index == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } int32_t i, j; int16_t k = 0; for (j = 0 ; j < columns; j++) { @@ -734,8 +734,8 @@ } } //otherwise, index will remain NULL (and will never be touched by //the enumerator code anyway) - uprv_free(mask); - return en; + en->context = result.orphan(); + return en.orphan(); } /* check a string against the selector - UTF16 version */ diff -Nru icu-64.2/source/common/ucptrie.cpp icu-65.1/source/common/ucptrie.cpp --- icu-64.2/source/common/ucptrie.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucptrie.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -280,7 +280,7 @@ int32_t prevI3Block = -1; int32_t prevBlock = -1; UChar32 c = start; - uint32_t trieValue, value; + uint32_t trieValue, value = nullValue; bool haveValue = false; do { int32_t i3Block; diff -Nru icu-64.2/source/common/ucurr.cpp icu-65.1/source/common/ucurr.cpp --- icu-64.2/source/common/ucurr.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ucurr.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -365,10 +365,7 @@ #if !UCONFIG_NO_SERVICE struct CReg; -static UMutex *gCRegLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gCRegLock; static CReg* gCRegHead = 0; struct CReg : public icu::UMemory { @@ -394,14 +391,14 @@ if (status && U_SUCCESS(*status) && _iso && _id) { CReg* n = new CReg(_iso, _id); if (n) { - umtx_lock(gCRegLock()); + umtx_lock(&gCRegLock); if (!gCRegHead) { /* register for the first time */ ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cleanup); } n->next = gCRegHead; gCRegHead = n; - umtx_unlock(gCRegLock()); + umtx_unlock(&gCRegLock); return n; } *status = U_MEMORY_ALLOCATION_ERROR; @@ -411,7 +408,7 @@ static UBool unreg(UCurrRegistryKey key) { UBool found = FALSE; - umtx_lock(gCRegLock()); + umtx_lock(&gCRegLock); CReg** p = &gCRegHead; while (*p) { @@ -424,13 +421,13 @@ p = &((*p)->next); } - umtx_unlock(gCRegLock()); + umtx_unlock(&gCRegLock); return found; } static const UChar* get(const char* id) { const UChar* result = NULL; - umtx_lock(gCRegLock()); + umtx_lock(&gCRegLock); CReg* p = gCRegHead; /* register cleanup of the mutex */ @@ -442,7 +439,7 @@ } p = p->next; } - umtx_unlock(gCRegLock()); + umtx_unlock(&gCRegLock); return result; } @@ -716,7 +713,9 @@ // We no longer support choice format data in names. Data should not contain // choice patterns. - *isChoiceFormat = FALSE; + if (isChoiceFormat != NULL) { + *isChoiceFormat = FALSE; + } if (U_SUCCESS(ec2)) { U_ASSERT(s != NULL); return s; @@ -1356,10 +1355,7 @@ // It is a simple round-robin replacement strategy. static int8_t currentCacheEntryIndex = 0; -static UMutex *gCurrencyCacheMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gCurrencyCacheMutex; // Cache deletion static void @@ -1408,7 +1404,7 @@ CurrencyNameStruct* currencySymbols = NULL; CurrencyNameCacheEntry* cacheEntry = NULL; - umtx_lock(gCurrencyCacheMutex()); + umtx_lock(&gCurrencyCacheMutex); // in order to handle racing correctly, // not putting 'search' in a separate function. int8_t found = -1; @@ -1423,13 +1419,13 @@ cacheEntry = currCache[found]; ++(cacheEntry->refCount); } - umtx_unlock(gCurrencyCacheMutex()); + umtx_unlock(&gCurrencyCacheMutex); if (found == -1) { collectCurrencyNames(locale, ¤cyNames, &total_currency_name_count, ¤cySymbols, &total_currency_symbol_count, ec); if (U_FAILURE(ec)) { return NULL; } - umtx_lock(gCurrencyCacheMutex()); + umtx_lock(&gCurrencyCacheMutex); // check again. for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) { if (currCache[i]!= NULL && @@ -1468,19 +1464,19 @@ cacheEntry = currCache[found]; ++(cacheEntry->refCount); } - umtx_unlock(gCurrencyCacheMutex()); + umtx_unlock(&gCurrencyCacheMutex); } return cacheEntry; } static void releaseCacheEntry(CurrencyNameCacheEntry* cacheEntry) { - umtx_lock(gCurrencyCacheMutex()); + umtx_lock(&gCurrencyCacheMutex); --(cacheEntry->refCount); if (cacheEntry->refCount == 0) { // remove deleteCacheEntry(cacheEntry); } - umtx_unlock(gCurrencyCacheMutex()); + umtx_unlock(&gCurrencyCacheMutex); } U_CAPI void @@ -1601,10 +1597,9 @@ { U_NAMESPACE_USE - UBool isChoiceFormat; int32_t len; const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME, - &isChoiceFormat, &len, &ec); + nullptr /* isChoiceFormat */, &len, &ec); if (U_SUCCESS(ec)) { result.setTo(currname, len); } diff -Nru icu-64.2/source/common/udata.cpp icu-65.1/source/common/udata.cpp --- icu-64.2/source/common/udata.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/udata.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -33,6 +33,7 @@ #include "cstring.h" #include "mutex.h" #include "putilimp.h" +#include "restrace.h" #include "uassert.h" #include "ucln_cmn.h" #include "ucmndata.h" @@ -110,11 +111,12 @@ static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */ static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER; -#if U_PLATFORM_HAS_WINUWP_API == 0 +#if !defined(ICU_DATA_DIR_WINDOWS) static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; // Access not synchronized. // Modifying is documented as thread-unsafe. #else -static UDataFileAccess gDataFileAccess = UDATA_NO_FILES; // Windows UWP looks in one spot explicitly +// If we are using the Windows data directory, then look in one spot only. +static UDataFileAccess gDataFileAccess = UDATA_NO_FILES; #endif static UBool U_CALLCONV @@ -206,7 +208,7 @@ return didUpdate; } -#if U_PLATFORM_HAS_WINUWP_API == 0 +#if !defined(ICU_DATA_DIR_WINDOWS) static UBool setCommonICUDataPointer(const void *pData, UBool /*warn*/, UErrorCode *pErrorCode) { @@ -320,7 +322,7 @@ retVal = el->item; } #ifdef UDATA_DEBUG - fprintf(stderr, "Cache: [%s] -> %p\n", baseName, retVal); + fprintf(stderr, "Cache: [%s] -> %p\n", baseName, (void*) retVal); #endif return retVal; } @@ -383,7 +385,7 @@ #ifdef UDATA_DEBUG fprintf(stderr, "Cache: [%s] <<< %p : %s. vFunc=%p\n", newElement->name, - newElement->item, u_errorName(subErr), newElement->item->vFuncs); + (void*) newElement->item, u_errorName(subErr), (void*) newElement->item->vFuncs); #endif if (subErr == U_USING_DEFAULT_WARNING || U_FAILURE(subErr)) { @@ -477,7 +479,7 @@ nextPath = itemPath.data(); } #ifdef UDATA_DEBUG - fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, inSuffix); + fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, (void*) inSuffix); #endif /** Suffix **/ @@ -492,12 +494,11 @@ /* pathBuffer will hold the output path strings returned by this iterator */ #ifdef UDATA_DEBUG - fprintf(stderr, "%p: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=%s], [nextpath=%s], [checklast4=%s]\n", - iter, + fprintf(stderr, "0: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=%s], [nextpath=%s], [checklast4=%s]\n", item, path, basename, - suffix, + suffix.data(), itemPath.data(), nextPath, checkLastFour?"TRUE":"false"); @@ -553,7 +554,7 @@ fprintf(stderr, "rest of path (IDD) = %s\n", currentPath); fprintf(stderr, " "); { - uint32_t qqq; + int32_t qqq; for(qqq=0;qqqpHeader == &U_ICUDATA_ENTRY_POINT) { @@ -714,7 +717,8 @@ setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode); } */ -#if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time +#if !defined(ICU_DATA_DIR_WINDOWS) +// When using the Windows system data, we expect only a single data file. setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT, FALSE, pErrorCode); { Mutex lock; @@ -831,7 +835,7 @@ * Use a specific mutex to avoid nested locks of the global mutex. */ #if MAP_IMPLEMENTATION==MAP_STDIO - static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER; + static UMutex extendICUDataMutex; umtx_lock(&extendICUDataMutex); #endif if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) { @@ -1070,13 +1074,13 @@ /* look up the data piece in the common data */ pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &length, subErrorCode); #ifdef UDATA_DEBUG - fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, pHeader, u_errorName(*subErrorCode)); + fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, (void*) pHeader, u_errorName(*subErrorCode)); #endif if(pHeader!=NULL) { pEntryData = checkDataItem(pHeader, isAcceptable, context, type, name, subErrorCode, pErrorCode); #ifdef UDATA_DEBUG - fprintf(stderr, "pEntryData=%p\n", pEntryData); + fprintf(stderr, "pEntryData=%p\n", (void*) pEntryData); #endif if (U_FAILURE(*pErrorCode)) { return NULL; @@ -1168,6 +1172,9 @@ UBool isICUData = FALSE; + FileTracer::traceOpen(path, type, name); + + /* Is this path ICU data? */ if(path == NULL || !strcmp(path, U_ICUDATA_ALIAS) || /* "ICUDATA" */ @@ -1276,12 +1283,12 @@ fprintf(stderr, " tocEntryPath = %s\n", tocEntryName.data()); #endif -#if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time +#if !defined(ICU_DATA_DIR_WINDOWS) if(path == NULL) { path = COMMON_DATA_NAME; /* "icudt26e" */ } #else - // Windows UWP expects only a single data file. + // When using the Windows system data, we expects only a single data file. path = COMMON_DATA_NAME; /* "icudt26e" */ #endif diff -Nru icu-64.2/source/common/uhash.cpp icu-65.1/source/common/uhash.cpp --- icu-64.2/source/common/uhash.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uhash.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -119,13 +119,14 @@ /* This macro expects a UHashTok.pointer as its keypointer and valuepointer parameters */ -#define HASH_DELETE_KEY_VALUE(hash, keypointer, valuepointer) \ - if (hash->keyDeleter != NULL && keypointer != NULL) { \ - (*hash->keyDeleter)(keypointer); \ - } \ - if (hash->valueDeleter != NULL && valuepointer != NULL) { \ - (*hash->valueDeleter)(valuepointer); \ - } +#define HASH_DELETE_KEY_VALUE(hash, keypointer, valuepointer) UPRV_BLOCK_MACRO_BEGIN { \ + if (hash->keyDeleter != NULL && keypointer != NULL) { \ + (*hash->keyDeleter)(keypointer); \ + } \ + if (hash->valueDeleter != NULL && valuepointer != NULL) { \ + (*hash->valueDeleter)(valuepointer); \ + } \ +} UPRV_BLOCK_MACRO_END /* * Constants for hinting whether a key or value is an integer diff -Nru icu-64.2/source/common/uidna.cpp icu-65.1/source/common/uidna.cpp --- icu-64.2/source/common/uidna.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uidna.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -57,18 +57,16 @@ inline static UBool startsWithPrefix(const UChar* src , int32_t srcLength){ - UBool startsWithPrefix = TRUE; - if(srcLength < ACE_PREFIX_LENGTH){ return FALSE; } for(int8_t i=0; i< ACE_PREFIX_LENGTH; i++){ if(toASCIILower(src[i]) != ACE_PREFIX[i]){ - startsWithPrefix = FALSE; + return FALSE; } } - return startsWithPrefix; + return TRUE; } @@ -441,6 +439,7 @@ for(int32_t j=0; j 0x7f){ srcIsASCII = FALSE; + break; }/*else if(isLDHChar(src[j])==FALSE){ // here we do not assemble surrogates // since we know that LDH code points diff -Nru icu-64.2/source/common/uinvchar.cpp icu-65.1/source/common/uinvchar.cpp --- icu-64.2/source/common/uinvchar.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uinvchar.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -207,7 +207,8 @@ while(length>0) { u=*us++; if(!UCHAR_IS_INVARIANT(u)) { - UPRV_UNREACHABLE; /* Variant characters were used. These are not portable in ICU. */ + U_ASSERT(FALSE); /* Variant characters were used. These are not portable in ICU. */ + u=0; } *cs++=(char)UCHAR_TO_CHAR(u); --length; @@ -445,6 +446,13 @@ return length; } +U_CFUNC UBool +uprv_isEbcdicAtSign(char c) { + static const uint8_t ebcdicAtSigns[] = { + 0x7C, 0x44, 0x66, 0x80, 0xAC, 0xAE, 0xAF, 0xB5, 0xEC, 0xEF, 0x00 }; + return c != 0 && uprv_strchr((const char *)ebcdicAtSigns, c) != nullptr; +} + /* compare invariant strings; variant characters compare less than others and unlike each other */ U_CFUNC int32_t uprv_compareInvAscii(const UDataSwapper *ds, @@ -562,6 +570,11 @@ } U_CAPI char U_EXPORT2 +uprv_ebcdicToAscii(char c) { + return (char)asciiFromEbcdic[(uint8_t)c]; +} + +U_CAPI char U_EXPORT2 uprv_ebcdicToLowercaseAscii(char c) { return (char)lowercaseAsciiFromEbcdic[(uint8_t)c]; } diff -Nru icu-64.2/source/common/uinvchar.h icu-65.1/source/common/uinvchar.h --- icu-64.2/source/common/uinvchar.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uinvchar.h 2019-10-03 11:16:41.000000000 +0000 @@ -68,6 +68,75 @@ # error Unknown charset family! #endif +#ifdef __cplusplus + +U_NAMESPACE_BEGIN + +/** + * Like U_UPPER_ORDINAL(x) but with validation. + * Returns 0..25 for A..Z else a value outside 0..25. + */ +inline int32_t uprv_upperOrdinal(int32_t c) { +#if U_CHARSET_FAMILY==U_ASCII_FAMILY + return c - 'A'; +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY + // EBCDIC: A-Z (26 letters) is split into three ranges A-I (9 letters), J-R (9), S-Z (8). + // https://en.wikipedia.org/wiki/EBCDIC_037#Codepage_layout + if (c <= 'I') { return c - 'A'; } // A-I --> 0-8 + if (c < 'J') { return -1; } + if (c <= 'R') { return c - 'J' + 9; } // J-R --> 9..17 + if (c < 'S') { return -1; } + return c - 'S' + 18; // S-Z --> 18..25 +#else +# error Unknown charset family! +#endif +} + +// Like U_UPPER_ORDINAL(x) but for lowercase and with validation. +// Returns 0..25 for a..z else a value outside 0..25. +inline int32_t uprv_lowerOrdinal(int32_t c) { +#if U_CHARSET_FAMILY==U_ASCII_FAMILY + return c - 'a'; +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY + // EBCDIC: a-z (26 letters) is split into three ranges a-i (9 letters), j-r (9), s-z (8). + // https://en.wikipedia.org/wiki/EBCDIC_037#Codepage_layout + if (c <= 'i') { return c - 'a'; } // a-i --> 0-8 + if (c < 'j') { return -1; } + if (c <= 'r') { return c - 'j' + 9; } // j-r --> 9..17 + if (c < 's') { return -1; } + return c - 's' + 18; // s-z --> 18..25 +#else +# error Unknown charset family! +#endif +} + +U_NAMESPACE_END + +#endif + +/** + * Returns true if c == '@' is possible. + * The @ sign is variant, and the @ sign used on one + * EBCDIC machine won't be compiled the same way on other EBCDIC based machines. + * @internal + */ +U_CFUNC UBool +uprv_isEbcdicAtSign(char c); + +/** + * \def uprv_isAtSign + * Returns true if c == '@' is possible. + * For ASCII, checks for exactly '@'. For EBCDIC, calls uprv_isEbcdicAtSign(). + * @internal + */ +#if U_CHARSET_FAMILY==U_ASCII_FAMILY +# define uprv_isAtSign(c) ((c)=='@') +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY +# define uprv_isAtSign(c) uprv_isEbcdicAtSign(c) +#else +# error Unknown charset family! +#endif + /** * Compare two EBCDIC invariant-character strings in ASCII order. * @internal @@ -87,6 +156,26 @@ #else # error Unknown charset family! #endif + +/** + * Converts an EBCDIC invariant character to ASCII. + * @internal + */ +U_INTERNAL char U_EXPORT2 +uprv_ebcdicToAscii(char c); + +/** + * \def uprv_invCharToAscii + * Converts an invariant character to ASCII. + * @internal + */ +#if U_CHARSET_FAMILY==U_ASCII_FAMILY +# define uprv_invCharToAscii(c) (c) +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY +# define uprv_invCharToAscii(c) uprv_ebcdicToAscii(c) +#else +# error Unknown charset family! +#endif /** * Converts an EBCDIC invariant character to lowercase ASCII. diff -Nru icu-64.2/source/common/uloc.cpp icu-65.1/source/common/uloc.cpp --- icu-64.2/source/common/uloc.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uloc.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -148,7 +148,8 @@ "mad", "maf", "mag", "mai", "mak", "man", "mas", "mde", "mdf", "mdh", "mdr", "men", "mer", "mfe", "mg", "mga", "mgh", "mgo", "mh", "mi", "mic", "min", "mis", "mk", - "ml", "mn", "mnc", "mni", "moh", "mos", "mr", "mrj", + "ml", "mn", "mnc", "mni", "mo", + "moh", "mos", "mr", "mrj", "ms", "mt", "mua", "mul", "mus", "mwl", "mwr", "mwv", "my", "mye", "myv", "mzn", "na", "nan", "nap", "naq", "nb", "nd", "nds", "ne", @@ -264,7 +265,8 @@ "mad", "maf", "mag", "mai", "mak", "man", "mas", "mde", "mdf", "mdh", "mdr", "men", "mer", "mfe", "mlg", "mga", "mgh", "mgo", "mah", "mri", "mic", "min", "mis", "mkd", - "mal", "mon", "mnc", "mni", "moh", "mos", "mar", "mrj", + "mal", "mon", "mnc", "mni", "mol", + "moh", "mos", "mar", "mrj", "msa", "mlt", "mua", "mul", "mus", "mwl", "mwr", "mwv", "mya", "mye", "myv", "mzn", "nau", "nan", "nap", "naq", "nob", "nde", "nds", "nep", @@ -480,14 +482,15 @@ /* Test if the locale id has BCP47 u extension and does not have '@' */ #define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == NULL && getShortestSubtagLength(localeID) == 1) /* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */ -#define _ConvertBCP47(finalID, id, buffer, length,err) \ - if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \ - U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \ - finalID=id; \ - if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \ - } else { \ - finalID=buffer; \ - } +#define _ConvertBCP47(finalID, id, buffer, length,err) UPRV_BLOCK_MACRO_BEGIN { \ + if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \ + U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \ + finalID=id; \ + if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \ + } else { \ + finalID=buffer; \ + } \ +} UPRV_BLOCK_MACRO_END /* Gets the size of the shortest subtag in the given localeID. */ static int32_t getShortestSubtagLength(const char *localeID) { int32_t localeIDLength = static_cast(uprv_strlen(localeID)); @@ -1454,31 +1457,29 @@ U_CAPI UEnumeration* U_EXPORT2 uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status) { - UKeywordsContext *myContext = NULL; - UEnumeration *result = NULL; + LocalMemory myContext; + LocalMemory result; - if(U_FAILURE(*status)) { - return NULL; + if (U_FAILURE(*status)) { + return nullptr; } - result = (UEnumeration *)uprv_malloc(sizeof(UEnumeration)); - /* Null pointer test */ - if (result == NULL) { + myContext.adoptInstead(static_cast(uprv_malloc(sizeof(UKeywordsContext)))); + result.adoptInstead(static_cast(uprv_malloc(sizeof(UEnumeration)))); + if (myContext.isNull() || result.isNull()) { *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - uprv_memcpy(result, &gKeywordsEnum, sizeof(UEnumeration)); - myContext = static_cast(uprv_malloc(sizeof(UKeywordsContext))); - if (myContext == NULL) { + uprv_memcpy(result.getAlias(), &gKeywordsEnum, sizeof(UEnumeration)); + myContext->keywords = static_cast(uprv_malloc(keywordListSize+1)); + if (myContext->keywords == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; - uprv_free(result); - return NULL; + return nullptr; } - myContext->keywords = (char *)uprv_malloc(keywordListSize+1); uprv_memcpy(myContext->keywords, keywordList, keywordListSize); myContext->keywords[keywordListSize] = 0; myContext->current = myContext->keywords; - result->context = myContext; - return result; + result->context = myContext.orphan(); + return result.orphan(); } U_CAPI UEnumeration* U_EXPORT2 diff -Nru icu-64.2/source/common/uloc_tag.cpp icu-65.1/source/common/uloc_tag.cpp --- icu-64.2/source/common/uloc_tag.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uloc_tag.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1558,10 +1558,8 @@ return; } - if (!_addAttributeToList(&attrFirst, attr)) { - *status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } + // duplicate attribute is ignored, causes no error. + _addAttributeToList(&attrFirst, attr); /* next tag */ pTag += len; diff -Nru icu-64.2/source/common/umutex.cpp icu-65.1/source/common/umutex.cpp --- icu-64.2/source/common/umutex.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/umutex.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -24,6 +24,7 @@ #include "unicode/utypes.h" #include "uassert.h" +#include "ucln_cmn.h" #include "cmemory.h" U_NAMESPACE_BEGIN @@ -35,60 +36,94 @@ #error U_USER_MUTEX_CPP not supported #endif + /************************************************************************************************* * * ICU Mutex wrappers. * *************************************************************************************************/ -// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. -static UMutex *globalMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; +namespace { +std::mutex *initMutex; +std::condition_variable *initCondition; + +// The ICU global mutex. +// Used when ICU implementation code passes nullptr for the mutex pointer. +UMutex globalMutex; + +std::once_flag initFlag; +std::once_flag *pInitFlag = &initFlag; + +} // Anonymous namespace + +U_CDECL_BEGIN +static UBool U_CALLCONV umtx_cleanup() { + initMutex->~mutex(); + initCondition->~condition_variable(); + UMutex::cleanup(); + + // Reset the once_flag, by destructing it and creating a fresh one in its place. + // Do not use this trick anywhere else in ICU; use umtx_initOnce, not std::call_once(). + pInitFlag->~once_flag(); + pInitFlag = new(&initFlag) std::once_flag(); + return true; +} + +static void U_CALLCONV umtx_init() { + initMutex = STATIC_NEW(std::mutex); + initCondition = STATIC_NEW(std::condition_variable); + ucln_common_registerCleanup(UCLN_COMMON_MUTEX, umtx_cleanup); +} +U_CDECL_END + + +std::mutex *UMutex::getMutex() { + std::mutex *retPtr = fMutex.load(std::memory_order_acquire); + if (retPtr == nullptr) { + std::call_once(*pInitFlag, umtx_init); + std::lock_guard guard(*initMutex); + retPtr = fMutex.load(std::memory_order_acquire); + if (retPtr == nullptr) { + fMutex = new(fStorage) std::mutex(); + retPtr = fMutex; + fListLink = gListHead; + gListHead = this; + } + } + U_ASSERT(retPtr != nullptr); + return retPtr; } -U_CAPI void U_EXPORT2 -umtx_lock(UMutex *mutex) { - if (mutex == nullptr) { - mutex = globalMutex(); +UMutex *UMutex::gListHead = nullptr; + +void UMutex::cleanup() { + UMutex *next = nullptr; + for (UMutex *m = gListHead; m != nullptr; m = next) { + (*m->fMutex).~mutex(); + m->fMutex = nullptr; + next = m->fListLink; + m->fListLink = nullptr; } - mutex->fMutex.lock(); + gListHead = nullptr; } U_CAPI void U_EXPORT2 -umtx_unlock(UMutex* mutex) -{ +umtx_lock(UMutex *mutex) { if (mutex == nullptr) { - mutex = globalMutex(); + mutex = &globalMutex; } - mutex->fMutex.unlock(); + mutex->lock(); } -UConditionVar::UConditionVar() : fCV() { -} -UConditionVar::~UConditionVar() { -} - -U_CAPI void U_EXPORT2 -umtx_condWait(UConditionVar *cond, UMutex *mutex) { +U_CAPI void U_EXPORT2 +umtx_unlock(UMutex* mutex) +{ if (mutex == nullptr) { - mutex = globalMutex(); + mutex = &globalMutex; } - cond->fCV.wait(mutex->fMutex); -} - - -U_CAPI void U_EXPORT2 -umtx_condBroadcast(UConditionVar *cond) { - cond->fCV.notify_all(); -} - - -U_CAPI void U_EXPORT2 -umtx_condSignal(UConditionVar *cond) { - cond->fCV.notify_one(); + mutex->unlock(); } @@ -98,17 +133,6 @@ * *************************************************************************************************/ -static std::mutex &initMutex() { - static std::mutex m; - return m; -} - -static std::condition_variable &initCondition() { - static std::condition_variable cv; - return cv; -} - - // This function is called when a test of a UInitOnce::fState reveals that // initialization has not completed, that we either need to call the init // function on this thread, or wait for some other thread to complete. @@ -119,8 +143,8 @@ // U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { - std::unique_lock lock(initMutex()); - + std::call_once(*pInitFlag, umtx_init); + std::unique_lock lock(*initMutex); if (umtx_loadAcquire(uio.fState) == 0) { umtx_storeRelease(uio.fState, 1); return true; // Caller will next call the init function. @@ -128,7 +152,7 @@ while (umtx_loadAcquire(uio.fState) == 1) { // Another thread is currently running the initialization. // Wait until it completes. - initCondition().wait(lock); + initCondition->wait(lock); } U_ASSERT(uio.fState == 2); return false; @@ -145,10 +169,10 @@ U_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) { { - std::unique_lock lock(initMutex()); + std::unique_lock lock(*initMutex); umtx_storeRelease(uio.fState, 2); } - initCondition().notify_all(); + initCondition->notify_all(); } U_NAMESPACE_END diff -Nru icu-64.2/source/common/umutex.h icu-65.1/source/common/umutex.h --- icu-64.2/source/common/umutex.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/umutex.h 2019-10-03 11:16:41.000000000 +0000 @@ -23,6 +23,7 @@ #include #include #include +#include #include "unicode/utypes.h" #include "unicode/uclean.h" @@ -36,10 +37,11 @@ #error U_USER_ATOMICS and U_USER_MUTEX_H are not supported #endif - // Export an explicit template instantiation of std::atomic. // When building DLLs for Windows this is required as it is used as a data member of the exported SharedObject class. // See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples. +// +// Similar story for std::atomic, and the exported UMutex class. #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN && !defined(U_IN_DOXYGEN) #if defined(__clang__) || defined(_MSC_VER) #if defined(__clang__) @@ -48,12 +50,14 @@ #pragma clang diagnostic ignored "-Winstantiation-after-specialization" #endif template struct U_COMMON_API std::atomic; +template struct U_COMMON_API std::atomic; #if defined(__clang__) #pragma clang diagnostic pop #endif #elif defined(__GNUC__) // For GCC this class is already exported/visible, so no need for U_COMMON_API. template struct std::atomic; +template struct std::atomic; #endif #endif @@ -180,49 +184,78 @@ } } +// UMutex should be constexpr-constructible, so that no initialization code +// is run during startup. +// This works on all C++ libraries except MS VS before VS2019. +#if (defined(_CPPLIB_VER) && !defined(_MSVC_STL_VERSION)) || \ + (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142) + // (VS std lib older than VS2017) || (VS std lib version < VS2019) +# define UMUTEX_CONSTEXPR +#else +# define UMUTEX_CONSTEXPR constexpr +#endif -/************************************************************************************************* +/** + * UMutex - ICU Mutex class. * - * ICU Mutex wrappers. Originally wrapped operating system mutexes, giving the rest of ICU a - * platform independent set of mutex operations. Now vestigial, wrapping std::mutex only. - * For internal ICU use only. - * - *************************************************************************************************/ + * This is the preferred Mutex class for use within ICU implementation code. + * It is a thin wrapper over C++ std::mutex, with these additions: + * - Static instances are safe, not triggering static construction or destruction, + * and the associated order of construction or destruction issues. + * - Plumbed into u_cleanup() for destructing the underlying std::mutex, + * which frees any OS level resources they may be holding. + * + * Limitations: + * - Static or global instances only. Cannot be heap allocated. Cannot appear as a + * member of another class. + * - No condition variables or other advanced features. If needed, you will need to use + * std::mutex and std::condition_variable directly. For an example, see unifiedcache.cpp + * + * Typical Usage: + * static UMutex myMutex; + * + * { + * Mutex lock(myMutex); + * ... // Do stuff that is protected by myMutex; + * } // myMutex is released when lock goes out of scope. + */ -struct UMutex : public icu::UMemory { - UMutex() = default; +class U_COMMON_API UMutex { +public: + UMUTEX_CONSTEXPR UMutex() {} ~UMutex() = default; + UMutex(const UMutex &other) = delete; UMutex &operator =(const UMutex &other) = delete; + void *operator new(size_t) = delete; - std::mutex fMutex = {}; // Note: struct - pubic members - because most access is from - // // plain C style functions (umtx_lock(), etc.) -}; - - -struct UConditionVar : public icu::UMemory { - U_COMMON_API UConditionVar(); - U_COMMON_API ~UConditionVar(); - UConditionVar(const UConditionVar &other) = delete; - UConditionVar &operator =(const UConditionVar &other) = delete; - - std::condition_variable_any fCV; + // requirements for C++ BasicLockable, allows UMutex to work with std::lock_guard + void lock() { + std::mutex *m = fMutex.load(std::memory_order_acquire); + if (m == nullptr) { m = getMutex(); } + m->lock(); + } + void unlock() { fMutex.load(std::memory_order_relaxed)->unlock(); } + + static void cleanup(); + +private: + alignas(std::mutex) char fStorage[sizeof(std::mutex)] {}; + std::atomic fMutex { nullptr }; + + /** All initialized UMutexes are kept in a linked list, so that they can be found, + * and the underlying std::mutex destructed, by u_cleanup(). + */ + UMutex *fListLink { nullptr }; + static UMutex *gListHead; + + /** Out-of-line function to lazily initialize a UMutex on first use. + * Initial fast check is inline, in lock(). The returned value may never + * be nullptr. + */ + std::mutex *getMutex(); }; -#define U_MUTEX_INITIALIZER {} -#define U_CONDITION_INITIALIZER {} - -// Implementation notes for UConditionVar: -// -// Use an out-of-line constructor to reduce problems with the ICU dependency checker. -// On Linux, the default constructor of std::condition_variable_any -// produces an in-line reference to global operator new(), which the -// dependency checker flags for any file that declares a UConditionVar. With -// an out-of-line constructor, the dependency is constrained to umutex.o -// -// Do not export (U_COMMON_API) the entire class, but only the constructor -// and destructor, to avoid Windows build problems with attempting to export the -// std::condition_variable_any. /* Lock a mutex. * @param mutex The given mutex to be locked. Pass NULL to specify @@ -237,30 +270,6 @@ */ U_INTERNAL void U_EXPORT2 umtx_unlock (UMutex* mutex); -/* - * Wait on a condition variable. - * The calling thread will unlock the mutex and wait on the condition variable. - * The mutex must be locked by the calling thread when invoking this function. - * - * @param cond the condition variable to wait on. - * @param mutex the associated mutex. - */ - -U_INTERNAL void U_EXPORT2 umtx_condWait(UConditionVar *cond, UMutex *mutex); - - -/* - * Broadcast wakeup of all threads waiting on a Condition. - * - * @param cond the condition variable. - */ -U_INTERNAL void U_EXPORT2 umtx_condBroadcast(UConditionVar *cond); - -/* - * Signal a condition variable, waking up one waiting thread. - */ -U_INTERNAL void U_EXPORT2 umtx_condSignal(UConditionVar *cond); - U_NAMESPACE_END diff -Nru icu-64.2/source/common/unames.cpp icu-65.1/source/common/unames.cpp --- icu-64.2/source/common/unames.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unames.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -212,13 +212,13 @@ return U_SUCCESS(*pErrorCode); } -#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) { \ +#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) UPRV_BLOCK_MACRO_BEGIN { \ if((bufferLength)>0) { \ *(buffer)++=c; \ --(bufferLength); \ } \ ++(bufferPos); \ -} +} UPRV_BLOCK_MACRO_END #define U_ISO_COMMENT U_CHAR_NAME_CHOICE_COUNT diff -Nru icu-64.2/source/common/unicode/appendable.h icu-65.1/source/common/unicode/appendable.h --- icu-64.2/source/common/unicode/appendable.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/appendable.h 2019-10-03 11:16:41.000000000 +0000 @@ -23,6 +23,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" U_NAMESPACE_BEGIN @@ -231,4 +234,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __APPENDABLE_H__ diff -Nru icu-64.2/source/common/unicode/brkiter.h icu-65.1/source/common/unicode/brkiter.h --- icu-64.2/source/common/unicode/brkiter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/brkiter.h 2019-10-03 11:16:41.000000000 +0000 @@ -29,6 +29,10 @@ * \brief C++ API: Break Iterator. */ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #if UCONFIG_NO_BREAK_ITERATION U_NAMESPACE_BEGIN @@ -135,7 +139,7 @@ * method which subclasses implement. * @stable ICU 2.0 */ - virtual BreakIterator* clone(void) const = 0; + virtual BreakIterator* clone() const = 0; /** * Return a polymorphic class ID for this object. Different subclasses @@ -493,6 +497,7 @@ static UnicodeString& U_EXPORT2 getDisplayName(const Locale& objectLocale, UnicodeString& name); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Deprecated functionality. Use clone() instead. * @@ -515,6 +520,7 @@ virtual BreakIterator * createBufferClone(void *stackBuffer, int32_t &BufferSize, UErrorCode &status) = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API #ifndef U_HIDE_DEPRECATED_API @@ -658,5 +664,7 @@ #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // BRKITER_H //eof diff -Nru icu-64.2/source/common/unicode/bytestream.h icu-65.1/source/common/unicode/bytestream.h --- icu-64.2/source/common/unicode/bytestream.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/bytestream.h 2019-10-03 11:16:41.000000000 +0000 @@ -38,6 +38,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/std_string.h" @@ -267,4 +270,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __BYTESTREAM_H__ diff -Nru icu-64.2/source/common/unicode/bytestriebuilder.h icu-65.1/source/common/unicode/bytestriebuilder.h --- icu-64.2/source/common/unicode/bytestriebuilder.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/bytestriebuilder.h 2019-10-03 11:16:41.000000000 +0000 @@ -23,6 +23,9 @@ #define __BYTESTRIEBUILDER_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/bytestrie.h" #include "unicode/stringpiece.h" #include "unicode/stringtriebuilder.h" @@ -179,4 +182,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __BYTESTRIEBUILDER_H__ diff -Nru icu-64.2/source/common/unicode/bytestrie.h icu-65.1/source/common/unicode/bytestrie.h --- icu-64.2/source/common/unicode/bytestrie.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/bytestrie.h 2019-10-03 11:16:41.000000000 +0000 @@ -23,6 +23,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/stringpiece.h" #include "unicode/uobject.h" #include "unicode/ustringtrie.h" @@ -94,6 +97,41 @@ return *this; } +#ifndef U_HIDE_DRAFT_API + /** + * Returns the state of this trie as a 64-bit integer. + * The state value is never 0. + * + * @return opaque state value + * @see resetToState64 + * @draft ICU 65 + */ + uint64_t getState64() const { + return (static_cast(remainingMatchLength_ + 2) << kState64RemainingShift) | + (uint64_t)(pos_ - bytes_); + } + + /** + * Resets this trie to the saved state. + * Unlike resetToState(State), the 64-bit state value + * must be from getState64() from the same trie object or + * from one initialized the exact same way. + * Because of no validation, this method is faster. + * + * @param state The opaque trie state value from getState64(). + * @return *this + * @see getState64 + * @see resetToState + * @see reset + * @draft ICU 65 + */ + BytesTrie &resetToState64(uint64_t state) { + remainingMatchLength_ = static_cast(state >> kState64RemainingShift) - 2; + pos_ = bytes_ + (state & kState64PosMask); + return *this; + } +#endif /* U_HIDE_DRAFT_API */ + /** * BytesTrie state object, for saving a trie's current state * and resetting the trie back to this state later. @@ -502,6 +540,13 @@ static const int32_t kMaxTwoByteDelta=((kMinThreeByteDeltaLead-kMinTwoByteDeltaLead)<<8)-1; // 0x2fff static const int32_t kMaxThreeByteDelta=((kFourByteDeltaLead-kMinThreeByteDeltaLead)<<16)-1; // 0xdffff + // For getState64(): + // The remainingMatchLength_ is -1..14=(kMaxLinearMatchLength=0x10)-2 + // so we need at least 5 bits for that. + // We add 2 to store it as a positive value 1..16=kMaxLinearMatchLength. + static constexpr int32_t kState64RemainingShift = 59; + static constexpr uint64_t kState64PosMask = (UINT64_C(1) << kState64RemainingShift) - 1; + uint8_t *ownedArray_; // Fixed value referencing the BytesTrie bytes. @@ -517,4 +562,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __BYTESTRIE_H__ diff -Nru icu-64.2/source/common/unicode/caniter.h icu-65.1/source/common/unicode/caniter.h --- icu-64.2/source/common/unicode/caniter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/caniter.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_NORMALIZATION #include "unicode/uobject.h" @@ -207,4 +209,6 @@ #endif /* #if !UCONFIG_NO_NORMALIZATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/casemap.h icu-65.1/source/common/unicode/casemap.h --- icu-64.2/source/common/unicode/casemap.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/casemap.h 2019-10-03 11:16:41.000000000 +0000 @@ -8,6 +8,9 @@ #define __CASEMAP_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/stringpiece.h" #include "unicode/uobject.h" @@ -489,4 +492,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __CASEMAP_H__ diff -Nru icu-64.2/source/common/unicode/char16ptr.h icu-65.1/source/common/unicode/char16ptr.h --- icu-64.2/source/common/unicode/char16ptr.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/char16ptr.h 2019-10-03 11:16:41.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef __CHAR16PTR_H__ #define __CHAR16PTR_H__ -#include #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + +#include + /** * \file * \brief C++ API: char16_t pointer wrappers with @@ -305,4 +308,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __CHAR16PTR_H__ diff -Nru icu-64.2/source/common/unicode/chariter.h icu-65.1/source/common/unicode/chariter.h --- icu-64.2/source/common/unicode/chariter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/chariter.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,9 @@ #define CHARITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/unistr.h" /** @@ -377,7 +380,7 @@ * @return a pointer to a new CharacterIterator * @stable ICU 2.0 */ - virtual CharacterIterator* clone(void) const = 0; + virtual CharacterIterator* clone() const = 0; /** * Sets the iterator to refer to the first code unit in its @@ -725,4 +728,7 @@ } U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/dbbi.h icu-65.1/source/common/unicode/dbbi.h --- icu-64.2/source/common/unicode/dbbi.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/dbbi.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,10 @@ #ifndef DBBI_H #define DBBI_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/rbbi.h" #if !UCONFIG_NO_BREAK_ITERATION @@ -39,4 +43,6 @@ #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/docmain.h icu-65.1/source/common/unicode/docmain.h --- icu-64.2/source/common/unicode/docmain.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/docmain.h 2019-10-03 11:16:41.000000000 +0000 @@ -99,7 +99,7 @@ * * * Codepage Conversion - * ucnv.h, ucnvsel.hb + * ucnv.h, ucnvsel.h * C API * * @@ -115,7 +115,7 @@ * * Locales * uloc.h - * icu::Locale, icu::LocaleBuilder + * icu::Locale, icu::LocaleBuilder, icu::LocaleMatcher * * * Resource Bundles diff -Nru icu-64.2/source/common/unicode/dtintrv.h icu-65.1/source/common/unicode/dtintrv.h --- icu-64.2/source/common/unicode/dtintrv.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/dtintrv.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,9 @@ #define __DTINTRV_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -22,7 +25,6 @@ * \brief C++ API: Date Interval data type */ - U_NAMESPACE_BEGIN @@ -157,4 +159,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/edits.h icu-65.1/source/common/unicode/edits.h --- icu-64.2/source/common/unicode/edits.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/edits.h 2019-10-03 11:16:41.000000000 +0000 @@ -8,6 +8,9 @@ #define __EDITS_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -159,7 +162,7 @@ * @return TRUE if U_FAILURE(outErrorCode) * @stable ICU 59 */ - UBool copyErrorTo(UErrorCode &outErrorCode); + UBool copyErrorTo(UErrorCode &outErrorCode) const; /** * How much longer is the new text compared with the old text? @@ -523,4 +526,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __EDITS_H__ diff -Nru icu-64.2/source/common/unicode/errorcode.h icu-65.1/source/common/unicode/errorcode.h --- icu-64.2/source/common/unicode/errorcode.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/errorcode.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,6 +26,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" U_NAMESPACE_BEGIN @@ -136,4 +139,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __ERRORCODE_H__ diff -Nru icu-64.2/source/common/unicode/filteredbrk.h icu-65.1/source/common/unicode/filteredbrk.h --- icu-64.2/source/common/unicode/filteredbrk.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/filteredbrk.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,9 @@ #define FILTEREDBRK_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/brkiter.h" #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILTERED_BREAK_ITERATION @@ -101,6 +104,7 @@ */ virtual UBool unsuppressBreakAfter(const UnicodeString& string, UErrorCode& status) = 0; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * This function has been deprecated in favor of wrapIteratorWithFilter() * The behavior is identical. @@ -111,6 +115,7 @@ * @see wrapBreakIteratorWithFilter() */ virtual BreakIterator *build(BreakIterator* adoptBreakIterator, UErrorCode& status) = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Wrap (adopt) an existing break iterator in a new filtered instance. @@ -142,4 +147,6 @@ #endif // #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILTERED_BREAK_ITERATION +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // #ifndef FILTEREDBRK_H diff -Nru icu-64.2/source/common/unicode/idna.h icu-65.1/source/common/unicode/idna.h --- icu-64.2/source/common/unicode/idna.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/idna.h 2019-10-03 11:16:41.000000000 +0000 @@ -24,6 +24,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_IDNA #include "unicode/bytestream.h" @@ -322,4 +324,7 @@ U_NAMESPACE_END #endif // UCONFIG_NO_IDNA + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __IDNA_H__ diff -Nru icu-64.2/source/common/unicode/localebuilder.h icu-65.1/source/common/unicode/localebuilder.h --- icu-64.2/source/common/unicode/localebuilder.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/localebuilder.h 2019-10-03 11:16:41.000000000 +0000 @@ -3,11 +3,14 @@ #ifndef __LOCALEBUILDER_H__ #define __LOCALEBUILDER_H__ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/locid.h" +#include "unicode/localematcher.h" #include "unicode/stringpiece.h" #include "unicode/uobject.h" -#include "unicode/utypes.h" - #ifndef U_HIDE_DRAFT_API /** @@ -276,7 +279,24 @@ */ Locale build(UErrorCode& status); +#ifndef U_HIDE_DRAFT_API + /** + * Sets the UErrorCode if an error occurred while recording sets. + * Preserves older error codes in the outErrorCode. + * @param outErrorCode Set to an error code that occurred while setting subtags. + * Unchanged if there is no such error or if outErrorCode + * already contained an error. + * @return TRUE if U_FAILURE(outErrorCode) + * @draft ICU 65 + */ + UBool copyErrorTo(UErrorCode &outErrorCode) const; +#endif /* U_HIDE_DRAFT_API */ + private: + friend class LocaleMatcher::Result; + + void copyExtensionsFrom(const Locale& src, UErrorCode& errorCode); + UErrorCode status_; char language_[9]; char script_[5]; @@ -289,4 +309,7 @@ U_NAMESPACE_END #endif // U_HIDE_DRAFT_API + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __LOCALEBUILDER_H__ diff -Nru icu-64.2/source/common/unicode/localematcher.h icu-65.1/source/common/unicode/localematcher.h --- icu-64.2/source/common/unicode/localematcher.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/common/unicode/localematcher.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,605 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localematcher.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCALEMATCHER_H__ +#define __LOCALEMATCHER_H__ + +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" + +/** + * \file + * \brief C++ API: Locale matcher: User's desired locales vs. application's supported locales. + */ + +#ifndef U_HIDE_DRAFT_API + +/** + * Builder option for whether the language subtag or the script subtag is most important. + * + * @see Builder#setFavorSubtag(FavorSubtag) + * @draft ICU 65 + */ +enum ULocMatchFavorSubtag { + /** + * Language differences are most important, then script differences, then region differences. + * (This is the default behavior.) + * + * @draft ICU 65 + */ + ULOCMATCH_FAVOR_LANGUAGE, + /** + * Makes script differences matter relatively more than language differences. + * + * @draft ICU 65 + */ + ULOCMATCH_FAVOR_SCRIPT +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchFavorSubtag ULocMatchFavorSubtag; +#endif + +/** + * Builder option for whether all desired locales are treated equally or + * earlier ones are preferred. + * + * @see Builder#setDemotionPerDesiredLocale(Demotion) + * @draft ICU 65 + */ +enum ULocMatchDemotion { + /** + * All desired locales are treated equally. + * + * @draft ICU 65 + */ + ULOCMATCH_DEMOTION_NONE, + /** + * Earlier desired locales are preferred. + * + *

    From each desired locale to the next, + * the distance to any supported locale is increased by an additional amount + * which is at least as large as most region mismatches. + * A later desired locale has to have a better match with some supported locale + * due to more than merely having the same region subtag. + * + *

    For example: Supported={en, sv} desired=[en-GB, sv] + * yields Result(en-GB, en) because + * with the demotion of sv its perfect match is no better than + * the region distance between the earlier desired locale en-GB and en=en-US. + * + *

    Notes: + *

      + *
    • In some cases, language and/or script differences can be as small as + * the typical region difference. (Example: sr-Latn vs. sr-Cyrl) + *
    • It is possible for certain region differences to be larger than usual, + * and larger than the demotion. + * (As of CLDR 35 there is no such case, but + * this is possible in future versions of the data.) + *
    + * + * @draft ICU 65 + */ + ULOCMATCH_DEMOTION_REGION +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchDemotion ULocMatchDemotion; +#endif + +struct UHashtable; + +U_NAMESPACE_BEGIN + +struct LSR; + +class LocaleDistance; +class LocaleLsrIterator; +class UVector; +class XLikelySubtags; + +/** + * Immutable class that picks the best match between a user's desired locales and + * an application's supported locales. + * Movable but not copyable. + * + *

    Example: + *

    + * UErrorCode errorCode = U_ZERO_ERROR;
    + * LocaleMatcher matcher = LocaleMatcher::Builder().setSupportedLocales("fr, en-GB, en").build(errorCode);
    + * Locale *bestSupported = matcher.getBestLocale(Locale.US, errorCode);  // "en"
    + * 
    + * + *

    A matcher takes into account when languages are close to one another, + * such as Danish and Norwegian, + * and when regional variants are close, like en-GB and en-AU as opposed to en-US. + * + *

    If there are multiple supported locales with the same (language, script, region) + * likely subtags, then the current implementation returns the first of those locales. + * It ignores variant subtags (except for pseudolocale variants) and extensions. + * This may change in future versions. + * + *

    For example, the current implementation does not distinguish between + * de, de-DE, de-Latn, de-1901, de-u-co-phonebk. + * + *

    If you prefer one equivalent locale over another, then provide only the preferred one, + * or place it earlier in the list of supported locales. + * + *

    Otherwise, the order of supported locales may have no effect on the best-match results. + * The current implementation compares each desired locale with supported locales + * in the following order: + * 1. Default locale, if supported; + * 2. CLDR "paradigm locales" like en-GB and es-419; + * 3. other supported locales. + * This may change in future versions. + * + *

    Often a product will just need one matcher instance, built with the languages + * that it supports. However, it may want multiple instances with different + * default languages based on additional information, such as the domain. + * + *

    This class is not intended for public subclassing. + * + * @draft ICU 65 + */ +class U_COMMON_API LocaleMatcher : public UMemory { +public: + /** + * Data for the best-matching pair of a desired and a supported locale. + * Movable but not copyable. + * + * @draft ICU 65 + */ + class U_COMMON_API Result : public UMemory { + public: + /** + * Move constructor; might modify the source. + * This object will have the same contents that the source object had. + * + * @param src Result to move contents from. + * @draft ICU 65 + */ + Result(Result &&src) U_NOEXCEPT; + + /** + * Destructor. + * + * @draft ICU 65 + */ + ~Result(); + + /** + * Move assignment; might modify the source. + * This object will have the same contents that the source object had. + * + * @param src Result to move contents from. + * @draft ICU 65 + */ + Result &operator=(Result &&src) U_NOEXCEPT; + + /** + * Returns the best-matching desired locale. + * nullptr if the list of desired locales is empty or if none matched well enough. + * + * @return the best-matching desired locale, or nullptr. + * @draft ICU 65 + */ + inline const Locale *getDesiredLocale() const { return desiredLocale; } + + /** + * Returns the best-matching supported locale. + * If none matched well enough, this is the default locale. + * The default locale is nullptr if the list of supported locales is empty and + * no explicit default locale is set. + * + * @return the best-matching supported locale, or nullptr. + * @draft ICU 65 + */ + inline const Locale *getSupportedLocale() const { return supportedLocale; } + + /** + * Returns the index of the best-matching desired locale in the input Iterable order. + * -1 if the list of desired locales is empty or if none matched well enough. + * + * @return the index of the best-matching desired locale, or -1. + * @draft ICU 65 + */ + inline int32_t getDesiredIndex() const { return desiredIndex; } + + /** + * Returns the index of the best-matching supported locale in the + * constructor’s or builder’s input order (“set” Collection plus “added” locales). + * If the matcher was built from a locale list string, then the iteration order is that + * of a LocalePriorityList built from the same string. + * -1 if the list of supported locales is empty or if none matched well enough. + * + * @return the index of the best-matching supported locale, or -1. + * @draft ICU 65 + */ + inline int32_t getSupportedIndex() const { return supportedIndex; } + + /** + * Takes the best-matching supported locale and adds relevant fields of the + * best-matching desired locale, such as the -t- and -u- extensions. + * May replace some fields of the supported locale. + * The result is the locale that should be used for date and number formatting, collation, etc. + * Returns the root locale if getSupportedLocale() returns nullptr. + * + *

    Example: desired=ar-SA-u-nu-latn, supported=ar-EG, resolved locale=ar-SA-u-nu-latn + * + * @return a locale combining the best-matching desired and supported locales. + * @draft ICU 65 + */ + Locale makeResolvedLocale(UErrorCode &errorCode) const; + + private: + Result(const Locale *desired, const Locale *supported, + int32_t desIndex, int32_t suppIndex, UBool owned) : + desiredLocale(desired), supportedLocale(supported), + desiredIndex(desIndex), supportedIndex(suppIndex), + desiredIsOwned(owned) {} + + Result(const Result &other) = delete; + Result &operator=(const Result &other) = delete; + + const Locale *desiredLocale; + const Locale *supportedLocale; + int32_t desiredIndex; + int32_t supportedIndex; + UBool desiredIsOwned; + + friend class LocaleMatcher; + }; + + /** + * LocaleMatcher builder. + * Movable but not copyable. + * + * @see LocaleMatcher#builder() + * @draft ICU 65 + */ + class U_COMMON_API Builder : public UMemory { + public: + /** + * Constructs a builder used in chaining parameters for building a LocaleMatcher. + * + * @return a new Builder object + * @draft ICU 65 + */ + Builder() {} + + /** + * Move constructor; might modify the source. + * This builder will have the same contents that the source builder had. + * + * @param src Builder to move contents from. + * @draft ICU 65 + */ + Builder(Builder &&src) U_NOEXCEPT; + + /** + * Destructor. + * + * @draft ICU 65 + */ + ~Builder(); + + /** + * Move assignment; might modify the source. + * This builder will have the same contents that the source builder had. + * + * @param src Builder to move contents from. + * @draft ICU 65 + */ + Builder &operator=(Builder &&src) U_NOEXCEPT; + + /** + * Parses an Accept-Language string + * (RFC 2616 Section 14.4), + * such as "af, en, fr;q=0.9", and sets the supported locales accordingly. + * Allows whitespace in more places but does not allow "*". + * Clears any previously set/added supported locales first. + * + * @param locales the Accept-Language string of locales to set + * @return this Builder object + * @draft ICU 65 + */ + Builder &setSupportedLocalesFromListString(StringPiece locales); + + /** + * Copies the supported locales, preserving iteration order. + * Clears any previously set/added supported locales first. + * Duplicates are allowed, and are not removed. + * + * @param locales the list of locale + * @return this Builder object + * @draft ICU 65 + */ + Builder &setSupportedLocales(Locale::Iterator &locales); + + /** + * Copies the supported locales from the begin/end range, preserving iteration order. + * Clears any previously set/added supported locales first. + * Duplicates are allowed, and are not removed. + * + * Each of the iterator parameter values must be an + * input iterator whose value is convertible to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @return this Builder object + * @draft ICU 65 + */ + template + Builder &setSupportedLocales(Iter begin, Iter end) { + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + while (begin != end) { + addSupportedLocale(*begin++); + } + return *this; + } + + /** + * Copies the supported locales from the begin/end range, preserving iteration order. + * Calls the converter to convert each *begin to a Locale or const Locale &. + * Clears any previously set/added supported locales first. + * Duplicates are allowed, and are not removed. + * + * Each of the iterator parameter values must be an + * input iterator whose value is convertible to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @param converter Converter from *begin to const Locale & or compatible. + * @return this Builder object + * @draft ICU 65 + */ + template + Builder &setSupportedLocalesViaConverter(Iter begin, Iter end, Conv converter) { + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + while (begin != end) { + addSupportedLocale(converter(*begin++)); + } + return *this; + } + + /** + * Adds another supported locale. + * Duplicates are allowed, and are not removed. + * + * @param locale another locale + * @return this Builder object + * @draft ICU 65 + */ + Builder &addSupportedLocale(const Locale &locale); + + /** + * Sets the default locale; if nullptr, or if it is not set explicitly, + * then the first supported locale is used as the default locale. + * + * @param defaultLocale the default locale (will be copied) + * @return this Builder object + * @draft ICU 65 + */ + Builder &setDefaultLocale(const Locale *defaultLocale); + + /** + * If ULOCMATCH_FAVOR_SCRIPT, then the language differences are smaller than script + * differences. + * This is used in situations (such as maps) where + * it is better to fall back to the same script than a similar language. + * + * @param subtag the subtag to favor + * @return this Builder object + * @draft ICU 65 + */ + Builder &setFavorSubtag(ULocMatchFavorSubtag subtag); + + /** + * Option for whether all desired locales are treated equally or + * earlier ones are preferred (this is the default). + * + * @param demotion the demotion per desired locale to set. + * @return this Builder object + * @draft ICU 65 + */ + Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion); + + /** + * Sets the UErrorCode if an error occurred while setting parameters. + * Preserves older error codes in the outErrorCode. + * + * @param outErrorCode Set to an error code if it does not contain one already + * and an error occurred while setting parameters. + * Otherwise unchanged. + * @return TRUE if U_FAILURE(outErrorCode) + * @draft ICU 65 + */ + UBool copyErrorTo(UErrorCode &outErrorCode) const; + + /** + * Builds and returns a new locale matcher. + * This builder can continue to be used. + * + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return new LocaleMatcher. + * @draft ICU 65 + */ + LocaleMatcher build(UErrorCode &errorCode) const; + + private: + friend class LocaleMatcher; + + Builder(const Builder &other) = delete; + Builder &operator=(const Builder &other) = delete; + + void clearSupportedLocales(); + bool ensureSupportedLocaleVector(); + + UErrorCode errorCode_ = U_ZERO_ERROR; + UVector *supportedLocales_ = nullptr; + int32_t thresholdDistance_ = -1; + ULocMatchDemotion demotion_ = ULOCMATCH_DEMOTION_REGION; + Locale *defaultLocale_ = nullptr; + ULocMatchFavorSubtag favor_ = ULOCMATCH_FAVOR_LANGUAGE; + }; + + // FYI No public LocaleMatcher constructors in C++; use the Builder. + + /** + * Move copy constructor; might modify the source. + * This matcher will have the same settings that the source matcher had. + * @param src source matcher + * @draft ICU 65 + */ + LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT; + + /** + * Destructor. + * @draft ICU 65 + */ + ~LocaleMatcher(); + + /** + * Move assignment operator; might modify the source. + * This matcher will have the same settings that the source matcher had. + * The behavior is undefined if *this and src are the same object. + * @param src source matcher + * @return *this + * @draft ICU 65 + */ + LocaleMatcher &operator=(LocaleMatcher &&src) U_NOEXCEPT; + + /** + * Returns the supported locale which best matches the desired locale. + * + * @param desiredLocale Typically a user's language. + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return the best-matching supported locale. + * @draft ICU 65 + */ + const Locale *getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const; + + /** + * Returns the supported locale which best matches one of the desired locales. + * + * @param desiredLocales Typically a user's languages, in order of preference (descending). + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return the best-matching supported locale. + * @draft ICU 65 + */ + const Locale *getBestMatch(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const; + + /** + * Parses an Accept-Language string + * (RFC 2616 Section 14.4), + * such as "af, en, fr;q=0.9", + * and returns the supported locale which best matches one of the desired locales. + * Allows whitespace in more places but does not allow "*". + * + * @param desiredLocaleList Typically a user's languages, as an Accept-Language string. + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return the best-matching supported locale. + * @draft ICU 65 + */ + const Locale *getBestMatchForListString(StringPiece desiredLocaleList, UErrorCode &errorCode) const; + + /** + * Returns the best match between the desired locale and the supported locales. + * If the result's desired locale is not nullptr, then it is the address of the input locale. + * It has not been cloned. + * + * @param desiredLocale Typically a user's language. + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return the best-matching pair of the desired and a supported locale. + * @draft ICU 65 + */ + Result getBestMatchResult(const Locale &desiredLocale, UErrorCode &errorCode) const; + + /** + * Returns the best match between the desired and supported locales. + * If the result's desired locale is not nullptr, then it is a clone of + * the best-matching desired locale. The Result object owns the clone. + * + * @param desiredLocales Typically a user's languages, in order of preference (descending). + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return the best-matching pair of a desired and a supported locale. + * @draft ICU 65 + */ + Result getBestMatchResult(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const; + +#ifndef U_HIDE_INTERNAL_API + /** + * Returns a fraction between 0 and 1, where 1 means that the languages are a + * perfect match, and 0 means that they are completely different. + * + *

    This is mostly an implementation detail, and the precise values may change over time. + * The implementation may use either the maximized forms or the others ones, or both. + * The implementation may or may not rely on the forms to be consistent with each other. + * + *

    Callers should construct and use a matcher rather than match pairs of locales directly. + * + * @param desired Desired locale. + * @param supported Supported locale. + * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test, + * or else the function returns immediately. Check for U_FAILURE() + * on output or use with function chaining. (See User Guide for details.) + * @return value between 0 and 1, inclusive. + * @internal (has a known user) + */ + double internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const; +#endif // U_HIDE_INTERNAL_API + +private: + LocaleMatcher(const Builder &builder, UErrorCode &errorCode); + LocaleMatcher(const LocaleMatcher &other) = delete; + LocaleMatcher &operator=(const LocaleMatcher &other) = delete; + + int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; + + const XLikelySubtags &likelySubtags; + const LocaleDistance &localeDistance; + int32_t thresholdDistance; + int32_t demotionPerDesiredLocale; + ULocMatchFavorSubtag favorSubtag; + + // These are in input order. + const Locale ** supportedLocales; + LSR *lsrs; + int32_t supportedLocalesLength; + // These are in preference order: 1. Default locale 2. paradigm locales 3. others. + UHashtable *supportedLsrToIndex; // Map stores index+1 because 0 is "not found" + // Array versions of the supportedLsrToIndex keys and values. + // The distance lookup loops over the supportedLSRs and returns the index of the best match. + const LSR **supportedLSRs; + int32_t *supportedIndexes; + int32_t supportedLSRsLength; + Locale *ownedDefaultLocale; + const Locale *defaultLocale; + int32_t defaultLocaleIndex; +}; + +U_NAMESPACE_END + +#endif // U_HIDE_DRAFT_API +#endif // U_SHOW_CPLUSPLUS_API +#endif // __LOCALEMATCHER_H__ diff -Nru icu-64.2/source/common/unicode/locdspnm.h icu-65.1/source/common/unicode/locdspnm.h --- icu-64.2/source/common/unicode/locdspnm.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/locdspnm.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Provides display names of Locale and its components. @@ -204,4 +206,6 @@ #endif +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/locid.h icu-65.1/source/common/unicode/locid.h --- icu-64.2/source/common/unicode/locid.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/locid.h 2019-10-03 11:16:41.000000000 +0000 @@ -31,11 +31,14 @@ #ifndef LOCID_H #define LOCID_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/bytestream.h" #include "unicode/localpointer.h" #include "unicode/strenum.h" #include "unicode/stringpiece.h" -#include "unicode/utypes.h" #include "unicode/uobject.h" #include "unicode/putil.h" #include "unicode/uloc.h" @@ -284,16 +287,14 @@ */ Locale(const Locale& other); -#ifndef U_HIDE_DRAFT_API /** * Move constructor; might leave source in bogus state. * This locale will have the same contents that the source locale had. * * @param other The Locale object being moved in. - * @draft ICU 63 + * @stable ICU 63 */ Locale(Locale&& other) U_NOEXCEPT; -#endif // U_HIDE_DRAFT_API /** * Destructor @@ -310,7 +311,6 @@ */ Locale& operator=(const Locale& other); -#ifndef U_HIDE_DRAFT_API /** * Move assignment operator; might leave source in bogus state. * This locale will have the same contents that the source locale had. @@ -318,10 +318,9 @@ * * @param other The Locale object being moved in. * @return *this - * @draft ICU 63 + * @stable ICU 63 */ Locale& operator=(Locale&& other) U_NOEXCEPT; -#endif // U_HIDE_DRAFT_API /** * Checks if two locale keys are the same. @@ -389,7 +388,6 @@ UErrorCode& success); #endif /* U_HIDE_SYSTEM_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns a Locale for the specified BCP47 language tag string. * If the specified language tag contains any ill-formed subtags, @@ -405,7 +403,7 @@ * @param tag the input BCP47 language tag. * @param status error information if creating the Locale failed. * @return the Locale for the specified BCP47 language tag. - * @draft ICU 63 + * @stable ICU 63 */ static Locale U_EXPORT2 forLanguageTag(StringPiece tag, UErrorCode& status); @@ -420,7 +418,7 @@ * @param sink the output sink receiving the BCP47 language * tag for this Locale. * @param status error information if creating the language tag failed. - * @draft ICU 63 + * @stable ICU 63 */ void toLanguageTag(ByteSink& sink, UErrorCode& status) const; @@ -432,11 +430,10 @@ * * @param status error information if creating the language tag failed. * @return the BCP47 language tag for this Locale. - * @draft ICU 63 + * @stable ICU 63 */ template inline StringClass toLanguageTag(UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API /** * Creates a locale which has had minimal canonicalization @@ -508,7 +505,6 @@ */ const char * getBaseName() const; -#ifndef U_HIDE_DRAFT_API /** * Add the likely subtags for this Locale, per the algorithm described * in the following CLDR technical report: @@ -536,7 +532,7 @@ * @param status error information if maximizing this Locale failed. * If this Locale is not well-formed, the error code is * U_ILLEGAL_ARGUMENT_ERROR. - * @draft ICU 63 + * @stable ICU 63 */ void addLikelySubtags(UErrorCode& status); @@ -567,10 +563,9 @@ * @param status error information if maximizing this Locale failed. * If this Locale is not well-formed, the error code is * U_ILLEGAL_ARGUMENT_ERROR. - * @draft ICU 63 + * @stable ICU 63 */ void minimizeSubtags(UErrorCode& status); -#endif // U_HIDE_DRAFT_API /** * Gets the list of keywords for the specified locale. @@ -583,8 +578,6 @@ */ StringEnumeration * createKeywords(UErrorCode &status) const; -#ifndef U_HIDE_DRAFT_API - /** * Gets the list of Unicode keywords for the specified locale. * @@ -592,7 +585,7 @@ * @return pointer to StringEnumeration class, or NULL if there are no keywords. * Client must dispose of it by calling delete. * @see getUnicodeKeywords - * @draft ICU 63 + * @stable ICU 63 */ StringEnumeration * createUnicodeKeywords(UErrorCode &status) const; @@ -605,7 +598,7 @@ * * @param iterator an STL style output iterator to write the keywords to. * @param status error information if creating set of keywords failed. - * @draft ICU 63 + * @stable ICU 63 */ template inline void getKeywords(OutputIterator iterator, UErrorCode& status) const; @@ -619,13 +612,11 @@ * * @param iterator an STL style output iterator to write the keywords to. * @param status error information if creating set of keywords failed. - * @draft ICU 63 + * @stable ICU 63 */ template inline void getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API - /** * Gets the value for a keyword. * @@ -644,7 +635,6 @@ */ int32_t getKeywordValue(const char* keywordName, char *buffer, int32_t bufferCapacity, UErrorCode &status) const; -#ifndef U_HIDE_DRAFT_API /** * Gets the value for a keyword. * @@ -656,7 +646,7 @@ * @param keywordName name of the keyword for which we want the value. * @param sink the sink to receive the keyword value. * @param status error information if getting the value failed. - * @draft ICU 63 + * @stable ICU 63 */ void getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const; @@ -671,7 +661,7 @@ * @param keywordName name of the keyword for which we want the value. * @param status error information if getting the value failed. * @return the keyword value. - * @draft ICU 63 + * @stable ICU 63 */ template inline StringClass getKeywordValue(StringPiece keywordName, UErrorCode& status) const; @@ -687,7 +677,7 @@ * @param keywordName name of the keyword for which we want the value. * @param sink the sink to receive the keyword value. * @param status error information if getting the value failed. - * @draft ICU 63 + * @stable ICU 63 */ void getUnicodeKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const; @@ -702,11 +692,10 @@ * @param keywordName name of the keyword for which we want the value. * @param status error information if getting the value failed. * @return the keyword value. - * @draft ICU 63 + * @stable ICU 63 */ template inline StringClass getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API /** * Sets or removes the value for a keyword. @@ -729,7 +718,6 @@ */ void setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Sets or removes the value for a keyword. * @@ -746,7 +734,7 @@ * NULL, will result in the keyword being removed. No error is given if * that keyword does not exist. * @param status Returns any error information while performing this operation. - * @draft ICU 63 + * @stable ICU 63 */ void setKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status); @@ -766,10 +754,9 @@ * NULL, will result in the keyword being removed. No error is given if * that keyword does not exist. * @param status Returns any error information while performing this operation. - * @draft ICU 63 + * @stable ICU 63 */ void setUnicodeKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status); -#endif // U_HIDE_DRAFT_API /** * returns the locale's three-letter language code, as specified @@ -1008,6 +995,104 @@ */ virtual UClassID getDynamicClassID() const; +#ifndef U_HIDE_DRAFT_API + /** + * A Locale iterator interface similar to a Java Iterator. + * @draft ICU 65 + */ + class U_COMMON_API Iterator /* not : public UObject because this is an interface/mixin class */ { + public: + /** @draft ICU 65 */ + virtual ~Iterator(); + + /** + * @return TRUE if next() can be called again. + * @draft ICU 65 + */ + virtual UBool hasNext() const = 0; + + /** + * @return the next locale. + * @draft ICU 65 + */ + virtual const Locale &next() = 0; + }; + + /** + * A generic Locale iterator implementation over Locale input iterators. + * @draft ICU 65 + */ + template + class RangeIterator : public Iterator, public UMemory { + public: + /** + * Constructs an iterator from a begin/end range. + * Each of the iterator parameter values must be an + * input iterator whose value is convertible to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @draft ICU 65 + */ + RangeIterator(Iter begin, Iter end) : it_(begin), end_(end) {} + + /** + * @return TRUE if next() can be called again. + * @draft ICU 65 + */ + UBool hasNext() const override { return it_ != end_; } + + /** + * @return the next locale. + * @draft ICU 65 + */ + const Locale &next() override { return *it_++; } + + private: + Iter it_; + const Iter end_; + }; + + /** + * A generic Locale iterator implementation over Locale input iterators. + * Calls the converter to convert each *begin to a const Locale &. + * @draft ICU 65 + */ + template + class ConvertingIterator : public Iterator, public UMemory { + public: + /** + * Constructs an iterator from a begin/end range. + * Each of the iterator parameter values must be an + * input iterator whose value the converter converts to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @param converter Converter from *begin to const Locale & or compatible. + * @draft ICU 65 + */ + ConvertingIterator(Iter begin, Iter end, Conv converter) : + it_(begin), end_(end), converter_(converter) {} + + /** + * @return TRUE if next() can be called again. + * @draft ICU 65 + */ + UBool hasNext() const override { return it_ != end_; } + + /** + * @return the next locale. + * @draft ICU 65 + */ + const Locale &next() override { return converter_(*it_++); } + + private: + Iter it_; + const Iter end_; + Conv converter_; + }; +#endif // U_HIDE_DRAFT_API + protected: /* only protected for testing purposes. DO NOT USE. */ #ifndef U_HIDE_INTERNAL_API /** @@ -1074,7 +1159,6 @@ return !operator==(other); } -#ifndef U_HIDE_DRAFT_API template inline StringClass Locale::toLanguageTag(UErrorCode& status) const { @@ -1083,7 +1167,6 @@ toLanguageTag(sink, status); return result; } -#endif // U_HIDE_DRAFT_API inline const char * Locale::getCountry() const @@ -1115,13 +1198,11 @@ return fullName; } -#ifndef U_HIDE_DRAFT_API - template inline void Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const { LocalPointer keys(createKeywords(status)); - if (U_FAILURE(status)) { + if (U_FAILURE(status) || keys.isNull()) { return; } for (;;) { @@ -1138,7 +1219,7 @@ Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const { LocalPointer keys(createUnicodeKeywords(status)); - if (U_FAILURE(status)) { + if (U_FAILURE(status) || keys.isNull()) { return; } for (;;) { @@ -1169,8 +1250,6 @@ return result; } -#endif // U_HIDE_DRAFT_API - inline UBool Locale::isBogus(void) const { return fIsBogus; @@ -1178,4 +1257,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/messagepattern.h icu-65.1/source/common/unicode/messagepattern.h --- icu-64.2/source/common/unicode/messagepattern.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/messagepattern.h 2019-10-03 11:16:41.000000000 +0000 @@ -24,6 +24,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/parseerr.h" @@ -942,4 +944,6 @@ #endif // !UCONFIG_NO_FORMATTING +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __MESSAGEPATTERN_H__ diff -Nru icu-64.2/source/common/unicode/normalizer2.h icu-65.1/source/common/unicode/normalizer2.h --- icu-64.2/source/common/unicode/normalizer2.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/normalizer2.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,6 +26,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_NORMALIZATION #include "unicode/stringpiece.h" @@ -771,4 +773,7 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_NORMALIZATION + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __NORMALIZER2_H__ diff -Nru icu-64.2/source/common/unicode/normlzr.h icu-65.1/source/common/unicode/normlzr.h --- icu-64.2/source/common/unicode/normlzr.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/normlzr.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Unicode Normalization @@ -183,6 +185,7 @@ Normalizer(const CharacterIterator& iter, UNormalizationMode mode); #endif /* U_HIDE_DEPRECATED_API */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Copy constructor. * @param copy The object to be copied. @@ -195,7 +198,7 @@ * @deprecated ICU 56 Use Normalizer2 instead. */ virtual ~Normalizer(); - +#endif // U_FORCE_HIDE_DEPRECATED_API //------------------------------------------------------------------------- // Static utility methods @@ -599,7 +602,7 @@ * @return a pointer to a new Normalizer * @deprecated ICU 56 Use Normalizer2 instead. */ - Normalizer* clone(void) const; + Normalizer* clone() const; /** * Generates a hash code for this iterator. @@ -723,12 +726,14 @@ static UClassID U_EXPORT2 getStaticClassID(); #endif /* U_HIDE_DEPRECATED_API */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * ICU "poor man's RTTI", returns a UClassID for the actual class. * @return a UClassID for the actual class. * @deprecated ICU 56 Use Normalizer2 instead. */ virtual UClassID getDynamicClassID() const; +#endif // U_FORCE_HIDE_DEPRECATED_API private: //------------------------------------------------------------------------- @@ -807,3 +812,5 @@ #endif /* #if !UCONFIG_NO_NORMALIZATION */ #endif // NORMLZR_H + +#endif /* U_SHOW_CPLUSPLUS_API */ diff -Nru icu-64.2/source/common/unicode/parsepos.h icu-65.1/source/common/unicode/parsepos.h --- icu-64.2/source/common/unicode/parsepos.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/parsepos.h 2019-10-03 11:16:41.000000000 +0000 @@ -19,6 +19,9 @@ #define PARSEPOS_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" @@ -229,4 +232,6 @@ } U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/platform.h icu-65.1/source/common/unicode/platform.h --- icu-64.2/source/common/unicode/platform.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/platform.h 2019-10-03 11:16:41.000000000 +0000 @@ -135,6 +135,14 @@ /** Fuchsia is a POSIX-ish platform. @internal */ #define U_PF_FUCHSIA 4100 /* Maximum value for Linux-based platform is 4499 */ +/** + * Emscripten is a C++ transpiler for the Web that can target asm.js or + * WebAssembly. It provides some POSIX-compatible wrappers and stubs and + * some Linux-like functionality, but is not fully compatible with + * either. + * @internal + */ +#define U_PF_EMSCRIPTEN 5010 /** z/OS is the successor to OS/390 which was the successor to MVS. @internal */ #define U_PF_OS390 9000 /** "IBM i" is the current name of what used to be i5/OS and earlier OS/400. @internal */ @@ -192,6 +200,8 @@ # define U_PLATFORM U_PF_OS390 #elif defined(__OS400__) || defined(__TOS_OS400__) # define U_PLATFORM U_PF_OS400 +#elif defined(__EMSCRIPTEN__) +# define U_PLATFORM U_PF_EMSCRIPTEN #else # define U_PLATFORM U_PF_UNKNOWN #endif @@ -414,26 +424,40 @@ #endif /* Compatibility with compilers other than clang: http://clang.llvm.org/docs/LanguageExtensions.html */ -#ifndef __has_attribute -# define __has_attribute(x) 0 +#ifdef __has_attribute +# define UPRV_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define UPRV_HAS_ATTRIBUTE(x) 0 #endif -#ifndef __has_cpp_attribute -# define __has_cpp_attribute(x) 0 +#ifdef __has_cpp_attribute +# define UPRV_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define UPRV_HAS_CPP_ATTRIBUTE(x) 0 #endif -#ifndef __has_declspec_attribute -# define __has_declspec_attribute(x) 0 +#ifdef __has_declspec_attribute +# define UPRV_HAS_DECLSPEC_ATTRIBUTE(x) __has_declspec_attribute(x) +#else +# define UPRV_HAS_DECLSPEC_ATTRIBUTE(x) 0 #endif -#ifndef __has_builtin -# define __has_builtin(x) 0 +#ifdef __has_builtin +# define UPRV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define UPRV_HAS_BUILTIN(x) 0 #endif -#ifndef __has_feature -# define __has_feature(x) 0 +#ifdef __has_feature +# define UPRV_HAS_FEATURE(x) __has_feature(x) +#else +# define UPRV_HAS_FEATURE(x) 0 #endif -#ifndef __has_extension -# define __has_extension(x) 0 +#ifdef __has_extension +# define UPRV_HAS_EXTENSION(x) __has_extension(x) +#else +# define UPRV_HAS_EXTENSION(x) 0 #endif -#ifndef __has_warning -# define __has_warning(x) 0 +#ifdef __has_warning +# define UPRV_HAS_WARNING(x) __has_warning(x) +#else +# define UPRV_HAS_WARNING(x) 0 #endif /** @@ -452,7 +476,9 @@ * Attribute to specify the size of the allocated buffer for malloc-like functions * @internal */ -#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || __has_attribute(alloc_size) +#if (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \ + UPRV_HAS_ATTRIBUTE(alloc_size) # define U_ALLOC_SIZE_ATTR(X) __attribute__ ((alloc_size(X))) # define U_ALLOC_SIZE_ATTR2(X,Y) __attribute__ ((alloc_size(X,Y))) #else @@ -516,8 +542,9 @@ #elif defined(__clang__) // Test for compiler vs. feature separately. // Other compilers might choke on the feature test. -# if __has_cpp_attribute(clang::fallthrough) || \ - (__has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")) +# if UPRV_HAS_CPP_ATTRIBUTE(clang::fallthrough) || \ + (UPRV_HAS_FEATURE(cxx_attributes) && \ + UPRV_HAS_WARNING("-Wimplicit-fallthrough")) # define U_FALLTHROUGH [[clang::fallthrough]] # endif #elif defined(__GNUC__) && (__GNUC__ >= 7) @@ -620,7 +647,8 @@ */ #ifdef U_CHARSET_IS_UTF8 /* Use the predefined value. */ -#elif U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED +#elif U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED || \ + U_PLATFORM == U_PF_EMSCRIPTEN # define U_CHARSET_IS_UTF8 1 #else # define U_CHARSET_IS_UTF8 0 @@ -707,7 +735,7 @@ * narrow-character strings are in EBCDIC. */ # define U_SIZEOF_WCHAR_T 2 -#else +# else /* * LOCALETYPE(*CLD) or LOCALETYPE(*LOCALE) is specified. * Wide-character strings are in 16-bit EBCDIC, @@ -786,7 +814,8 @@ /* Use the predefined value. */ #elif defined(U_STATIC_IMPLEMENTATION) # define U_EXPORT -#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) +#elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \ + UPRV_HAS_DECLSPEC_ATTRIBUTE(dllimport)) # define U_EXPORT __declspec(dllexport) #elif defined(__GNUC__) # define U_EXPORT __attribute__((visibility("default"))) @@ -810,7 +839,8 @@ #ifdef U_IMPORT /* Use the predefined value. */ -#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) +#elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \ + UPRV_HAS_DECLSPEC_ATTRIBUTE(dllimport)) /* Windows needs to export/import data. */ # define U_IMPORT __declspec(dllimport) #else @@ -852,4 +882,4 @@ #endif /* @} */ -#endif +#endif // _PLATFORM_H diff -Nru icu-64.2/source/common/unicode/rbbi.h icu-65.1/source/common/unicode/rbbi.h --- icu-64.2/source/common/unicode/rbbi.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/rbbi.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,6 +18,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Rule Based Break Iterator @@ -272,7 +274,7 @@ * @return a newly-constructed RuleBasedBreakIterator * @stable ICU 2.0 */ - virtual BreakIterator* clone() const; + virtual RuleBasedBreakIterator* clone() const; /** * Compute a hash code for this BreakIterator @@ -536,6 +538,7 @@ */ static UClassID U_EXPORT2 getStaticClassID(void); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Deprecated functionality. Use clone() instead. * @@ -562,10 +565,10 @@ * or if the stackBuffer was too small to hold the clone. * @deprecated ICU 52. Use clone() instead. */ - virtual BreakIterator * createBufferClone(void *stackBuffer, - int32_t &BufferSize, - UErrorCode &status); - + virtual RuleBasedBreakIterator *createBufferClone(void *stackBuffer, + int32_t &BufferSize, + UErrorCode &status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Return the binary form of compiled break rules, @@ -696,4 +699,6 @@ #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/rep.h icu-65.1/source/common/unicode/rep.h --- icu-64.2/source/common/unicode/rep.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/rep.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,10 @@ #ifndef REP_H #define REP_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -189,9 +193,6 @@ * Clones can be used concurrently in multiple threads. * If a subclass does not implement clone(), or if an error occurs, * then NULL is returned. - * The clone functions in all subclasses return a pointer to a Replaceable - * because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * The caller must delete the clone. * * @return a clone of this object @@ -260,4 +261,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/resbund.h icu-65.1/source/common/unicode/resbund.h --- icu-64.2/source/common/unicode/resbund.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/resbund.h 2019-10-03 11:16:41.000000000 +0000 @@ -49,6 +49,9 @@ #define RESBUND_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/ures.h" #include "unicode/unistr.h" @@ -489,4 +492,7 @@ }; U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/schriter.h icu-65.1/source/common/unicode/schriter.h --- icu-64.2/source/common/unicode/schriter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/schriter.h 2019-10-03 11:16:41.000000000 +0000 @@ -21,6 +21,9 @@ #define SCHRITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/chariter.h" #include "unicode/uchriter.h" @@ -130,7 +133,7 @@ * @return the newly cloned object. * @stable ICU 2.0 */ - virtual CharacterIterator* clone(void) const; + virtual StringCharacterIterator* clone() const; /** * Sets the iterator to iterate over the provided string. @@ -186,4 +189,7 @@ }; U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/simpleformatter.h icu-65.1/source/common/unicode/simpleformatter.h --- icu-64.2/source/common/unicode/simpleformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/simpleformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -17,6 +17,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unistr.h" U_NAMESPACE_BEGIN @@ -333,4 +336,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __SIMPLEFORMATTER_H__ diff -Nru icu-64.2/source/common/unicode/std_string.h icu-65.1/source/common/unicode/std_string.h --- icu-64.2/source/common/unicode/std_string.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/std_string.h 2019-10-03 11:16:41.000000000 +0000 @@ -27,6 +27,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + // Workaround for a libstdc++ bug before libstdc++4.6 (2011). // https://bugs.llvm.org/show_bug.cgi?id=13364 #if defined(__GLIBCXX__) @@ -34,4 +36,6 @@ #endif #include +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __STD_STRING_H__ diff -Nru icu-64.2/source/common/unicode/strenum.h icu-65.1/source/common/unicode/strenum.h --- icu-64.2/source/common/unicode/strenum.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/strenum.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,10 @@ #ifndef STRENUM_H #define STRENUM_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/unistr.h" @@ -67,9 +71,6 @@ * Clones can be used concurrently in multiple threads. * If a subclass does not implement clone(), or if an error occurs, * then NULL is returned. - * The clone functions in all subclasses return a base class pointer - * because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * The caller must delete the clone. * * @return a clone of this object @@ -274,5 +275,7 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + /* STRENUM_H */ #endif diff -Nru icu-64.2/source/common/unicode/stringpiece.h icu-65.1/source/common/unicode/stringpiece.h --- icu-64.2/source/common/unicode/stringpiece.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/stringpiece.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,12 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#include +#include + #include "unicode/uobject.h" #include "unicode/std_string.h" @@ -74,6 +80,33 @@ */ StringPiece(const std::string& str) : ptr_(str.data()), length_(static_cast(str.size())) { } +#ifndef U_HIDE_DRAFT_API + /** + * Constructs from some other implementation of a string piece class, from any + * C++ record type that has these two methods: + * + * \code{.cpp} + * + * struct OtherStringPieceClass { + * const char* data(); + * size_t size(); + * }; + * + * \endcode + * + * The other string piece class will typically be std::string_view from C++17 + * or absl::string_view from Abseil. + * + * @param str the other string piece + * @draft ICU 65 + */ + template ::value && + std::is_same::value>::type> + StringPiece(T str) + : ptr_(str.data()), length_(static_cast(str.size())) {} +#endif // U_HIDE_DRAFT_API /** * Constructs from a const char * pointer and a specified length. * @param offset a const char * pointer (need not be terminated) @@ -221,4 +254,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __STRINGPIECE_H__ diff -Nru icu-64.2/source/common/unicode/stringtriebuilder.h icu-65.1/source/common/unicode/stringtriebuilder.h --- icu-64.2/source/common/unicode/stringtriebuilder.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/stringtriebuilder.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,6 +18,9 @@ #define __STRINGTRIEBUILDER_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -418,4 +421,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __STRINGTRIEBUILDER_H__ diff -Nru icu-64.2/source/common/unicode/symtable.h icu-65.1/source/common/unicode/symtable.h --- icu-64.2/source/common/unicode/symtable.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/symtable.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,9 @@ #define SYMTABLE_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -111,4 +114,6 @@ }; U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/uchar.h icu-65.1/source/common/unicode/uchar.h --- icu-64.2/source/common/unicode/uchar.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uchar.h 2019-10-03 11:16:41.000000000 +0000 @@ -2578,8 +2578,6 @@ U_STABLE UBool U_EXPORT2 u_hasBinaryProperty(UChar32 c, UProperty which); -#ifndef U_HIDE_DRAFT_API - /** * Returns a frozen USet for a binary property. * The library retains ownership over the returned object. @@ -2593,13 +2591,11 @@ * @see UProperty * @see u_hasBinaryProperty * @see Unicode::fromUSet - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI const USet * U_EXPORT2 u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode); -#endif // U_HIDE_DRAFT_API - /** * Check if a code point has the Alphabetic Unicode property. * Same as u_hasBinaryProperty(c, UCHAR_ALPHABETIC). @@ -2757,8 +2753,6 @@ U_STABLE int32_t U_EXPORT2 u_getIntPropertyMaxValue(UProperty which); -#ifndef U_HIDE_DRAFT_API - /** * Returns an immutable UCPMap for an enumerated/catalog/int-valued property. * The library retains ownership over the returned object. @@ -2772,13 +2766,11 @@ * @return the property as a map * @see UProperty * @see u_getIntPropertyValue - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI const UCPMap * U_EXPORT2 u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode); -#endif // U_HIDE_DRAFT_API - /** * Get the numeric value for a Unicode code point as defined in the * Unicode Character Database. @@ -3197,15 +3189,14 @@ u_isprint(UChar32 c); /** - * Determines whether the specified code point is a base character. + * Non-standard: Determines whether the specified code point is a base character. * True for general categories "L" (letters), "N" (numbers), * "Mc" (spacing combining marks), and "Me" (enclosing marks). * - * Note that this is different from the Unicode definition in - * chapter 3.5, conformance clause D13, - * which defines base characters to be all characters (not Cn) - * that do not graphically combine with preceding characters (M) - * and that are neither control (Cc) or format (Cf) characters. + * Note that this is different from the Unicode Standard definition in + * chapter 3.6, conformance clause D51 “Base character”, + * which defines base characters as the code points with general categories + * Letter (L), Number (N), Punctuation (P), Symbol (S), or Space Separator (Zs). * * @param c the code point to be tested * @return TRUE if the code point is a base character according to this function diff -Nru icu-64.2/source/common/unicode/ucharstriebuilder.h icu-65.1/source/common/unicode/ucharstriebuilder.h --- icu-64.2/source/common/unicode/ucharstriebuilder.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/ucharstriebuilder.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,6 +18,9 @@ #define __UCHARSTRIEBUILDER_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/stringtriebuilder.h" #include "unicode/ucharstrie.h" #include "unicode/unistr.h" @@ -184,4 +187,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __UCHARSTRIEBUILDER_H__ diff -Nru icu-64.2/source/common/unicode/ucharstrie.h icu-65.1/source/common/unicode/ucharstrie.h --- icu-64.2/source/common/unicode/ucharstrie.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/ucharstrie.h 2019-10-03 11:16:41.000000000 +0000 @@ -24,6 +24,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unistr.h" #include "unicode/uobject.h" #include "unicode/ustringtrie.h" @@ -94,6 +97,41 @@ return *this; } +#ifndef U_HIDE_DRAFT_API + /** + * Returns the state of this trie as a 64-bit integer. + * The state value is never 0. + * + * @return opaque state value + * @see resetToState64 + * @draft ICU 65 + */ + uint64_t getState64() const { + return (static_cast(remainingMatchLength_ + 2) << kState64RemainingShift) | + (uint64_t)(pos_ - uchars_); + } + + /** + * Resets this trie to the saved state. + * Unlike resetToState(State), the 64-bit state value + * must be from getState64() from the same trie object or + * from one initialized the exact same way. + * Because of no validation, this method is faster. + * + * @param state The opaque trie state value from getState64(). + * @return *this + * @see getState64 + * @see resetToState + * @see reset + * @draft ICU 65 + */ + UCharsTrie &resetToState64(uint64_t state) { + remainingMatchLength_ = static_cast(state >> kState64RemainingShift) - 2; + pos_ = uchars_ + (state & kState64PosMask); + return *this; + } +#endif /* U_HIDE_DRAFT_API */ + /** * UCharsTrie state object, for saving a trie's current state * and resetting the trie back to this state later. @@ -560,6 +598,13 @@ static const int32_t kMaxTwoUnitDelta=((kThreeUnitDeltaLead-kMinTwoUnitDeltaLead)<<16)-1; // 0x03feffff + // For getState64(): + // The remainingMatchLength_ is -1..14=(kMaxLinearMatchLength=0x10)-2 + // so we need at least 5 bits for that. + // We add 2 to store it as a positive value 1..16=kMaxLinearMatchLength. + static constexpr int32_t kState64RemainingShift = 59; + static constexpr uint64_t kState64PosMask = (UINT64_C(1) << kState64RemainingShift) - 1; + char16_t *ownedArray_; // Fixed value referencing the UCharsTrie words. @@ -575,4 +620,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __UCHARSTRIE_H__ diff -Nru icu-64.2/source/common/unicode/uchriter.h icu-65.1/source/common/unicode/uchriter.h --- icu-64.2/source/common/unicode/uchriter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uchriter.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,9 @@ #define UCHRITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/chariter.h" /** @@ -132,7 +135,7 @@ * @return the CharacterIterator newly created * @stable ICU 2.0 */ - virtual CharacterIterator* clone(void) const; + virtual UCharCharacterIterator* clone() const; /** * Sets the iterator to refer to the first code unit in its @@ -384,4 +387,7 @@ }; U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/uconfig.h icu-65.1/source/common/unicode/uconfig.h --- icu-64.2/source/common/unicode/uconfig.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uconfig.h 2019-10-03 11:16:41.000000000 +0000 @@ -453,4 +453,4 @@ # define UCONFIG_NO_FILTERED_BREAK_ITERATION 0 #endif -#endif +#endif // __UCONFIG_H__ diff -Nru icu-64.2/source/common/unicode/ucpmap.h icu-65.1/source/common/unicode/ucpmap.h --- icu-64.2/source/common/unicode/ucpmap.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/ucpmap.h 2019-10-03 11:16:41.000000000 +0000 @@ -9,8 +9,6 @@ #include "unicode/utypes.h" -#ifndef U_HIDE_DRAFT_API - U_CDECL_BEGIN /** @@ -28,7 +26,7 @@ * * @see UCPTrie * @see UMutableCPTrie - * @draft ICU 63 + * @stable ICU 63 */ typedef struct UCPMap UCPMap; @@ -39,13 +37,13 @@ * @see ucpmap_getRange * @see ucptrie_getRange * @see umutablecptrie_getRange - * @draft ICU 63 + * @stable ICU 63 */ enum UCPMapRangeOption { /** * ucpmap_getRange() enumerates all same-value ranges as stored in the map. * Most users should use this option. - * @draft ICU 63 + * @stable ICU 63 */ UCPMAP_RANGE_NORMAL, /** @@ -61,7 +59,7 @@ * special values optimized for UTF-16 string processing * or for special error behavior for unpaired surrogates, * but those values are not to be associated with the lead surrogate code *points*. - * @draft ICU 63 + * @stable ICU 63 */ UCPMAP_RANGE_FIXED_LEAD_SURROGATES, /** @@ -77,7 +75,7 @@ * special values optimized for UTF-16 string processing * or for special error behavior for unpaired surrogates, * but those values are not to be associated with the lead surrogate code *points*. - * @draft ICU 63 + * @stable ICU 63 */ UCPMAP_RANGE_FIXED_ALL_SURROGATES }; @@ -93,7 +91,7 @@ * @param c the code point * @return the map value, * or an implementation-defined error value if the code point is not in the range 0..U+10FFFF - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI uint32_t U_EXPORT2 ucpmap_get(const UCPMap *map, UChar32 c); @@ -110,7 +108,7 @@ * @param context an opaque pointer, as passed into the getRange function * @param value a value from the map * @return the modified value - * @draft ICU 63 + * @stable ICU 63 */ typedef uint32_t U_CALLCONV UCPMapValueFilter(const void *context, uint32_t value); @@ -149,7 +147,7 @@ * may have been modified by filter(context, map value) * if that function pointer is not NULL * @return the range end code point, or -1 if start is not a valid code point - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UChar32 U_EXPORT2 ucpmap_getRange(const UCPMap *map, UChar32 start, @@ -158,5 +156,4 @@ U_CDECL_END -#endif // U_HIDE_DRAFT_API #endif diff -Nru icu-64.2/source/common/unicode/ucptrie.h icu-65.1/source/common/unicode/ucptrie.h --- icu-64.2/source/common/unicode/ucptrie.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/ucptrie.h 2019-10-03 11:16:41.000000000 +0000 @@ -9,8 +9,6 @@ #include "unicode/utypes.h" -#ifndef U_HIDE_DRAFT_API - #include "unicode/localpointer.h" #include "unicode/ucpmap.h" #include "unicode/utf8.h" @@ -55,7 +53,7 @@ * The macros will return bogus values, or may crash, if used on the wrong type or value width. * * @see UMutableCPTrie - * @draft ICU 63 + * @stable ICU 63 */ struct UCPTrie { #ifndef U_IN_DOXYGEN @@ -115,23 +113,23 @@ * @see umutablecptrie_buildImmutable * @see ucptrie_openFromBinary * @see ucptrie_getType - * @draft ICU 63 + * @stable ICU 63 */ enum UCPTrieType { /** * For ucptrie_openFromBinary() to accept any type. * ucptrie_getType() will return the actual type. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_TYPE_ANY = -1, /** * Fast/simple/larger BMP data structure. Use functions and "fast" macros. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_TYPE_FAST, /** * Small/slower BMP data structure. Use functions and "small" macros. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_TYPE_SMALL }; @@ -145,30 +143,30 @@ * @see umutablecptrie_buildImmutable * @see ucptrie_openFromBinary * @see ucptrie_getValueWidth - * @draft ICU 63 + * @stable ICU 63 */ enum UCPTrieValueWidth { /** * For ucptrie_openFromBinary() to accept any data value width. * ucptrie_getValueWidth() will return the actual data value width. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_ANY = -1, /** * The trie stores 16 bits per data value. * It returns them as unsigned values 0..0xffff=65535. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_16, /** * The trie stores 32 bits per data value. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_32, /** * The trie stores 8 bits per data value. * It returns them as unsigned values 0..0xff=255. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_8 }; @@ -200,7 +198,7 @@ * @see umutablecptrie_open * @see umutablecptrie_buildImmutable * @see ucptrie_toBinary - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrie * U_EXPORT2 ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth, @@ -211,30 +209,11 @@ * Closes a trie and releases associated memory. * * @param trie the trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 ucptrie_close(UCPTrie *trie); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUCPTriePointer - * "Smart pointer" class, closes a UCPTrie via ucptrie_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @draft ICU 63 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close); - -U_NAMESPACE_END - -#endif - /** * Returns the trie type. * @@ -242,7 +221,7 @@ * @return the trie type * @see ucptrie_openFromBinary * @see UCPTRIE_TYPE_ANY - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrieType U_EXPORT2 ucptrie_getType(const UCPTrie *trie); @@ -254,7 +233,7 @@ * @return the number of bits in a trie data value * @see ucptrie_openFromBinary * @see UCPTRIE_VALUE_BITS_ANY - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrieValueWidth U_EXPORT2 ucptrie_getValueWidth(const UCPTrie *trie); @@ -271,7 +250,7 @@ * @param c the code point * @return the trie value, * or the trie error value if the code point is not in the range 0..U+10FFFF - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI uint32_t U_EXPORT2 ucptrie_get(const UCPTrie *trie, UChar32 c); @@ -310,7 +289,7 @@ * may have been modified by filter(context, trie value) * if that function pointer is not NULL * @return the range end code point, or -1 if start is not a valid code point - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UChar32 U_EXPORT2 ucptrie_getRange(const UCPTrie *trie, UChar32 start, @@ -330,7 +309,7 @@ * @return the number of bytes written or (if buffer overflow) needed for the trie * * @see ucptrie_openFromBinary() - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI int32_t U_EXPORT2 ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode *pErrorCode); @@ -341,7 +320,7 @@ * Do not use this macro in any other way. * * @see UCPTRIE_VALUE_BITS_16 - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_16(trie, i) ((trie)->data.ptr16[i]) @@ -351,7 +330,7 @@ * Do not use this macro in any other way. * * @see UCPTRIE_VALUE_BITS_32 - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_32(trie, i) ((trie)->data.ptr32[i]) @@ -361,7 +340,7 @@ * Do not use this macro in any other way. * * @see UCPTRIE_VALUE_BITS_8 - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_8(trie, i) ((trie)->data.ptr8[i]) @@ -373,7 +352,7 @@ * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point * @return The code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_FAST_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_CP_INDEX(trie, 0xffff, c)) @@ -385,7 +364,7 @@ * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point * @return The code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_SMALL_GET(trie, dataAccess, c) \ dataAccess(trie, _UCPTRIE_CP_INDEX(trie, UCPTRIE_SMALL_MAX, c)) @@ -401,9 +380,9 @@ * @param limit (const UChar *, in) the limit pointer for the text, or NULL if NUL-terminated * @param c (UChar32, out) variable for the code point * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) { \ +#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \ (c) = *(src)++; \ int32_t __index; \ if (!U16_IS_SURROGATE(c)) { \ @@ -419,7 +398,7 @@ } \ } \ (result) = dataAccess(trie, __index); \ -} +} UPRV_BLOCK_MACRO_END /** * UTF-16: Reads the previous code point (UChar32 c, out), pre-decrements src, @@ -432,9 +411,9 @@ * @param src (const UChar *, in/out) the source text pointer * @param c (UChar32, out) variable for the code point * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) { \ +#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \ (c) = *--(src); \ int32_t __index; \ if (!U16_IS_SURROGATE(c)) { \ @@ -450,7 +429,7 @@ } \ } \ (result) = dataAccess(trie, __index); \ -} +} UPRV_BLOCK_MACRO_END /** * UTF-8: Post-increments src and gets a value from the trie. @@ -466,9 +445,9 @@ * @param src (const char *, in/out) the source text pointer * @param limit (const char *, in) the limit pointer for the text (must not be NULL) * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) { \ +#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __lead = (uint8_t)*(src)++; \ if (!U8_IS_SINGLE(__lead)) { \ uint8_t __t1, __t2, __t3; \ @@ -496,7 +475,7 @@ } \ } \ (result) = dataAccess(trie, __lead); \ -} +} UPRV_BLOCK_MACRO_END /** * UTF-8: Pre-decrements src and gets a value from the trie. @@ -512,9 +491,9 @@ * @param start (const char *, in) the start pointer for the text * @param src (const char *, in/out) the source text pointer * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) { \ +#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __index = (uint8_t)*--(src); \ if (!U8_IS_SINGLE(__index)) { \ __index = ucptrie_internalU8PrevIndex((trie), __index, (const uint8_t *)(start), \ @@ -523,7 +502,7 @@ __index >>= 3; \ } \ (result) = dataAccess(trie, __index); \ -} +} UPRV_BLOCK_MACRO_END /** * Returns a trie value for an ASCII code point, without range checking. @@ -532,7 +511,7 @@ * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point; must be U+0000..U+007F * @return The ASCII code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_ASCII_GET(trie, dataAccess, c) dataAccess(trie, c) @@ -545,7 +524,7 @@ * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point, must be U+0000..U+FFFF * @return The BMP code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_FAST_BMP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_FAST_INDEX(trie, c)) @@ -557,7 +536,7 @@ * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point, must be U+10000..U+10FFFF * @return The supplementary code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_FAST_SUPP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_SMALL_INDEX(trie, c)) @@ -642,5 +621,24 @@ U_CDECL_END #endif // U_IN_DOXYGEN -#endif // U_HIDE_DRAFT_API + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUCPTriePointer + * "Smart pointer" class, closes a UCPTrie via ucptrie_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 63 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close); + +U_NAMESPACE_END + +#endif // U_SHOW_CPLUSPLUS_API + #endif diff -Nru icu-64.2/source/common/unicode/ucurr.h icu-65.1/source/common/unicode/ucurr.h --- icu-64.2/source/common/unicode/ucurr.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/ucurr.h 2019-10-03 11:16:41.000000000 +0000 @@ -159,14 +159,14 @@ * @param currency null-terminated 3-letter ISO 4217 code * @param locale locale in which to display currency * @param nameStyle selector for which kind of name to return - * @param isChoiceFormat fill-in set to TRUE if the returned value - * is a ChoiceFormat pattern; otherwise it is a static string + * @param isChoiceFormat always set to FALSE, or can be NULL; + * display names are static strings; + * since ICU 4.4, ChoiceFormat patterns are no longer supported * @param len fill-in parameter to receive length of result * @param ec error code * @return pointer to display string of 'len' UChars. If the resource * data contains no entry for 'currency', then 'currency' itself is - * returned. If *isChoiceFormat is TRUE, then the result is a - * ChoiceFormat pattern. Otherwise it is a static string. + * returned. * @stable ICU 2.6 */ U_STABLE const UChar* U_EXPORT2 @@ -183,14 +183,15 @@ * currency object in the en_US locale is "US dollar" or "US dollars". * @param currency null-terminated 3-letter ISO 4217 code * @param locale locale in which to display currency - * @param isChoiceFormat fill-in set to TRUE if the returned value - * is a ChoiceFormat pattern; otherwise it is a static string + * @param isChoiceFormat always set to FALSE, or can be NULL; + * display names are static strings; + * since ICU 4.4, ChoiceFormat patterns are no longer supported * @param pluralCount plural count * @param len fill-in parameter to receive length of result * @param ec error code * @return pointer to display string of 'len' UChars. If the resource * data contains no entry for 'currency', then 'currency' itself is - * returned. + * returned. * @stable ICU 4.2 */ U_STABLE const UChar* U_EXPORT2 @@ -320,7 +321,7 @@ * Provides a UEnumeration object for listing ISO-4217 codes. * @param currType You can use one of several UCurrCurrencyType values for this * variable. You can also | (or) them together to get a specific list of - * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to + * currencies. Most people will want to use the (UCURR_COMMON|UCURR_NON_DEPRECATED) value to * get a list of current currencies. * @param pErrorCode Error code * @stable ICU 3.2 diff -Nru icu-64.2/source/common/unicode/udata.h icu-65.1/source/common/unicode/udata.h --- icu-64.2/source/common/unicode/udata.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/udata.h 2019-10-03 11:16:41.000000000 +0000 @@ -264,25 +264,6 @@ U_STABLE void U_EXPORT2 udata_close(UDataMemory *pData); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUDataMemoryPointer - * "Smart pointer" class, closes a UDataMemory via udata_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close); - -U_NAMESPACE_END - -#endif - /** * Get the pointer to the actual data inside the data memory. * The data is read-only. @@ -434,4 +415,23 @@ U_CDECL_END +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUDataMemoryPointer + * "Smart pointer" class, closes a UDataMemory via udata_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 4.4 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close); + +U_NAMESPACE_END + +#endif // U_SHOW_CPLUSPLUS_API + #endif diff -Nru icu-64.2/source/common/unicode/uloc.h icu-65.1/source/common/unicode/uloc.h --- icu-64.2/source/common/unicode/uloc.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uloc.h 2019-10-03 11:16:41.000000000 +0000 @@ -742,12 +742,18 @@ /** - * Gets the specified locale from a list of all available locales. - * The return value is a pointer to an item of - * a locale name array. Both this array and the pointers - * it contains are owned by ICU and should not be deleted or written through - * by the caller. The locale name is terminated by a null pointer. - * @param n the specific locale name index of the available locale list + * Gets the specified locale from a list of available locales. + * + * This method corresponds to uloc_openAvailableByType called with the + * ULOC_AVAILABLE_DEFAULT type argument. + * + * The return value is a pointer to an item of a locale name array. Both this + * array and the pointers it contains are owned by ICU and should not be + * deleted or written through by the caller. The locale name is terminated by + * a null pointer. + * + * @param n the specific locale name index of the available locale list; + * should not exceed the number returned by uloc_countAvailable. * @return a specified locale name of all available locales * @stable ICU 2.0 */ @@ -762,6 +768,72 @@ */ U_STABLE int32_t U_EXPORT2 uloc_countAvailable(void); +#ifndef U_HIDE_DRAFT_API + +/** + * Types for uloc_getAvailableByType and uloc_countAvailableByType. + * + * @draft ICU 65 + */ +typedef enum ULocAvailableType { + /** + * Locales that return data when passed to ICU APIs, + * but not including legacy or alias locales. + * + * @draft ICU 65 + */ + ULOC_AVAILABLE_DEFAULT, + + /** + * Legacy or alias locales that return data when passed to ICU APIs. + * Examples of supported legacy or alias locales: + * + * - iw (alias to he) + * - mo (alias to ro) + * - zh_CN (alias to zh_Hans_CN) + * - sr_BA (alias to sr_Cyrl_BA) + * - ars (alias to ar_SA) + * + * The locales in this set are disjoint from the ones in + * ULOC_AVAILABLE_DEFAULT. To get both sets at the same time, use + * ULOC_AVAILABLE_WITH_LEGACY_ALIASES. + * + * @draft ICU 65 + */ + ULOC_AVAILABLE_ONLY_LEGACY_ALIASES, + + /** + * The union of the locales in ULOC_AVAILABLE_DEFAULT and + * ULOC_AVAILABLE_ONLY_LEGACY_ALIAS. + * + * @draft ICU 65 + */ + ULOC_AVAILABLE_WITH_LEGACY_ALIASES, + +#ifndef U_HIDE_INTERNAL_API + /** + * @internal + */ + ULOC_AVAILABLE_COUNT +#endif +} ULocAvailableType; + +/** + * Gets a list of available locales according to the type argument, allowing + * the user to access different sets of supported locales in ICU. + * + * The returned UEnumeration must be closed by the caller. + * + * @param type Type choice from ULocAvailableType. + * @param status Set if an error occurred. + * @return a UEnumeration owned by the caller, or nullptr on failure. + * @draft ICU 65 + */ +U_DRAFT UEnumeration* U_EXPORT2 +uloc_openAvailableByType(ULocAvailableType type, UErrorCode* status); + +#endif // U_HIDE_DRAFT_API + /** * * Gets a list of all available 2-letter language codes defined in ISO 639, diff -Nru icu-64.2/source/common/unicode/umachine.h icu-65.1/source/common/unicode/umachine.h --- icu-64.2/source/common/unicode/umachine.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/umachine.h 2019-10-03 11:16:41.000000000 +0000 @@ -140,6 +140,42 @@ #define U_FINAL final #endif +// Before ICU 65, function-like, multi-statement ICU macros were just defined as +// series of statements wrapped in { } blocks and the caller could choose to +// either treat them as if they were actual functions and end the invocation +// with a trailing ; creating an empty statement after the block or else omit +// this trailing ; using the knowledge that the macro would expand to { }. +// +// But doing so doesn't work well with macros that look like functions and +// compiler warnings about empty statements (ICU-20601) and ICU 65 therefore +// switches to the standard solution of wrapping such macros in do { } while. +// +// This will however break existing code that depends on being able to invoke +// these macros without a trailing ; so to be able to remain compatible with +// such code the wrapper is itself defined as macros so that it's possible to +// build ICU 65 and later with the old macro behaviour, like this: +// +// export CPPFLAGS='-DUPRV_BLOCK_MACRO_BEGIN="" -DUPRV_BLOCK_MACRO_END=""' +// runConfigureICU ... +// + +/** + * \def UPRV_BLOCK_MACRO_BEGIN + * Defined as the "do" keyword by default. + * @internal + */ +#ifndef UPRV_BLOCK_MACRO_BEGIN +#define UPRV_BLOCK_MACRO_BEGIN do +#endif + +/** + * \def UPRV_BLOCK_MACRO_END + * Defined as "while (FALSE)" by default. + * @internal + */ +#ifndef UPRV_BLOCK_MACRO_END +#define UPRV_BLOCK_MACRO_END while (FALSE) +#endif /*==========================================================================*/ /* limits for int32_t etc., like in POSIX inttypes.h */ diff -Nru icu-64.2/source/common/unicode/umutablecptrie.h icu-65.1/source/common/unicode/umutablecptrie.h --- icu-64.2/source/common/unicode/umutablecptrie.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/umutablecptrie.h 2019-10-03 11:16:41.000000000 +0000 @@ -9,8 +9,6 @@ #include "unicode/utypes.h" -#ifndef U_HIDE_DRAFT_API - #include "unicode/localpointer.h" #include "unicode/ucpmap.h" #include "unicode/ucptrie.h" @@ -44,7 +42,7 @@ * * @see UCPTrie * @see umutablecptrie_buildImmutable - * @draft ICU 63 + * @stable ICU 63 */ typedef struct UMutableCPTrie UMutableCPTrie; @@ -59,7 +57,7 @@ * @param errorValue the value for out-of-range code points and ill-formed UTF-8/16 * @param pErrorCode an in/out ICU UErrorCode * @return the trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErrorCode); @@ -71,7 +69,7 @@ * @param other the trie to clone * @param pErrorCode an in/out ICU UErrorCode * @return the trie clone - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode); @@ -80,7 +78,7 @@ * Closes a mutable trie and releases associated memory. * * @param trie the trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 umutablecptrie_close(UMutableCPTrie *trie); @@ -96,7 +94,7 @@ * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 63 + * @stable ICU 63 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); @@ -111,7 +109,7 @@ * @param map the source map * @param pErrorCode an in/out ICU UErrorCode * @return the mutable trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_fromUCPMap(const UCPMap *map, UErrorCode *pErrorCode); @@ -123,7 +121,7 @@ * @param trie the immutable trie * @param pErrorCode an in/out ICU UErrorCode * @return the mutable trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_fromUCPTrie(const UCPTrie *trie, UErrorCode *pErrorCode); @@ -134,7 +132,7 @@ * @param trie the trie * @param c the code point * @return the value - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI uint32_t U_EXPORT2 umutablecptrie_get(const UMutableCPTrie *trie, UChar32 c); @@ -166,7 +164,7 @@ * may have been modified by filter(context, trie value) * if that function pointer is not NULL * @return the range end code point, or -1 if start is not a valid code point - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UChar32 U_EXPORT2 umutablecptrie_getRange(const UMutableCPTrie *trie, UChar32 start, @@ -180,7 +178,7 @@ * @param c the code point * @param value the value * @param pErrorCode an in/out ICU UErrorCode - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 umutablecptrie_set(UMutableCPTrie *trie, UChar32 c, uint32_t value, UErrorCode *pErrorCode); @@ -194,7 +192,7 @@ * @param end the last code point to get the value (inclusive) * @param value the value * @param pErrorCode an in/out ICU UErrorCode - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 umutablecptrie_setRange(UMutableCPTrie *trie, @@ -229,7 +227,7 @@ * @param pErrorCode an in/out ICU UErrorCode * * @see umutablecptrie_fromUCPTrie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrie * U_EXPORT2 umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieValueWidth valueWidth, @@ -237,5 +235,4 @@ U_CDECL_END -#endif // U_HIDE_DRAFT_API #endif diff -Nru icu-64.2/source/common/unicode/unifilt.h icu-65.1/source/common/unicode/unifilt.h --- icu-64.2/source/common/unicode/unifilt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/unifilt.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,10 @@ #ifndef UNIFILT_H #define UNIFILT_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unifunct.h" #include "unicode/unimatch.h" @@ -68,6 +72,14 @@ virtual ~UnicodeFilter(); /** + * Clones this object polymorphically. + * The caller owns the result and should delete it when done. + * @return clone, or nullptr if an error occurred + * @stable ICU 2.4 + */ + virtual UnicodeFilter* clone() const = 0; + + /** * Returns true for characters that are in the selected * subset. In other words, if a character is to be * filtered, then contains() returns @@ -119,4 +131,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/unifunct.h icu-65.1/source/common/unicode/unifunct.h --- icu-64.2/source/common/unicode/unifunct.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/unifunct.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,9 @@ #define UNIFUNCT_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -124,4 +127,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/unimatch.h icu-65.1/source/common/unicode/unimatch.h --- icu-64.2/source/common/unicode/unimatch.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/unimatch.h 2019-10-03 11:16:41.000000000 +0000 @@ -17,6 +17,7 @@ * \brief C++ API: Unicode Matcher */ +#if U_SHOW_CPLUSPLUS_API U_NAMESPACE_BEGIN @@ -162,4 +163,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/uniset.h icu-65.1/source/common/unicode/uniset.h --- icu-64.2/source/common/unicode/uniset.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uniset.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,10 @@ #ifndef UNICODESET_H #define UNICODESET_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/ucpmap.h" #include "unicode/unifilt.h" #include "unicode/unistr.h" @@ -501,7 +505,7 @@ * @see cloneAsThawed * @stable ICU 2.0 */ - virtual UnicodeFunctor* clone() const; + virtual UnicodeSet* clone() const; /** * Returns the hash code value for this set. @@ -579,7 +583,7 @@ * @see cloneAsThawed * @stable ICU 3.8 */ - UnicodeFunctor *freeze(); + UnicodeSet *freeze(); /** * Clone the set and make the clone mutable. @@ -589,7 +593,7 @@ * @see isFrozen * @stable ICU 3.8 */ - UnicodeFunctor *cloneAsThawed() const; + UnicodeSet *cloneAsThawed() const; //---------------------------------------------------------------- // Public API @@ -1651,11 +1655,10 @@ const UnicodeSet* inclusions, UErrorCode &status); -#ifndef U_HIDE_DRAFT_API // Skipped: ucpmap.h is draft only. + // UCPMap is now stable ICU 63 void applyIntPropertyValue(const UCPMap *map, UCPMapValueFilter *filter, const void *context, UErrorCode &errorCode); -#endif /* U_HIDE_DRAFT_API */ /** * Set the new pattern to cache. @@ -1736,4 +1739,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/unistr.h icu-65.1/source/common/unicode/unistr.h --- icu-64.2/source/common/unicode/unistr.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/unistr.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,8 +28,11 @@ * \brief C++ API: Unicode String */ -#include #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#include #include "unicode/char16ptr.h" #include "unicode/rep.h" #include "unicode/std_string.h" @@ -209,7 +212,9 @@ * similar functionality as the Java String and StringBuffer/StringBuilder classes. * It is a concrete implementation of the abstract class Replaceable (for transliteration). * - * A UnicodeString may also "alias" an external array of characters + * The UnicodeString equivalent of std::string’s clear() is remove(). + * + * A UnicodeString may "alias" an external array of characters * (that is, point to it, rather than own the array) * whose lifetime must then at least match the lifetime of the aliasing object. * This aliasing may be preserved when returning a UnicodeString by value, @@ -2092,8 +2097,7 @@ * s.truncate(0); // set to an empty string (complete truncation), or * s=UnicodeString(); // assign an empty string, or * s.setTo((UChar32)-1); // set to a pseudo code point that is out of range, or - * static const char16_t nul=0; - * s.setTo(&nul, 0); // set to an empty C Unicode string + * s.setTo(u"", 0); // set to an empty C Unicode string * } * \endcode * @@ -2534,11 +2538,14 @@ /* Remove operations */ /** - * Remove all characters from the UnicodeString object. + * Removes all characters from the UnicodeString object and clears the bogus flag. + * This is the UnicodeString equivalent of std::string’s clear(). + * * @return a reference to this + * @see setToBogus * @stable ICU 2.0 */ - inline UnicodeString& remove(void); + inline UnicodeString& remove(); /** * Remove the characters in the range @@ -3034,11 +3041,11 @@ * uint16_t * constructor. * Delegates to UnicodeString(const char16_t *, int32_t). * @param text UTF-16 string - * @param length string length + * @param textLength string length * @stable ICU 59 */ - UnicodeString(const uint16_t *text, int32_t length) : - UnicodeString(ConstChar16Ptr(text), length) {} + UnicodeString(const uint16_t *text, int32_t textLength) : + UnicodeString(ConstChar16Ptr(text), textLength) {} #endif #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN) @@ -3047,21 +3054,21 @@ * (Only defined if U_SIZEOF_WCHAR_T==2.) * Delegates to UnicodeString(const char16_t *, int32_t). * @param text NUL-terminated UTF-16 string - * @param length string length + * @param textLength string length * @stable ICU 59 */ - UnicodeString(const wchar_t *text, int32_t length) : - UnicodeString(ConstChar16Ptr(text), length) {} + UnicodeString(const wchar_t *text, int32_t textLength) : + UnicodeString(ConstChar16Ptr(text), textLength) {} #endif /** * nullptr_t constructor. * Effectively the same as the default constructor, makes an empty string object. * @param text nullptr - * @param length ignored + * @param textLength ignored * @stable ICU 59 */ - inline UnicodeString(const std::nullptr_t text, int32_t length); + inline UnicodeString(const std::nullptr_t text, int32_t textLength); /** * Readonly-aliasing char16_t* constructor. @@ -3266,13 +3273,13 @@ * } * \endcode * @param src String using only invariant characters. - * @param length Length of src, or -1 if NUL-terminated. + * @param textLength Length of src, or -1 if NUL-terminated. * @param inv Signature-distinguishing paramater, use US_INV. * * @see US_INV * @stable ICU 3.2 */ - UnicodeString(const char *src, int32_t length, enum EInvariant inv); + UnicodeString(const char *src, int32_t textLength, enum EInvariant inv); /** @@ -3323,9 +3330,6 @@ * Clones can be used concurrently in multiple threads. * If a subclass does not implement clone(), or if an error occurs, * then NULL is returned. - * The clone functions in all subclasses return a pointer to a Replaceable - * because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * The caller must delete the clone. * * @return a clone of this object @@ -3334,7 +3338,7 @@ * @see getDynamicClassID * @stable ICU 2.6 */ - virtual Replaceable *clone() const; + virtual UnicodeString *clone() const; /** Destructor. * @stable ICU 2.0 @@ -4748,4 +4752,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/unorm.h icu-65.1/source/common/unicode/unorm.h --- icu-64.2/source/common/unicode/unorm.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/unorm.h 2019-10-03 11:16:41.000000000 +0000 @@ -131,6 +131,8 @@ // Do not conditionalize the following enum with #ifndef U_HIDE_DEPRECATED_API, // it is needed for layout of Normalizer object. +#ifndef U_FORCE_HIDE_DEPRECATED_API + /** * Constants for normalization modes. * @deprecated ICU 56 Use unorm2.h instead. @@ -155,6 +157,8 @@ UNORM_MODE_COUNT } UNormalizationMode; +#endif // U_FORCE_HIDE_DEPRECATED_API + #ifndef U_HIDE_DEPRECATED_API /** diff -Nru icu-64.2/source/common/unicode/uobject.h icu-65.1/source/common/unicode/uobject.h --- icu-64.2/source/common/unicode/uobject.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uobject.h 2019-10-03 11:16:41.000000000 +0000 @@ -20,6 +20,9 @@ #define __UOBJECT_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/platform.h" /** @@ -43,7 +46,7 @@ * @stable ICU 4.2. Since ICU 64, Use U_NOEXCEPT instead. See ICU-20422. */ #ifndef U_NO_THROW -#define U_NO_THROW throw() +#define U_NO_THROW U_NOEXCEPT #endif /*===========================================================================*/ @@ -212,11 +215,8 @@ * The clone() function is not available in UObject because it is not * implemented by all ICU classes. * Many ICU services provide a clone() function for their class trees, - * defined on the service's C++ base class, and all subclasses within that - * service class tree return a pointer to the service base class + * defined on the service's C++ base class * (which itself is a subclass of UObject). - * This is because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * * @stable ICU 2.2 */ @@ -319,4 +319,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/urename.h icu-65.1/source/common/unicode/urename.h --- icu-64.2/source/common/unicode/urename.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/urename.h 2019-10-03 11:16:41.000000000 +0000 @@ -193,10 +193,13 @@ #define res_getAlias U_ICU_ENTRY_POINT_RENAME(res_getAlias) #define res_getArrayItem U_ICU_ENTRY_POINT_RENAME(res_getArrayItem) #define res_getBinary U_ICU_ENTRY_POINT_RENAME(res_getBinary) +#define res_getBinaryNoTrace U_ICU_ENTRY_POINT_RENAME(res_getBinaryNoTrace) #define res_getIntVector U_ICU_ENTRY_POINT_RENAME(res_getIntVector) +#define res_getIntVectorNoTrace U_ICU_ENTRY_POINT_RENAME(res_getIntVectorNoTrace) #define res_getPublicType U_ICU_ENTRY_POINT_RENAME(res_getPublicType) #define res_getResource U_ICU_ENTRY_POINT_RENAME(res_getResource) #define res_getString U_ICU_ENTRY_POINT_RENAME(res_getString) +#define res_getStringNoTrace U_ICU_ENTRY_POINT_RENAME(res_getStringNoTrace) #define res_getTableItemByIndex U_ICU_ENTRY_POINT_RENAME(res_getTableItemByIndex) #define res_getTableItemByKey U_ICU_ENTRY_POINT_RENAME(res_getTableItemByKey) #define res_load U_ICU_ENTRY_POINT_RENAME(res_load) @@ -523,6 +526,7 @@ #define ucal_getDefaultTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getDefaultTimeZone) #define ucal_getFieldDifference U_ICU_ENTRY_POINT_RENAME(ucal_getFieldDifference) #define ucal_getGregorianChange U_ICU_ENTRY_POINT_RENAME(ucal_getGregorianChange) +#define ucal_getHostTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getHostTimeZone) #define ucal_getKeywordValuesForLocale U_ICU_ENTRY_POINT_RENAME(ucal_getKeywordValuesForLocale) #define ucal_getLimit U_ICU_ENTRY_POINT_RENAME(ucal_getLimit) #define ucal_getLocaleByType U_ICU_ENTRY_POINT_RENAME(ucal_getLocaleByType) @@ -575,7 +579,6 @@ #define ucasemap_getLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_getLocale) #define ucasemap_getOptions U_ICU_ENTRY_POINT_RENAME(ucasemap_getOptions) #define ucasemap_internalUTF8ToTitle U_ICU_ENTRY_POINT_RENAME(ucasemap_internalUTF8ToTitle) -#define ucasemap_mapUTF8 U_ICU_ENTRY_POINT_RENAME(ucasemap_mapUTF8) #define ucasemap_open U_ICU_ENTRY_POINT_RENAME(ucasemap_open) #define ucasemap_setBreakIterator U_ICU_ENTRY_POINT_RENAME(ucasemap_setBreakIterator) #define ucasemap_setLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_setLocale) @@ -930,16 +933,9 @@ #define ufieldpositer_close U_ICU_ENTRY_POINT_RENAME(ufieldpositer_close) #define ufieldpositer_next U_ICU_ENTRY_POINT_RENAME(ufieldpositer_next) #define ufieldpositer_open U_ICU_ENTRY_POINT_RENAME(ufieldpositer_open) -#define ufile_close_translit U_ICU_ENTRY_POINT_RENAME(ufile_close_translit) -#define ufile_fill_uchar_buffer U_ICU_ENTRY_POINT_RENAME(ufile_fill_uchar_buffer) -#define ufile_flush_io U_ICU_ENTRY_POINT_RENAME(ufile_flush_io) -#define ufile_flush_translit U_ICU_ENTRY_POINT_RENAME(ufile_flush_translit) #define ufile_getch U_ICU_ENTRY_POINT_RENAME(ufile_getch) #define ufile_getch32 U_ICU_ENTRY_POINT_RENAME(ufile_getch32) -#define ufmt_64tou U_ICU_ENTRY_POINT_RENAME(ufmt_64tou) #define ufmt_close U_ICU_ENTRY_POINT_RENAME(ufmt_close) -#define ufmt_defaultCPToUnicode U_ICU_ENTRY_POINT_RENAME(ufmt_defaultCPToUnicode) -#define ufmt_digitvalue U_ICU_ENTRY_POINT_RENAME(ufmt_digitvalue) #define ufmt_getArrayItemByIndex U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayItemByIndex) #define ufmt_getArrayLength U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayLength) #define ufmt_getDate U_ICU_ENTRY_POINT_RENAME(ufmt_getDate) @@ -951,11 +947,7 @@ #define ufmt_getType U_ICU_ENTRY_POINT_RENAME(ufmt_getType) #define ufmt_getUChars U_ICU_ENTRY_POINT_RENAME(ufmt_getUChars) #define ufmt_isNumeric U_ICU_ENTRY_POINT_RENAME(ufmt_isNumeric) -#define ufmt_isdigit U_ICU_ENTRY_POINT_RENAME(ufmt_isdigit) #define ufmt_open U_ICU_ENTRY_POINT_RENAME(ufmt_open) -#define ufmt_ptou U_ICU_ENTRY_POINT_RENAME(ufmt_ptou) -#define ufmt_uto64 U_ICU_ENTRY_POINT_RENAME(ufmt_uto64) -#define ufmt_utop U_ICU_ENTRY_POINT_RENAME(ufmt_utop) #define ufmtval_getString U_ICU_ENTRY_POINT_RENAME(ufmtval_getString) #define ufmtval_nextPosition U_ICU_ENTRY_POINT_RENAME(ufmtval_nextPosition) #define ugender_getInstance U_ICU_ENTRY_POINT_RENAME(ugender_getInstance) @@ -1103,6 +1095,7 @@ #define uloc_getVariant U_ICU_ENTRY_POINT_RENAME(uloc_getVariant) #define uloc_isRightToLeft U_ICU_ENTRY_POINT_RENAME(uloc_isRightToLeft) #define uloc_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(uloc_minimizeSubtags) +#define uloc_openAvailableByType U_ICU_ENTRY_POINT_RENAME(uloc_openAvailableByType) #define uloc_openKeywordList U_ICU_ENTRY_POINT_RENAME(uloc_openKeywordList) #define uloc_openKeywords U_ICU_ENTRY_POINT_RENAME(uloc_openKeywords) #define uloc_setDefault U_ICU_ENTRY_POINT_RENAME(uloc_setDefault) @@ -1159,9 +1152,6 @@ #define umsg_toPattern U_ICU_ENTRY_POINT_RENAME(umsg_toPattern) #define umsg_vformat U_ICU_ENTRY_POINT_RENAME(umsg_vformat) #define umsg_vparse U_ICU_ENTRY_POINT_RENAME(umsg_vparse) -#define umtx_condBroadcast U_ICU_ENTRY_POINT_RENAME(umtx_condBroadcast) -#define umtx_condSignal U_ICU_ENTRY_POINT_RENAME(umtx_condSignal) -#define umtx_condWait U_ICU_ENTRY_POINT_RENAME(umtx_condWait) #define umtx_lock U_ICU_ENTRY_POINT_RENAME(umtx_lock) #define umtx_unlock U_ICU_ENTRY_POINT_RENAME(umtx_unlock) #define umutablecptrie_buildImmutable U_ICU_ENTRY_POINT_RENAME(umutablecptrie_buildImmutable) @@ -1327,7 +1317,6 @@ #define uprv_decNumberAbs U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAbs) #define uprv_decNumberAdd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAdd) #define uprv_decNumberAnd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAnd) -#define uprv_decNumberClass U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClass) #define uprv_decNumberClassToString U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClassToString) #define uprv_decNumberCompare U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompare) #define uprv_decNumberCompareSignal U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompareSignal) @@ -1393,6 +1382,7 @@ #define uprv_dlsym_func U_ICU_ENTRY_POINT_RENAME(uprv_dlsym_func) #define uprv_eastrncpy U_ICU_ENTRY_POINT_RENAME(uprv_eastrncpy) #define uprv_ebcdicFromAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicFromAscii) +#define uprv_ebcdicToAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicToAscii) #define uprv_ebcdicToLowercaseAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicToLowercaseAscii) #define uprv_ebcdictolower U_ICU_ENTRY_POINT_RENAME(uprv_ebcdictolower) #define uprv_fabs U_ICU_ENTRY_POINT_RENAME(uprv_fabs) @@ -1412,6 +1402,7 @@ #define uprv_getUTCtime U_ICU_ENTRY_POINT_RENAME(uprv_getUTCtime) #define uprv_int32Comparator U_ICU_ENTRY_POINT_RENAME(uprv_int32Comparator) #define uprv_isASCIILetter U_ICU_ENTRY_POINT_RENAME(uprv_isASCIILetter) +#define uprv_isEbcdicAtSign U_ICU_ENTRY_POINT_RENAME(uprv_isEbcdicAtSign) #define uprv_isInfinite U_ICU_ENTRY_POINT_RENAME(uprv_isInfinite) #define uprv_isInvariantString U_ICU_ENTRY_POINT_RENAME(uprv_isInvariantString) #define uprv_isInvariantUString U_ICU_ENTRY_POINT_RENAME(uprv_isInvariantUString) @@ -1579,6 +1570,7 @@ #define ures_getUTF8String U_ICU_ENTRY_POINT_RENAME(ures_getUTF8String) #define ures_getUTF8StringByIndex U_ICU_ENTRY_POINT_RENAME(ures_getUTF8StringByIndex) #define ures_getUTF8StringByKey U_ICU_ENTRY_POINT_RENAME(ures_getUTF8StringByKey) +#define ures_getValueWithFallback U_ICU_ENTRY_POINT_RENAME(ures_getValueWithFallback) #define ures_getVersion U_ICU_ENTRY_POINT_RENAME(ures_getVersion) #define ures_getVersionByKey U_ICU_ENTRY_POINT_RENAME(ures_getVersionByKey) #define ures_getVersionNumber U_ICU_ENTRY_POINT_RENAME(ures_getVersionNumber) diff -Nru icu-64.2/source/common/unicode/usetiter.h icu-65.1/source/common/unicode/usetiter.h --- icu-64.2/source/common/unicode/usetiter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/usetiter.h 2019-10-03 11:16:41.000000000 +0000 @@ -10,6 +10,9 @@ #define USETITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/unistr.h" @@ -317,4 +320,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/common/unicode/utext.h icu-65.1/source/common/unicode/utext.h --- icu-64.2/source/common/unicode/utext.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/utext.h 2019-10-03 11:16:41.000000000 +0000 @@ -766,12 +766,14 @@ * * @stable ICU 3.8 */ -#define UTEXT_SETNATIVEINDEX(ut, ix) \ - { int64_t __offset = (ix) - (ut)->chunkNativeStart; \ - if (__offset>=0 && __offset<(int64_t)(ut)->nativeIndexingLimit && (ut)->chunkContents[__offset]<0xdc00) { \ - (ut)->chunkOffset=(int32_t)__offset; \ - } else { \ - utext_setNativeIndex((ut), (ix)); } } +#define UTEXT_SETNATIVEINDEX(ut, ix) UPRV_BLOCK_MACRO_BEGIN { \ + int64_t __offset = (ix) - (ut)->chunkNativeStart; \ + if (__offset>=0 && __offset<(int64_t)(ut)->nativeIndexingLimit && (ut)->chunkContents[__offset]<0xdc00) { \ + (ut)->chunkOffset=(int32_t)__offset; \ + } else { \ + utext_setNativeIndex((ut), (ix)); \ + } \ +} UPRV_BLOCK_MACRO_END diff -Nru icu-64.2/source/common/unicode/utf16.h icu-65.1/source/common/unicode/utf16.h --- icu-64.2/source/common/unicode/utf16.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/utf16.h 2019-10-03 11:16:41.000000000 +0000 @@ -163,7 +163,7 @@ * @see U16_GET * @stable ICU 2.4 */ -#define U16_GET_UNSAFE(s, i, c) { \ +#define U16_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(U16_IS_SURROGATE(c)) { \ if(U16_IS_SURROGATE_LEAD(c)) { \ @@ -172,7 +172,7 @@ (c)=U16_GET_SUPPLEMENTARY((s)[(i)-1], (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -197,7 +197,7 @@ * @see U16_GET_UNSAFE * @stable ICU 2.4 */ -#define U16_GET(s, start, i, length, c) { \ +#define U16_GET(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -211,7 +211,7 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -236,7 +236,7 @@ * @see U16_GET_UNSAFE * @stable ICU 60 */ -#define U16_GET_OR_FFFD(s, start, i, length, c) { \ +#define U16_GET_OR_FFFD(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -254,7 +254,7 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /* definitions with forward iteration --------------------------------------- */ @@ -277,12 +277,12 @@ * @see U16_NEXT * @stable ICU 2.4 */ -#define U16_NEXT_UNSAFE(s, i, c) { \ +#define U16_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(U16_IS_LEAD(c)) { \ (c)=U16_GET_SUPPLEMENTARY((c), (s)[(i)++]); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a code point boundary offset, @@ -305,7 +305,7 @@ * @see U16_NEXT_UNSAFE * @stable ICU 2.4 */ -#define U16_NEXT(s, i, length, c) { \ +#define U16_NEXT(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(U16_IS_LEAD(c)) { \ uint16_t __c2; \ @@ -314,7 +314,7 @@ (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a code point boundary offset, @@ -337,7 +337,7 @@ * @see U16_NEXT_UNSAFE * @stable ICU 60 */ -#define U16_NEXT_OR_FFFD(s, i, length, c) { \ +#define U16_NEXT_OR_FFFD(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -348,7 +348,7 @@ (c)=0xfffd; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 or 2 code units. @@ -363,14 +363,14 @@ * @see U16_APPEND * @stable ICU 2.4 */ -#define U16_APPEND_UNSAFE(s, i, c) { \ +#define U16_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else { \ (s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \ (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 or 2 code units. @@ -389,7 +389,7 @@ * @see U16_APPEND_UNSAFE * @stable ICU 2.4 */ -#define U16_APPEND(s, i, capacity, c, isError) { \ +#define U16_APPEND(s, i, capacity, c, isError) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else if((uint32_t)(c)<=0x10ffff && (i)+1<(capacity)) { \ @@ -398,7 +398,7 @@ } else /* c>0x10ffff or not enough space */ { \ (isError)=TRUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -410,11 +410,11 @@ * @see U16_FWD_1 * @stable ICU 2.4 */ -#define U16_FWD_1_UNSAFE(s, i) { \ +#define U16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_LEAD((s)[(i)++])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -429,11 +429,11 @@ * @see U16_FWD_1_UNSAFE * @stable ICU 2.4 */ -#define U16_FWD_1(s, i, length) { \ +#define U16_FWD_1(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_LEAD((s)[(i)++]) && (i)!=(length) && U16_IS_TRAIL((s)[i])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -447,13 +447,13 @@ * @see U16_FWD_N * @stable ICU 2.4 */ -#define U16_FWD_N_UNSAFE(s, i, n) { \ +#define U16_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U16_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -470,13 +470,13 @@ * @see U16_FWD_N_UNSAFE * @stable ICU 2.4 */ -#define U16_FWD_N(s, i, length, n) { \ +#define U16_FWD_N(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \ U16_FWD_1(s, i, length); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -491,11 +491,11 @@ * @see U16_SET_CP_START * @stable ICU 2.4 */ -#define U16_SET_CP_START_UNSAFE(s, i) { \ +#define U16_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[i])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -511,11 +511,11 @@ * @see U16_SET_CP_START_UNSAFE * @stable ICU 2.4 */ -#define U16_SET_CP_START(s, start, i) { \ +#define U16_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[i]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /* definitions with backward iteration -------------------------------------- */ @@ -539,12 +539,12 @@ * @see U16_PREV * @stable ICU 2.4 */ -#define U16_PREV_UNSAFE(s, i, c) { \ +#define U16_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(U16_IS_TRAIL(c)) { \ (c)=U16_GET_SUPPLEMENTARY((s)[--(i)], (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -566,7 +566,7 @@ * @see U16_PREV_UNSAFE * @stable ICU 2.4 */ -#define U16_PREV(s, start, i, c) { \ +#define U16_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(U16_IS_TRAIL(c)) { \ uint16_t __c2; \ @@ -575,7 +575,7 @@ (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -597,7 +597,7 @@ * @see U16_PREV_UNSAFE * @stable ICU 60 */ -#define U16_PREV_OR_FFFD(s, start, i, c) { \ +#define U16_PREV_OR_FFFD(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -608,7 +608,7 @@ (c)=0xfffd; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -621,11 +621,11 @@ * @see U16_BACK_1 * @stable ICU 2.4 */ -#define U16_BACK_1_UNSAFE(s, i) { \ +#define U16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[--(i)])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -639,11 +639,11 @@ * @see U16_BACK_1_UNSAFE * @stable ICU 2.4 */ -#define U16_BACK_1(s, start, i) { \ +#define U16_BACK_1(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[--(i)]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -658,13 +658,13 @@ * @see U16_BACK_N * @stable ICU 2.4 */ -#define U16_BACK_N_UNSAFE(s, i, n) { \ +#define U16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U16_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -680,13 +680,13 @@ * @see U16_BACK_N_UNSAFE * @stable ICU 2.4 */ -#define U16_BACK_N(s, start, i, n) { \ +#define U16_BACK_N(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && (i)>(start)) { \ U16_BACK_1(s, start, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -701,11 +701,11 @@ * @see U16_SET_CP_LIMIT * @stable ICU 2.4 */ -#define U16_SET_CP_LIMIT_UNSAFE(s, i) { \ +#define U16_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_LEAD((s)[(i)-1])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -724,10 +724,10 @@ * @see U16_SET_CP_LIMIT_UNSAFE * @stable ICU 2.4 */ -#define U16_SET_CP_LIMIT(s, start, i, length) { \ +#define U16_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \ if((start)<(i) && ((i)<(length) || (length)<0) && U16_IS_LEAD((s)[(i)-1]) && U16_IS_TRAIL((s)[i])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END #endif diff -Nru icu-64.2/source/common/unicode/utf8.h icu-65.1/source/common/unicode/utf8.h --- icu-64.2/source/common/unicode/utf8.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/utf8.h 2019-10-03 11:16:41.000000000 +0000 @@ -229,11 +229,11 @@ * @see U8_GET * @stable ICU 2.4 */ -#define U8_GET_UNSAFE(s, i, c) { \ +#define U8_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _u8_get_unsafe_index=(int32_t)(i); \ U8_SET_CP_START_UNSAFE(s, _u8_get_unsafe_index); \ U8_NEXT_UNSAFE(s, _u8_get_unsafe_index, c); \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -256,11 +256,11 @@ * @see U8_GET_UNSAFE * @stable ICU 2.4 */ -#define U8_GET(s, start, i, length, c) { \ +#define U8_GET(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _u8_get_index=(i); \ U8_SET_CP_START(s, start, _u8_get_index); \ U8_NEXT(s, _u8_get_index, length, c); \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -287,11 +287,11 @@ * @see U8_GET * @stable ICU 51 */ -#define U8_GET_OR_FFFD(s, start, i, length, c) { \ +#define U8_GET_OR_FFFD(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _u8_get_index=(i); \ U8_SET_CP_START(s, start, _u8_get_index); \ U8_NEXT_OR_FFFD(s, _u8_get_index, length, c); \ -} +} UPRV_BLOCK_MACRO_END /* definitions with forward iteration --------------------------------------- */ @@ -312,7 +312,7 @@ * @see U8_NEXT * @stable ICU 2.4 */ -#define U8_NEXT_UNSAFE(s, i, c) { \ +#define U8_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[(i)++]; \ if(!U8_IS_SINGLE(c)) { \ if((c)<0xe0) { \ @@ -326,7 +326,7 @@ (i)+=3; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a code point boundary offset, @@ -377,7 +377,7 @@ #define U8_NEXT_OR_FFFD(s, i, length, c) U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, 0xfffd) /** @internal */ -#define U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, sub) { \ +#define U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, sub) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[(i)++]; \ if(!U8_IS_SINGLE(c)) { \ uint8_t __t = 0; \ @@ -403,7 +403,7 @@ (c)=(sub); /* ill-formed*/ \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 to 4 bytes. @@ -418,7 +418,7 @@ * @see U8_APPEND * @stable ICU 2.4 */ -#define U8_APPEND_UNSAFE(s, i, c) { \ +#define U8_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ uint32_t __uc=(c); \ if(__uc<=0x7f) { \ (s)[(i)++]=(uint8_t)__uc; \ @@ -436,7 +436,7 @@ } \ (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 to 4 bytes. @@ -455,7 +455,7 @@ * @see U8_APPEND_UNSAFE * @stable ICU 2.4 */ -#define U8_APPEND(s, i, capacity, c, isError) { \ +#define U8_APPEND(s, i, capacity, c, isError) UPRV_BLOCK_MACRO_BEGIN { \ uint32_t __uc=(c); \ if(__uc<=0x7f) { \ (s)[(i)++]=(uint8_t)__uc; \ @@ -474,7 +474,7 @@ } else { \ (isError)=TRUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -486,9 +486,9 @@ * @see U8_FWD_1 * @stable ICU 2.4 */ -#define U8_FWD_1_UNSAFE(s, i) { \ +#define U8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ (i)+=1+U8_COUNT_TRAIL_BYTES_UNSAFE((s)[i]); \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -503,7 +503,7 @@ * @see U8_FWD_1_UNSAFE * @stable ICU 2.4 */ -#define U8_FWD_1(s, i, length) { \ +#define U8_FWD_1(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ uint8_t __b=(s)[(i)++]; \ if(U8_IS_LEAD(__b) && (i)!=(length)) { \ uint8_t __t1=(s)[i]; \ @@ -524,7 +524,7 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -538,13 +538,13 @@ * @see U8_FWD_N * @stable ICU 2.4 */ -#define U8_FWD_N_UNSAFE(s, i, n) { \ +#define U8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U8_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -561,13 +561,13 @@ * @see U8_FWD_N_UNSAFE * @stable ICU 2.4 */ -#define U8_FWD_N(s, i, length, n) { \ +#define U8_FWD_N(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \ U8_FWD_1(s, i, length); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -582,9 +582,9 @@ * @see U8_SET_CP_START * @stable ICU 2.4 */ -#define U8_SET_CP_START_UNSAFE(s, i) { \ +#define U8_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(U8_IS_TRAIL((s)[i])) { --(i); } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -603,11 +603,11 @@ * @see U8_TRUNCATE_IF_INCOMPLETE * @stable ICU 2.4 */ -#define U8_SET_CP_START(s, start, i) { \ +#define U8_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U8_IS_TRAIL((s)[(i)])) { \ (i)=utf8_back1SafeBody(s, start, (i)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * If the string ends with a UTF-8 byte sequence that is valid so far @@ -635,7 +635,7 @@ * @see U8_SET_CP_START * @stable ICU 61 */ -#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) \ +#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) UPRV_BLOCK_MACRO_BEGIN { \ if((length)>(start)) { \ uint8_t __b1=s[(length)-1]; \ if(U8_IS_SINGLE(__b1)) { \ @@ -656,7 +656,8 @@ } \ } \ } \ - } + } \ +} UPRV_BLOCK_MACRO_END /* definitions with backward iteration -------------------------------------- */ @@ -679,7 +680,7 @@ * @see U8_PREV * @stable ICU 2.4 */ -#define U8_PREV_UNSAFE(s, i, c) { \ +#define U8_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if(U8_IS_TRAIL(c)) { \ uint8_t __b, __count=1, __shift=6; \ @@ -699,7 +700,7 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -721,12 +722,12 @@ * @see U8_PREV_UNSAFE * @stable ICU 2.4 */ -#define U8_PREV(s, start, i, c) { \ +#define U8_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if(!U8_IS_SINGLE(c)) { \ (c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -1); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -752,12 +753,12 @@ * @see U8_PREV * @stable ICU 51 */ -#define U8_PREV_OR_FFFD(s, start, i, c) { \ +#define U8_PREV_OR_FFFD(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if(!U8_IS_SINGLE(c)) { \ (c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -3); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -770,9 +771,9 @@ * @see U8_BACK_1 * @stable ICU 2.4 */ -#define U8_BACK_1_UNSAFE(s, i) { \ +#define U8_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(U8_IS_TRAIL((s)[--(i)])) {} \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -786,11 +787,11 @@ * @see U8_BACK_1_UNSAFE * @stable ICU 2.4 */ -#define U8_BACK_1(s, start, i) { \ +#define U8_BACK_1(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U8_IS_TRAIL((s)[--(i)])) { \ (i)=utf8_back1SafeBody(s, start, (i)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -805,13 +806,13 @@ * @see U8_BACK_N * @stable ICU 2.4 */ -#define U8_BACK_N_UNSAFE(s, i, n) { \ +#define U8_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U8_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -827,13 +828,13 @@ * @see U8_BACK_N_UNSAFE * @stable ICU 2.4 */ -#define U8_BACK_N(s, start, i, n) { \ +#define U8_BACK_N(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && (i)>(start)) { \ U8_BACK_1(s, start, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -848,10 +849,10 @@ * @see U8_SET_CP_LIMIT * @stable ICU 2.4 */ -#define U8_SET_CP_LIMIT_UNSAFE(s, i) { \ +#define U8_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ U8_BACK_1_UNSAFE(s, i); \ U8_FWD_1_UNSAFE(s, i); \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -870,11 +871,11 @@ * @see U8_SET_CP_LIMIT_UNSAFE * @stable ICU 2.4 */ -#define U8_SET_CP_LIMIT(s, start, i, length) { \ +#define U8_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \ if((start)<(i) && ((i)<(length) || (length)<0)) { \ U8_BACK_1(s, start, i); \ U8_FWD_1(s, i, length); \ } \ -} +} UPRV_BLOCK_MACRO_END #endif diff -Nru icu-64.2/source/common/unicode/utf_old.h icu-65.1/source/common/unicode/utf_old.h --- icu-64.2/source/common/unicode/utf_old.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/utf_old.h 2019-10-03 11:16:41.000000000 +0000 @@ -19,9 +19,6 @@ /** * \file * \brief C API: Deprecated macros for Unicode string handling - */ - -/** * * The macros in utf_old.h are all deprecated and their use discouraged. * Some of the design principles behind the set of UTF macros @@ -139,12 +136,16 @@ * *


    * - * @deprecated ICU 2.4. Use the macros in utf.h, utf16.h, utf8.h instead. + * Deprecated ICU 2.4. Use the macros in utf.h, utf16.h, utf8.h instead. */ #ifndef __UTF_OLD_H__ #define __UTF_OLD_H__ +#include "unicode/utf.h" +#include "unicode/utf8.h" +#include "unicode/utf16.h" + /** * \def U_HIDE_OBSOLETE_UTF_OLD_H * @@ -162,10 +163,6 @@ #if !defined(U_HIDE_DEPRECATED_API) && !U_HIDE_OBSOLETE_UTF_OLD_H -#include "unicode/utf.h" -#include "unicode/utf8.h" -#include "unicode/utf16.h" - /* Formerly utf.h, part 1 --------------------------------------------------- */ #ifdef U_USE_UTF_DEPRECATES @@ -365,21 +362,21 @@ #define UTF8_ARRAY_SIZE(size) ((5*(size))/2) /** @deprecated ICU 2.4. Renamed to U8_GET_UNSAFE, see utf_old.h. */ -#define UTF8_GET_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _utf8_get_char_unsafe_index=(int32_t)(i); \ UTF8_SET_CHAR_START_UNSAFE(s, _utf8_get_char_unsafe_index); \ UTF8_NEXT_CHAR_UNSAFE(s, _utf8_get_char_unsafe_index, c); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_GET instead, see utf_old.h. */ -#define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) { \ +#define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _utf8_get_char_safe_index=(int32_t)(i); \ UTF8_SET_CHAR_START_SAFE(s, start, _utf8_get_char_safe_index); \ UTF8_NEXT_CHAR_SAFE(s, _utf8_get_char_safe_index, length, c, strict); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_NEXT_UNSAFE, see utf_old.h. */ -#define UTF8_NEXT_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if((uint8_t)((c)-0xc0)<0x35) { \ uint8_t __count=UTF8_COUNT_TRAIL_BYTES(c); \ @@ -396,10 +393,10 @@ break; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_APPEND_UNSAFE, see utf_old.h. */ -#define UTF8_APPEND_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0x7f) { \ (s)[(i)++]=(uint8_t)(c); \ } else { \ @@ -416,29 +413,29 @@ } \ (s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_FWD_1_UNSAFE, see utf_old.h. */ -#define UTF8_FWD_1_UNSAFE(s, i) { \ +#define UTF8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ (i)+=1+UTF8_COUNT_TRAIL_BYTES((s)[i]); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_FWD_N_UNSAFE, see utf_old.h. */ -#define UTF8_FWD_N_UNSAFE(s, i, n) { \ +#define UTF8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF8_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_SET_CP_START_UNSAFE, see utf_old.h. */ -#define UTF8_SET_CHAR_START_UNSAFE(s, i) { \ +#define UTF8_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(UTF8_IS_TRAIL((s)[i])) { --(i); } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_NEXT instead, see utf_old.h. */ -#define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) { \ +#define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if((c)>=0x80) { \ if(UTF8_IS_LEAD(c)) { \ @@ -447,16 +444,16 @@ (c)=UTF8_ERROR_VALUE_1; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_APPEND instead, see utf_old.h. */ -#define UTF8_APPEND_CHAR_SAFE(s, i, length, c) { \ +#define UTF8_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0x7f) { \ (s)[(i)++]=(uint8_t)(c); \ } else { \ (i)=utf8_appendCharSafeBody(s, (int32_t)(i), (int32_t)(length), c, NULL); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_FWD_1, see utf_old.h. */ #define UTF8_FWD_1_SAFE(s, i, length) U8_FWD_1(s, i, length) @@ -468,7 +465,7 @@ #define UTF8_SET_CHAR_START_SAFE(s, start, i) U8_SET_CP_START(s, start, i) /** @deprecated ICU 2.4. Renamed to U8_PREV_UNSAFE, see utf_old.h. */ -#define UTF8_PREV_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(UTF8_IS_TRAIL(c)) { \ uint8_t __b, __count=1, __shift=6; \ @@ -488,30 +485,30 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_BACK_1_UNSAFE, see utf_old.h. */ -#define UTF8_BACK_1_UNSAFE(s, i) { \ +#define UTF8_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(UTF8_IS_TRAIL((s)[--(i)])) {} \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_BACK_N_UNSAFE, see utf_old.h. */ -#define UTF8_BACK_N_UNSAFE(s, i, n) { \ +#define UTF8_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF8_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_SET_CP_LIMIT_UNSAFE, see utf_old.h. */ -#define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) { \ +#define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ UTF8_BACK_1_UNSAFE(s, i); \ UTF8_FWD_1_UNSAFE(s, i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_PREV instead, see utf_old.h. */ -#define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) { \ +#define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if((c)>=0x80) { \ if((c)<=0xbf) { \ @@ -520,7 +517,7 @@ (c)=UTF8_ERROR_VALUE_1; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_BACK_1, see utf_old.h. */ #define UTF8_BACK_1_SAFE(s, start, i) U8_BACK_1(s, start, i) @@ -593,7 +590,7 @@ * UTF16_PREV_CHAR[_UNSAFE]() is more efficient for that. * @deprecated ICU 2.4. Renamed to U16_GET_UNSAFE, see utf_old.h. */ -#define UTF16_GET_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(UTF_IS_SURROGATE(c)) { \ if(UTF_IS_SURROGATE_FIRST(c)) { \ @@ -602,10 +599,10 @@ (c)=UTF16_GET_PAIR_VALUE((s)[(i)-1], (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_GET instead, see utf_old.h. */ -#define UTF16_GET_CHAR_SAFE(s, start, i, length, c, strict) { \ +#define UTF16_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(UTF_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -629,51 +626,51 @@ } else if((strict) && !UTF_IS_UNICODE_CHAR(c)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_NEXT_UNSAFE, see utf_old.h. */ -#define UTF16_NEXT_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(UTF_IS_FIRST_SURROGATE(c)) { \ (c)=UTF16_GET_PAIR_VALUE((c), (s)[(i)++]); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_APPEND_UNSAFE, see utf_old.h. */ -#define UTF16_APPEND_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else { \ (s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \ (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_FWD_1_UNSAFE, see utf_old.h. */ -#define UTF16_FWD_1_UNSAFE(s, i) { \ +#define UTF16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_FIRST_SURROGATE((s)[(i)++])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_FWD_N_UNSAFE, see utf_old.h. */ -#define UTF16_FWD_N_UNSAFE(s, i, n) { \ +#define UTF16_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF16_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_SET_CP_START_UNSAFE, see utf_old.h. */ -#define UTF16_SET_CHAR_START_UNSAFE(s, i) { \ +#define UTF16_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_SECOND_SURROGATE((s)[i])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_NEXT instead, see utf_old.h. */ -#define UTF16_NEXT_CHAR_SAFE(s, i, length, c, strict) { \ +#define UTF16_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(UTF_IS_FIRST_SURROGATE(c)) { \ uint16_t __c2; \ @@ -689,10 +686,10 @@ /* unmatched second surrogate or other non-character */ \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_APPEND instead, see utf_old.h. */ -#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) { \ +#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else if((uint32_t)(c)<=0x10ffff) { \ @@ -705,7 +702,7 @@ } else /* c>0x10ffff, write error value */ { \ (s)[(i)++]=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_FWD_1, see utf_old.h. */ #define UTF16_FWD_1_SAFE(s, i, length) U16_FWD_1(s, i, length) @@ -717,38 +714,38 @@ #define UTF16_SET_CHAR_START_SAFE(s, start, i) U16_SET_CP_START(s, start, i) /** @deprecated ICU 2.4. Renamed to U16_PREV_UNSAFE, see utf_old.h. */ -#define UTF16_PREV_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(UTF_IS_SECOND_SURROGATE(c)) { \ (c)=UTF16_GET_PAIR_VALUE((s)[--(i)], (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_BACK_1_UNSAFE, see utf_old.h. */ -#define UTF16_BACK_1_UNSAFE(s, i) { \ +#define UTF16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_SECOND_SURROGATE((s)[--(i)])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_BACK_N_UNSAFE, see utf_old.h. */ -#define UTF16_BACK_N_UNSAFE(s, i, n) { \ +#define UTF16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF16_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_SET_CP_LIMIT_UNSAFE, see utf_old.h. */ -#define UTF16_SET_CHAR_LIMIT_UNSAFE(s, i) { \ +#define UTF16_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_FIRST_SURROGATE((s)[(i)-1])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_PREV instead, see utf_old.h. */ -#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) { \ +#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(UTF_IS_SECOND_SURROGATE(c)) { \ uint16_t __c2; \ @@ -764,7 +761,7 @@ /* unmatched first surrogate or other non-character */ \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_BACK_1, see utf_old.h. */ #define UTF16_BACK_1_SAFE(s, start, i) U16_BACK_1(s, start, i) @@ -830,122 +827,122 @@ #define UTF32_ARRAY_SIZE(size) (size) /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_GET_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_GET_CHAR_SAFE(s, start, i, length, c, strict) { \ +#define UTF32_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(!UTF32_IS_SAFE(c, strict)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /* definitions with forward iteration --------------------------------------- */ /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_NEXT_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_APPEND_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (s)[(i)++]=(c); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_1_UNSAFE(s, i) { \ +#define UTF32_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ ++(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_N_UNSAFE(s, i, n) { \ +#define UTF32_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ (i)+=(n); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_START_UNSAFE(s, i) { \ -} +#define UTF32_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_NEXT_CHAR_SAFE(s, i, length, c, strict) { \ +#define UTF32_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(!UTF32_IS_SAFE(c, strict)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_APPEND_CHAR_SAFE(s, i, length, c) { \ +#define UTF32_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0x10ffff) { \ (s)[(i)++]=(c); \ } else /* c>0x10ffff, write 0xfffd */ { \ (s)[(i)++]=0xfffd; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_1_SAFE(s, i, length) { \ +#define UTF32_FWD_1_SAFE(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ ++(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_N_SAFE(s, i, length, n) { \ +#define UTF32_FWD_N_SAFE(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \ if(((i)+=(n))>(length)) { \ (i)=(length); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_START_SAFE(s, start, i) { \ -} +#define UTF32_SET_CHAR_START_SAFE(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /* definitions with backward iteration -------------------------------------- */ /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_PREV_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_1_UNSAFE(s, i) { \ +#define UTF32_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ --(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_N_UNSAFE(s, i, n) { \ +#define UTF32_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ (i)-=(n); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_LIMIT_UNSAFE(s, i) { \ -} +#define UTF32_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_PREV_CHAR_SAFE(s, start, i, c, strict) { \ +#define UTF32_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(!UTF32_IS_SAFE(c, strict)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_1_SAFE(s, start, i) { \ +#define UTF32_BACK_1_SAFE(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ --(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_N_SAFE(s, start, i, n) { \ +#define UTF32_BACK_N_SAFE(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \ (i)-=(n); \ if((i)<(start)) { \ (i)=(start); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_LIMIT_SAFE(s, i, length) { \ -} +#define UTF32_SET_CHAR_LIMIT_SAFE(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /* Formerly utf.h, part 2 --------------------------------------------------- */ diff -Nru icu-64.2/source/common/unicode/utrace.h icu-65.1/source/common/unicode/utrace.h --- icu-64.2/source/common/unicode/utrace.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/utrace.h 2019-10-03 11:16:41.000000000 +0000 @@ -66,6 +66,7 @@ UTRACE_FUNCTION_START=0, UTRACE_U_INIT=UTRACE_FUNCTION_START, UTRACE_U_CLEANUP, + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal collation trace location. @@ -83,6 +84,7 @@ UTRACE_UCNV_FLUSH_CACHE, UTRACE_UCNV_LOAD, UTRACE_UCNV_UNLOAD, + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal collation trace location. @@ -101,13 +103,80 @@ UTRACE_UCOL_STRCOLLITER, UTRACE_UCOL_OPEN_FROM_SHORT_STRING, UTRACE_UCOL_STRCOLLUTF8, /**< @stable ICU 50 */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal collation trace location. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UTRACE_COLLATION_LIMIT + UTRACE_COLLATION_LIMIT, #endif // U_HIDE_DEPRECATED_API + +#ifndef U_HIDE_DRAFT_API + + /** + * The lowest resource/data location. + * @draft ICU 65 + */ + UTRACE_UDATA_START=0x3000, + + /** + * Indicates that a value was read from a resource bundle. Provides three + * C-style strings to UTraceData: type, file name, and resource path. The + * possible types are: + * + * - "string" (a string value was accessed) + * - "binary" (a binary value was accessed) + * - "intvector" (a integer vector value was accessed) + * - "int" (a signed integer value was accessed) + * - "uint" (a unsigned integer value was accessed) + * - "get" (a path was loaded, but the value was not accessed) + * - "getalias" (a path was loaded, and an alias was resolved) + * + * @draft ICU 65 + */ + UTRACE_UDATA_RESOURCE=UTRACE_UDATA_START, + + /** + * Indicates that a resource bundle was opened. + * + * Provides one C-style string to UTraceData: file name. + * @draft ICU 65 + */ + UTRACE_UDATA_BUNDLE, + + /** + * Indicates that a data file was opened, but not *.res files. + * + * Provides one C-style string to UTraceData: file name. + * + * @draft ICU 65 + */ + UTRACE_UDATA_DATA_FILE, + + /** + * Indicates that a *.res file was opened. + * + * This differs from UTRACE_UDATA_BUNDLE because a res file is typically + * opened only once per application runtime, but the bundle corresponding + * to that res file may be opened many times. + * + * Provides one C-style string to UTraceData: file name. + * + * @draft ICU 65 + */ + UTRACE_UDATA_RES_FILE, + +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API + /** + * One more than the highest normal resource/data trace location. + * @internal The numeric value may change over time, see ICU ticket #12420. + */ + UTRACE_RES_DATA_LIMIT, +#endif // U_HIDE_INTERNAL_API + } UTraceFunctionNumber; /** diff -Nru icu-64.2/source/common/unicode/utypes.h icu-65.1/source/common/unicode/utypes.h --- icu-64.2/source/common/unicode/utypes.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/utypes.h 2019-10-03 11:16:41.000000000 +0000 @@ -385,17 +385,31 @@ /*===========================================================================*/ /** - * Error code to replace exception handling, so that the code is compatible with all C++ compilers, - * and to use the same mechanism for C and C++. + * Standard ICU4C error code type, a substitute for exceptions. + * + * Initialize the UErrorCode with U_ZERO_ERROR, and check for success or + * failure using U_SUCCESS() or U_FAILURE(): + * + * UErrorCode errorCode = U_ZERO_ERROR; + * // call ICU API that needs an error code parameter. + * if (U_FAILURE(errorCode)) { + * // An error occurred. Handle it here. + * } + * + * C++ code should use icu::ErrorCode, available in unicode/errorcode.h, or a + * suitable subclass. + * + * For more information, see: + * http://icu-project.org/userguide/conventions + * + * Note: By convention, ICU functions that take a reference (C++) or a pointer + * (C) to a UErrorCode first test: + * + * if (U_FAILURE(errorCode)) { return immediately; } * - * \par - * ICU functions that take a reference (C++) or a pointer (C) to a UErrorCode - * first test if(U_FAILURE(errorCode)) { return immediately; } * so that in a chain of such functions the first one that sets an error code * causes the following ones to not perform any operations. * - * \par - * Error codes should be tested using U_FAILURE() and U_SUCCESS(). * @stable ICU 2.0 */ typedef enum UErrorCode { diff -Nru icu-64.2/source/common/unicode/uvernum.h icu-65.1/source/common/unicode/uvernum.h --- icu-64.2/source/common/unicode/uvernum.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uvernum.h 2019-10-03 11:16:41.000000000 +0000 @@ -60,13 +60,13 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 64 +#define U_ICU_VERSION_MAJOR_NUM 65 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_MINOR_NUM 2 +#define U_ICU_VERSION_MINOR_NUM 1 /** The current ICU patchlevel version as an integer. * This value will change in the subsequent releases of ICU @@ -86,7 +86,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _64 +#define U_ICU_VERSION_SUFFIX _65 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -139,7 +139,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "64.2" +#define U_ICU_VERSION "65.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -152,13 +152,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "64" +#define U_ICU_VERSION_SHORT "65" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "64.2" +#define U_ICU_DATA_VERSION "65.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff -Nru icu-64.2/source/common/unicode/uversion.h icu-65.1/source/common/unicode/uversion.h --- icu-64.2/source/common/unicode/uversion.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unicode/uversion.h 2019-10-03 11:16:41.000000000 +0000 @@ -62,26 +62,22 @@ /* C++ namespace if supported. Versioned unless versioning is disabled. */ /*===========================================================================*/ +/* Define C++ namespace symbols. */ +#ifdef __cplusplus + /** * \def U_NAMESPACE_BEGIN - * This is used to begin a declaration of a public ICU C++ API. - * When not compiling for C++, it does nothing. - * When compiling for C++, it begins an extern "C++" linkage block (to protect - * against cases in which an external client includes ICU header files inside - * an extern "C" linkage block). + * This is used to begin a declaration of a public ICU C++ API within + * versioned-ICU-namespace block. * - * It also begins a versioned-ICU-namespace block. * @stable ICU 2.4 */ /** * \def U_NAMESPACE_END * This is used to end a declaration of a public ICU C++ API. - * When not compiling for C++, it does nothing. - * When compiling for C++, it ends the extern "C++" block begun by - * U_NAMESPACE_BEGIN. + * It ends the versioned-ICU-namespace block begun by U_NAMESPACE_BEGIN. * - * It also ends the versioned-ICU-namespace block begun by U_NAMESPACE_BEGIN. * @stable ICU 2.4 */ @@ -89,9 +85,6 @@ * \def U_NAMESPACE_USE * This is used to specify that the rest of the code uses the * public ICU C++ API namespace. - * This is invoked by default; we recommend that you turn it off: - * See the "Recommended Build Options" section of the ICU4C readme - * (http://source.icu-project.org/repos/icu/icu/trunk/readme.html#RecBuild) * @stable ICU 2.4 */ @@ -105,8 +98,6 @@ * @stable ICU 2.4 */ -/* Define C++ namespace symbols. */ -#ifdef __cplusplus # if U_DISABLE_RENAMING # define U_ICU_NAMESPACE icu namespace U_ICU_NAMESPACE { } @@ -116,8 +107,8 @@ namespace icu = U_ICU_NAMESPACE; # endif -# define U_NAMESPACE_BEGIN extern "C++" { namespace U_ICU_NAMESPACE { -# define U_NAMESPACE_END } } +# define U_NAMESPACE_BEGIN namespace U_ICU_NAMESPACE { +# define U_NAMESPACE_END } # define U_NAMESPACE_USE using namespace U_ICU_NAMESPACE; # define U_NAMESPACE_QUALIFIER U_ICU_NAMESPACE:: @@ -133,12 +124,7 @@ # if U_USING_ICU_NAMESPACE U_NAMESPACE_USE # endif -#else -# define U_NAMESPACE_BEGIN -# define U_NAMESPACE_END -# define U_NAMESPACE_USE -# define U_NAMESPACE_QUALIFIER -#endif +#endif /* __cplusplus */ /*===========================================================================*/ /* General version helper functions. Definitions in putil.c */ diff -Nru icu-64.2/source/common/unifiedcache.cpp icu-65.1/source/common/unifiedcache.cpp --- icu-64.2/source/common/unifiedcache.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unifiedcache.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -13,22 +13,15 @@ #include "unifiedcache.h" #include // For std::max() +#include -#include "mutex.h" #include "uassert.h" #include "uhash.h" #include "ucln_cmn.h" -#include "umutex.h" static icu::UnifiedCache *gCache = NULL; -static icu::UMutex *gCacheMutex() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} -static icu::UConditionVar *gInProgressValueAddedCond() { - static icu::UConditionVar cv = U_CONDITION_INITIALIZER; - return &cv; -} +static std::mutex *gCacheMutex = nullptr; +static std::condition_variable *gInProgressValueAddedCond; static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; static const int32_t MAX_EVICT_ITERATIONS = 10; @@ -39,10 +32,12 @@ U_CDECL_BEGIN static UBool U_CALLCONV unifiedcache_cleanup() { gCacheInitOnce.reset(); - if (gCache) { - delete gCache; - gCache = NULL; - } + delete gCache; + gCache = nullptr; + gCacheMutex->~mutex(); + gCacheMutex = nullptr; + gInProgressValueAddedCond->~condition_variable(); + gInProgressValueAddedCond = nullptr; return TRUE; } U_CDECL_END @@ -77,6 +72,8 @@ ucln_common_registerCleanup( UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup); + gCacheMutex = STATIC_NEW(std::mutex); + gInProgressValueAddedCond = STATIC_NEW(std::condition_variable); gCache = new UnifiedCache(status); if (gCache == NULL) { status = U_MEMORY_ALLOCATION_ERROR; @@ -138,28 +135,28 @@ status = U_ILLEGAL_ARGUMENT_ERROR; return; } - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); fMaxUnused = count; fMaxPercentageOfInUse = percentageOfInUseItems; } int32_t UnifiedCache::unusedCount() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); return uhash_count(fHashtable) - fNumValuesInUse; } int64_t UnifiedCache::autoEvictedCount() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); return fAutoEvictedCount; } int32_t UnifiedCache::keyCount() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); return uhash_count(fHashtable); } void UnifiedCache::flush() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); // Use a loop in case cache items that are flushed held hard references to // other cache items making those additional cache items eligible for @@ -168,7 +165,7 @@ } void UnifiedCache::handleUnreferencedObject() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); --fNumValuesInUse; _runEvictionSlice(); } @@ -187,7 +184,7 @@ } void UnifiedCache::dumpContents() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); _dumpContents(); } @@ -227,7 +224,7 @@ // Now all that should be left in the cache are entries that refer to // each other and entries with hard references from outside the cache. // Nothing we can do about these so proceed to wipe out the cache. - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); _flush(TRUE); } uhash_close(fHashtable); @@ -328,7 +325,7 @@ const CacheKeyBase &key, const SharedObject *&value, UErrorCode &status) const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); const UHashElement *element = uhash_find(fHashtable, &key); if (element != NULL && !_inProgress(element)) { _fetch(element, value, status); @@ -353,15 +350,15 @@ UErrorCode &status) const { U_ASSERT(value == NULL); U_ASSERT(status == U_ZERO_ERROR); - Mutex lock(gCacheMutex()); + std::unique_lock lock(*gCacheMutex); const UHashElement *element = uhash_find(fHashtable, &key); // If the hash table contains an inProgress placeholder entry for this key, // this means that another thread is currently constructing the value object. // Loop, waiting for that construction to complete. while (element != NULL && _inProgress(element)) { - umtx_condWait(gInProgressValueAddedCond(), gCacheMutex()); - element = uhash_find(fHashtable, &key); + gInProgressValueAddedCond->wait(lock); + element = uhash_find(fHashtable, &key); } // If the hash table contains an entry for the key, @@ -433,7 +430,7 @@ // Tell waiting threads that we replace in-progress status with // an error. - umtx_condBroadcast(gInProgressValueAddedCond()); + gInProgressValueAddedCond->notify_all(); } void UnifiedCache::_fetch( diff -Nru icu-64.2/source/common/uniset.cpp icu-65.1/source/common/uniset.cpp --- icu-64.2/source/common/uniset.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uniset.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -278,11 +278,11 @@ * to support cloning in order to allow classes using * UnicodeMatchers, such as Transliterator, to implement cloning. */ -UnicodeFunctor* UnicodeSet::clone() const { +UnicodeSet* UnicodeSet::clone() const { return new UnicodeSet(*this); } -UnicodeFunctor *UnicodeSet::cloneAsThawed() const { +UnicodeSet *UnicodeSet::cloneAsThawed() const { return new UnicodeSet(*this, TRUE); } @@ -2172,7 +2172,7 @@ // We can regenerate an equivalent pattern later when requested. } -UnicodeFunctor *UnicodeSet::freeze() { +UnicodeSet *UnicodeSet::freeze() { if(!isFrozen() && !isBogus()) { compact(); diff -Nru icu-64.2/source/common/uniset_props.cpp icu-65.1/source/common/uniset_props.cpp --- icu-64.2/source/common/uniset_props.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uniset_props.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -802,7 +802,10 @@ // Property set API //---------------------------------------------------------------- -#define FAIL(ec) {ec=U_ILLEGAL_ARGUMENT_ERROR; return *this;} +#define FAIL(ec) UPRV_BLOCK_MACRO_BEGIN { \ + ec=U_ILLEGAL_ARGUMENT_ERROR; \ + return *this; \ +} UPRV_BLOCK_MACRO_END UnicodeSet& UnicodeSet::applyIntPropertyValue(UProperty prop, int32_t value, UErrorCode& ec) { diff -Nru icu-64.2/source/common/unisetspan.cpp icu-65.1/source/common/unisetspan.cpp --- icu-64.2/source/common/unisetspan.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unisetspan.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -400,7 +400,7 @@ if(otherStringSpan.pSpanNotSet==&otherStringSpan.spanSet) { pSpanNotSet=&spanSet; } else { - pSpanNotSet=(UnicodeSet *)otherStringSpan.pSpanNotSet->clone(); + pSpanNotSet=otherStringSpan.pSpanNotSet->clone(); } // Allocate a block of meta data. @@ -436,7 +436,7 @@ if(spanSet.contains(c)) { return; // Nothing to do. } - UnicodeSet *newSet=(UnicodeSet *)spanSet.cloneAsThawed(); + UnicodeSet *newSet=spanSet.cloneAsThawed(); if(newSet==NULL) { return; // Out of memory. } else { diff -Nru icu-64.2/source/common/unistr.cpp icu-65.1/source/common/unistr.cpp --- icu-64.2/source/common/unistr.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/unistr.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -332,7 +332,7 @@ } // UnicodeString overrides clone() with a real implementation -Replaceable * +UnicodeString * UnicodeString::clone() const { return new UnicodeString(*this); } diff -Nru icu-64.2/source/common/uresbund.cpp icu-65.1/source/common/uresbund.cpp --- icu-64.2/source/common/uresbund.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uresbund.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -31,6 +31,7 @@ #include "ucln_cmn.h" #include "cmemory.h" #include "cstring.h" +#include "mutex.h" #include "uhash.h" #include "unicode/uenum.h" #include "uenumimp.h" @@ -38,6 +39,7 @@ #include "umutex.h" #include "putilimp.h" #include "uassert.h" +#include "uresdata.h" using namespace icu; @@ -47,12 +49,9 @@ completely removed. */ static UHashtable *cache = NULL; -static icu::UInitOnce gCacheInitOnce; +static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; -static UMutex *resbMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex resbMutex; /* INTERNAL: hashes an entry */ static int32_t U_CALLCONV hashEntry(const UHashTok parm) { @@ -96,13 +95,12 @@ * Internal function */ static void entryIncrease(UResourceDataEntry *entry) { - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); entry->fCountExisting++; while(entry->fParent != NULL) { entry = entry->fParent; entry->fCountExisting++; } - umtx_unlock(resbMutex()); } /** @@ -184,9 +182,8 @@ /*if shared data hasn't even been lazy evaluated yet * return 0 */ - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); if (cache == NULL) { - umtx_unlock(resbMutex()); return 0; } @@ -218,7 +215,6 @@ * got decremented by free_entry(). */ } while(deletedMore); - umtx_unlock(resbMutex()); return rbDeletedNum; } @@ -232,9 +228,8 @@ const UHashElement *e; UResourceDataEntry *resB; - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); if (cache == NULL) { - umtx_unlock(resbMutex()); fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__); return FALSE; } @@ -253,9 +248,6 @@ } fprintf(stderr,"%s:%d: RB Cache still contains %d items.\n", __FILE__, __LINE__, uhash_count(cache)); - - umtx_unlock(resbMutex()); - return cacheNotEmpty; } @@ -401,7 +393,8 @@ /* We'll try to get alias string from the bundle */ aliasres = res_getResource(&(r->fData), "%%ALIAS"); if (aliasres != RES_BOGUS) { - const UChar *alias = res_getString(&(r->fData), aliasres, &aliasLen); + // No tracing: called during initial data loading + const UChar *alias = res_getStringNoTrace(&(r->fData), aliasres, &aliasLen); if(alias != NULL && aliasLen > 0) { /* if there is actual alias - unload and load new data */ u_UCharsToChars(alias, aliasName, aliasLen+1); r->fAlias = init_entry(aliasName, path, status); @@ -542,7 +535,8 @@ Resource parentRes = res_getResource(&t1->fData, "%%Parent"); if (parentRes != RES_BOGUS) { // An explicit parent was found. int32_t parentLocaleLen = 0; - const UChar *parentLocaleName = res_getString(&(t1->fData), parentRes, &parentLocaleLen); + // No tracing: called during initial data loading + const UChar *parentLocaleName = res_getStringNoTrace(&(t1->fData), parentRes, &parentLocaleLen); if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLen < nameCapacity) { u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1); if (uprv_strcmp(name, kRootLocaleName) == 0) { @@ -666,107 +660,105 @@ } } - umtx_lock(resbMutex()); - { /* umtx_lock */ - /* We're going to skip all the locales that do not have any data */ - r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + Mutex lock(&resbMutex); // Lock resbMutex until the end of this function. + + /* We're going to skip all the locales that do not have any data */ + r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finish; + } + + if(r != NULL) { /* if there is one real locale, we can look for parents. */ + t1 = r; + hasRealData = TRUE; + if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */ + UErrorCode usrStatus = U_ZERO_ERROR; + UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finish; + } + if ( u1 != NULL ) { + if(u1->fBogus == U_ZERO_ERROR) { + u1->fParent = t1; + r = u1; + } else { + /* the USR override data wasn't found, set it to be deleted */ + u1->fCountExisting = 0; + } + } + } + if (hasChopped && !isRoot) { + if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { + goto finish; + } + } + } + + /* we could have reached this point without having any real data */ + /* if that is the case, we need to chain in the default locale */ + if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) { + /* insert default locale */ + uprv_strcpy(name, uloc_getDefault()); + r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); // If we failed due to out-of-memory, report the failure and exit early. if (intStatus == U_MEMORY_ALLOCATION_ERROR) { *status = intStatus; - goto finishUnlock; + goto finish; } - - if(r != NULL) { /* if there is one real locale, we can look for parents. */ + intStatus = U_USING_DEFAULT_WARNING; + if(r != NULL) { /* the default locale exists */ t1 = r; hasRealData = TRUE; - if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */ - UErrorCode usrStatus = U_ZERO_ERROR; - UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus); - // If we failed due to out-of-memory, report the failure and exit early. - if (intStatus == U_MEMORY_ALLOCATION_ERROR) { - *status = intStatus; - goto finishUnlock; - } - if ( u1 != NULL ) { - if(u1->fBogus == U_ZERO_ERROR) { - u1->fParent = t1; - r = u1; - } else { - /* the USR override data wasn't found, set it to be deleted */ - u1->fCountExisting = 0; - } - } - } + isDefault = TRUE; + // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path? if (hasChopped && !isRoot) { if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { - goto finishUnlock; + goto finish; } } } + } - /* we could have reached this point without having any real data */ - /* if that is the case, we need to chain in the default locale */ - if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) { - /* insert default locale */ - uprv_strcpy(name, uloc_getDefault()); - r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); - // If we failed due to out-of-memory, report the failure and exit early. - if (intStatus == U_MEMORY_ALLOCATION_ERROR) { - *status = intStatus; - goto finishUnlock; - } + /* we could still have r == NULL at this point - maybe even default locale is not */ + /* present */ + if(r == NULL) { + uprv_strcpy(name, kRootLocaleName); + r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finish; + } + if(r != NULL) { + t1 = r; intStatus = U_USING_DEFAULT_WARNING; - if(r != NULL) { /* the default locale exists */ - t1 = r; - hasRealData = TRUE; - isDefault = TRUE; - // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path? - if (hasChopped && !isRoot) { - if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { - goto finishUnlock; - } - } - } + hasRealData = TRUE; + } else { /* we don't even have the root locale */ + *status = U_MISSING_RESOURCE_ERROR; + goto finish; } - - /* we could still have r == NULL at this point - maybe even default locale is not */ - /* present */ - if(r == NULL) { - uprv_strcpy(name, kRootLocaleName); - r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); - // If we failed due to out-of-memory, report the failure and exit early. - if (intStatus == U_MEMORY_ALLOCATION_ERROR) { - *status = intStatus; - goto finishUnlock; - } - if(r != NULL) { - t1 = r; - intStatus = U_USING_DEFAULT_WARNING; - hasRealData = TRUE; - } else { /* we don't even have the root locale */ - *status = U_MISSING_RESOURCE_ERROR; - goto finishUnlock; - } - } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && - t1->fParent == NULL && !r->fData.noFallback) { - if (!insertRootBundle(t1, status)) { - goto finishUnlock; - } - if(!hasRealData) { - r->fBogus = U_USING_DEFAULT_WARNING; - } + } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && + t1->fParent == NULL && !r->fData.noFallback) { + if (!insertRootBundle(t1, status)) { + goto finish; } - - // TODO: Does this ever loop? - while(r != NULL && !isRoot && t1->fParent != NULL) { - t1->fParent->fCountExisting++; - t1 = t1->fParent; + if(!hasRealData) { + r->fBogus = U_USING_DEFAULT_WARNING; } - } /* umtx_lock */ -finishUnlock: - umtx_unlock(resbMutex()); + } + + // TODO: Does this ever loop? + while(r != NULL && !isRoot && t1->fParent != NULL) { + t1->fParent->fCountExisting++; + t1 = t1->fParent; + } +finish: if(U_SUCCESS(*status)) { if(intStatus != U_ZERO_ERROR) { *status = intStatus; @@ -790,7 +782,7 @@ return NULL; } - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); // findFirstExisting() without fallbacks. UResourceDataEntry *r = init_entry(localeID, path, status); if(U_SUCCESS(*status)) { @@ -828,7 +820,6 @@ t1 = t1->fParent; } } - umtx_unlock(resbMutex()); return r; } @@ -871,9 +862,8 @@ */ static void entryClose(UResourceDataEntry *resB) { - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); entryCloseInt(resB); - umtx_unlock(resbMutex()); } /* @@ -1177,6 +1167,7 @@ if(mainRes != result) { ures_close(mainRes); } + ResourceTracer(resB).maybeTrace("getalias"); return result; } } else { @@ -1256,6 +1247,7 @@ /*resB->fParent = parent->fRes;*/ uprv_memmove(&resB->fResData, rdata, sizeof(ResourceData)); resB->fSize = res_countArrayItems(&(resB->fResData), resB->fRes); + ResourceTracer(resB).trace("get"); return resB; } @@ -1304,7 +1296,7 @@ *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - s = res_getString(&(resB->fResData), resB->fRes, len); + s = res_getString({resB}, &(resB->fResData), resB->fRes, len); if (s == NULL) { *status = U_RESOURCE_TYPE_MISMATCH; } @@ -1393,7 +1385,7 @@ *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - p = res_getBinary(&(resB->fResData), resB->fRes, len); + p = res_getBinary({resB}, &(resB->fResData), resB->fRes, len); if (p == NULL) { *status = U_RESOURCE_TYPE_MISMATCH; } @@ -1410,7 +1402,7 @@ *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - p = res_getIntVector(&(resB->fResData), resB->fRes, len); + p = res_getIntVector({resB}, &(resB->fResData), resB->fRes, len); if (p == NULL) { *status = U_RESOURCE_TYPE_MISMATCH; } @@ -1431,7 +1423,7 @@ *status = U_RESOURCE_TYPE_MISMATCH; return 0xffffffff; } - return RES_GET_INT(resB->fRes); + return res_getInt({resB}, resB->fRes); } U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *status) { @@ -1446,7 +1438,7 @@ *status = U_RESOURCE_TYPE_MISMATCH; return 0xffffffff; } - return RES_GET_UINT(resB->fRes); + return res_getUInt({resB}, resB->fRes); } U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) { @@ -1457,10 +1449,18 @@ } U_CAPI const char * U_EXPORT2 ures_getKey(const UResourceBundle *resB) { + // + // TODO: Trace ures_getKey? I guess not usually. + // + // We usually get the key string to decide whether we want the value, or to + // make a key-value pair. Tracing the value should suffice. + // + // However, I believe we have some data (e.g., in res_index) where the key + // strings are the data. Tracing the enclosing table should suffice. + // if(resB == NULL) { return NULL; } - return(resB->fKey); } @@ -1480,7 +1480,7 @@ ures_close(tempRes); return result; } else { - return res_getString(&(resB->fResData), r, len); + return res_getString({resB, sIndex}, &(resB->fResData), r, len); } } @@ -1516,7 +1516,7 @@ switch(RES_GET_TYPE(resB->fRes)) { case URES_STRING: case URES_STRING_V2: - return res_getString(&(resB->fResData), resB->fRes, len); + return res_getString({resB}, &(resB->fResData), resB->fRes, len); case URES_TABLE: case URES_TABLE16: case URES_TABLE32: @@ -1661,7 +1661,7 @@ switch(RES_GET_TYPE(resB->fRes)) { case URES_STRING: case URES_STRING_V2: - return res_getString(&(resB->fResData), resB->fRes, len); + return res_getString({resB}, &(resB->fResData), resB->fRes, len); case URES_TABLE: case URES_TABLE16: case URES_TABLE32: @@ -1953,10 +1953,10 @@ // When the sink sees the no-fallback/no-inheritance marker, // then it would remove the parent's item. // We would deserialize parent values even though they are overridden in a child bundle. - value.pResData = &bundle->fResData; + value.setData(&bundle->fResData); UResourceDataEntry *parentEntry = bundle->fData->fParent; UBool hasParent = parentEntry != NULL && U_SUCCESS(parentEntry->fBogus); - value.setResource(bundle->fRes); + value.setResource(bundle->fRes, ResourceTracer(bundle)); sink.put(bundle->fKey, value, !hasParent, errorCode); if (hasParent) { // We might try to query the sink whether @@ -2001,31 +2001,60 @@ } // namespace +// Requires a ResourceDataValue fill-in, so that we need not cast from a ResourceValue. +// Unfortunately, the caller must know which subclass to make and pass in. +// Alternatively, we could make it as polymorphic as in Java by +// returning a ResourceValue pointer (possibly wrapped into a LocalPointer) +// that the caller then owns. +// +// Also requires a UResourceBundle fill-in, so that the value's ResourceTracer +// can point to a non-local bundle. +// Without tracing, the child bundle could be a function-local object. +U_CAPI void U_EXPORT2 +ures_getValueWithFallback(const UResourceBundle *bundle, const char *path, + UResourceBundle *tempFillIn, + ResourceDataValue &value, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + if (path == nullptr) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + const UResourceBundle *rb; + if (*path == 0) { + // empty path + rb = bundle; + } else { + rb = ures_getByKeyWithFallback(bundle, path, tempFillIn, &errorCode); + if (U_FAILURE(errorCode)) { + return; + } + } + value.setData(&rb->fResData); + value.setResource(rb->fRes, ResourceTracer(rb)); +} + U_CAPI void U_EXPORT2 ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path, icu::ResourceSink &sink, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; } - if (path == NULL) { + if (path == nullptr) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } - UResourceBundle stackBundle; - ures_initStackObject(&stackBundle); + StackUResourceBundle stackBundle; const UResourceBundle *rb; if (*path == 0) { // empty path rb = bundle; } else { - rb = ures_getByKeyWithFallback(bundle, path, &stackBundle, &errorCode); + rb = ures_getByKeyWithFallback(bundle, path, stackBundle.getAlias(), &errorCode); if (U_FAILURE(errorCode)) { - ures_close(&stackBundle); return; } } // Get all table items with fallback. ResourceDataValue value; getAllItemsWithFallback(rb, value, sink, errorCode); - ures_close(&stackBundle); } U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) { @@ -2108,7 +2137,7 @@ switch (RES_GET_TYPE(res)) { case URES_STRING: case URES_STRING_V2: - return res_getString(rd, res, len); + return res_getString({resB, key}, rd, res, len); case URES_ALIAS: { const UChar* result = 0; @@ -2130,7 +2159,7 @@ switch (RES_GET_TYPE(res)) { case URES_STRING: case URES_STRING_V2: - return res_getString(&(resB->fResData), res, len); + return res_getString({resB, key}, &(resB->fResData), res, len); case URES_ALIAS: { const UChar* result = 0; @@ -2151,6 +2180,7 @@ /* here should go a first attempt to locate the key using index table */ const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status); if(U_SUCCESS(*status)) { + // TODO: Tracing return res_getString(rd, res, len); } else { *status = U_MISSING_RESOURCE_ERROR; @@ -2296,6 +2326,8 @@ r->fSize = res_countArrayItems(&(r->fResData), r->fRes); r->fIndex = -1; + ResourceTracer(r).traceOpen(); + return r; } diff -Nru icu-64.2/source/common/uresdata.cpp icu-65.1/source/common/uresdata.cpp --- icu-64.2/source/common/uresdata.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uresdata.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -33,6 +33,7 @@ #include "uinvchar.h" #include "uresdata.h" #include "uresimp.h" +#include "utracimp.h" /* * Resource access helpers @@ -307,7 +308,7 @@ } U_CAPI const UChar * U_EXPORT2 -res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { +res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) { const UChar *p; uint32_t offset=RES_GET_OFFSET(res); int32_t length; @@ -402,7 +403,8 @@ } for(int32_t i = 0; i < length; ++i) { int32_t sLength; - const UChar *s = res_getString(pResData, array.internalGetResource(pResData, i), &sLength); + // No tracing: handled by the caller + const UChar *s = res_getStringNoTrace(pResData, array.internalGetResource(pResData, i), &sLength); if(s == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; return 0; @@ -434,7 +436,7 @@ } U_CAPI const uint8_t * U_EXPORT2 -res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) { +res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) { const uint8_t *p; uint32_t offset=RES_GET_OFFSET(res); int32_t length; @@ -454,7 +456,7 @@ U_CAPI const int32_t * U_EXPORT2 -res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength) { +res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) { const int32_t *p; uint32_t offset=RES_GET_OFFSET(res); int32_t length; @@ -507,7 +509,7 @@ if(U_FAILURE(errorCode)) { return NULL; } - const UChar *s = res_getString(pResData, res, &length); + const UChar *s = res_getString(fTraceInfo, &getData(), res, &length); if(s == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -518,7 +520,7 @@ if(U_FAILURE(errorCode)) { return NULL; } - const UChar *s = res_getAlias(pResData, res, &length); + const UChar *s = res_getAlias(&getData(), res, &length); if(s == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -532,7 +534,7 @@ if(RES_GET_TYPE(res) != URES_INT) { errorCode = U_RESOURCE_TYPE_MISMATCH; } - return RES_GET_INT(res); + return res_getInt(fTraceInfo, res); } uint32_t ResourceDataValue::getUInt(UErrorCode &errorCode) const { @@ -542,14 +544,14 @@ if(RES_GET_TYPE(res) != URES_INT) { errorCode = U_RESOURCE_TYPE_MISMATCH; } - return RES_GET_UINT(res); + return res_getUInt(fTraceInfo, res); } const int32_t *ResourceDataValue::getIntVector(int32_t &length, UErrorCode &errorCode) const { if(U_FAILURE(errorCode)) { return NULL; } - const int32_t *iv = res_getIntVector(pResData, res, &length); + const int32_t *iv = res_getIntVector(fTraceInfo, &getData(), res, &length); if(iv == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -560,7 +562,7 @@ if(U_FAILURE(errorCode)) { return NULL; } - const uint8_t *b = res_getBinary(pResData, res, &length); + const uint8_t *b = res_getBinary(fTraceInfo, &getData(), res, &length); if(b == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -578,19 +580,19 @@ switch(RES_GET_TYPE(res)) { case URES_ARRAY: if (offset!=0) { // empty if offset==0 - items32 = (const Resource *)pResData->pRoot+offset; + items32 = (const Resource *)getData().pRoot+offset; length = *items32++; } break; case URES_ARRAY16: - items16 = pResData->p16BitUnits+offset; + items16 = getData().p16BitUnits+offset; length = *items16++; break; default: errorCode = U_RESOURCE_TYPE_MISMATCH; return ResourceArray(); } - return ResourceArray(items16, items32, length); + return ResourceArray(items16, items32, length, fTraceInfo); } ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const { @@ -606,19 +608,19 @@ switch(RES_GET_TYPE(res)) { case URES_TABLE: if (offset != 0) { // empty if offset==0 - keys16 = (const uint16_t *)(pResData->pRoot+offset); + keys16 = (const uint16_t *)(getData().pRoot+offset); length = *keys16++; items32 = (const Resource *)(keys16+length+(~length&1)); } break; case URES_TABLE16: - keys16 = pResData->p16BitUnits+offset; + keys16 = getData().p16BitUnits+offset; length = *keys16++; items16 = keys16 + length; break; case URES_TABLE32: if (offset != 0) { // empty if offset==0 - keys32 = pResData->pRoot+offset; + keys32 = getData().pRoot+offset; length = *keys32++; items32 = (const Resource *)keys32 + length; } @@ -627,22 +629,22 @@ errorCode = U_RESOURCE_TYPE_MISMATCH; return ResourceTable(); } - return ResourceTable(keys16, keys32, items16, items32, length); + return ResourceTable(keys16, keys32, items16, items32, length, fTraceInfo); } UBool ResourceDataValue::isNoInheritanceMarker() const { - return ::isNoInheritanceMarker(pResData, res); + return ::isNoInheritanceMarker(&getData(), res); } int32_t ResourceDataValue::getStringArray(UnicodeString *dest, int32_t capacity, UErrorCode &errorCode) const { - return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode); + return ::getStringArray(&getData(), getArray(errorCode), dest, capacity, errorCode); } int32_t ResourceDataValue::getStringArrayOrStringAsArray(UnicodeString *dest, int32_t capacity, UErrorCode &errorCode) const { if(URES_IS_ARRAY(res)) { - return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode); + return ::getStringArray(&getData(), getArray(errorCode), dest, capacity, errorCode); } if(U_FAILURE(errorCode)) { return 0; @@ -656,7 +658,7 @@ return 1; } int32_t sLength; - const UChar *s = res_getString(pResData, res, &sLength); + const UChar *s = res_getString(fTraceInfo, &getData(), res, &sLength); if(s != NULL) { dest[0].setTo(TRUE, s, sLength); return 1; @@ -671,7 +673,7 @@ return us; } int32_t sLength; - const UChar *s = res_getString(pResData, res, &sLength); + const UChar *s = res_getString(fTraceInfo, &getData(), res, &sLength); if(s != NULL) { us.setTo(TRUE, s, sLength); return us; @@ -681,7 +683,8 @@ return us; } if(array.getSize() > 0) { - s = res_getString(pResData, array.internalGetResource(pResData, 0), &sLength); + // Tracing is already performed above (unimportant for trace that this is an array) + s = res_getStringNoTrace(&getData(), array.internalGetResource(&getData(), 0), &sLength); if(s != NULL) { us.setTo(TRUE, s, sLength); return us; @@ -818,18 +821,45 @@ const char *&key, icu::ResourceValue &value) const { if(0 <= i && i < length) { icu::ResourceDataValue &rdValue = static_cast(value); - if (keys16 != NULL) { - key = RES_GET_KEY16(rdValue.pResData, keys16[i]); + if (keys16 != nullptr) { + key = RES_GET_KEY16(&rdValue.getData(), keys16[i]); } else { - key = RES_GET_KEY32(rdValue.pResData, keys32[i]); + key = RES_GET_KEY32(&rdValue.getData(), keys32[i]); } Resource res; - if (items16 != NULL) { - res = makeResourceFrom16(rdValue.pResData, items16[i]); + if (items16 != nullptr) { + res = makeResourceFrom16(&rdValue.getData(), items16[i]); } else { res = items32[i]; } - rdValue.setResource(res); + // Note: the ResourceTracer keeps a reference to the field of this + // ResourceTable. This is OK because the ResourceTable should remain + // alive for the duration that fields are being read from it + // (including nested fields). + rdValue.setResource(res, ResourceTracer(fTraceInfo, key)); + return TRUE; + } + return FALSE; +} + +UBool icu::ResourceTable::findValue(const char *key, ResourceValue &value) const { + icu::ResourceDataValue &rdValue = static_cast(value); + const char *realKey = nullptr; + int32_t i; + if (keys16 != nullptr) { + i = _res_findTableItem(&rdValue.getData(), keys16, length, key, &realKey); + } else { + i = _res_findTable32Item(&rdValue.getData(), keys32, length, key, &realKey); + } + if (i >= 0) { + Resource res; + if (items16 != nullptr) { + res = makeResourceFrom16(&rdValue.getData(), items16[i]); + } else { + res = items32[i]; + } + // Same note about lifetime as in getKeyAndValue(). + rdValue.setResource(res, ResourceTracer(fTraceInfo, key)); return TRUE; } return FALSE; @@ -875,7 +905,13 @@ UBool icu::ResourceArray::getValue(int32_t i, icu::ResourceValue &value) const { if(0 <= i && i < length) { icu::ResourceDataValue &rdValue = static_cast(value); - rdValue.setResource(internalGetResource(rdValue.pResData, i)); + // Note: the ResourceTracer keeps a reference to the field of this + // ResourceArray. This is OK because the ResourceArray should remain + // alive for the duration that fields are being read from it + // (including nested fields). + rdValue.setResource( + internalGetResource(&rdValue.getData(), i), + ResourceTracer(fTraceInfo, i)); return TRUE; } return FALSE; diff -Nru icu-64.2/source/common/uresdata.h icu-65.1/source/common/uresdata.h --- icu-64.2/source/common/uresdata.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uresdata.h 2019-10-03 11:16:41.000000000 +0000 @@ -69,14 +69,16 @@ #define RES_GET_OFFSET(res) ((res)&0x0fffffff) #define RES_GET_POINTER(pRoot, res) ((pRoot)+RES_GET_OFFSET(res)) -/* get signed and unsigned integer values directly from the Resource handle */ +/* get signed and unsigned integer values directly from the Resource handle + * NOTE: For proper logging, please use the res_getInt() constexpr + */ #if U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC -# define RES_GET_INT(res) (((int32_t)((res)<<4L))>>4L) +# define RES_GET_INT_NO_TRACE(res) (((int32_t)((res)<<4L))>>4L) #else -# define RES_GET_INT(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff) +# define RES_GET_INT_NO_TRACE(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff) #endif -#define RES_GET_UINT(res) ((res)&0x0fffffff) +#define RES_GET_UINT_NO_TRACE(res) ((res)&0x0fffffff) #define URES_IS_ARRAY(type) ((int32_t)(type)==URES_ARRAY || (int32_t)(type)==URES_ARRAY16) #define URES_IS_TABLE(type) ((int32_t)(type)==URES_TABLE || (int32_t)(type)==URES_TABLE16 || (int32_t)(type)==URES_TABLE32) @@ -423,22 +425,26 @@ U_INTERNAL UResType U_EXPORT2 res_getPublicType(Resource res); +/////////////////////////////////////////////////////////////////////////// +// To enable tracing, use the inline versions of the res_get* functions. // +/////////////////////////////////////////////////////////////////////////// + /* * Return a pointer to a zero-terminated, const UChar* string * and set its length in *pLength. * Returns NULL if not found. */ U_INTERNAL const UChar * U_EXPORT2 -res_getString(const ResourceData *pResData, Resource res, int32_t *pLength); - -U_INTERNAL const UChar * U_EXPORT2 -res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength); +res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength); U_INTERNAL const uint8_t * U_EXPORT2 -res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength); +res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength); U_INTERNAL const int32_t * U_EXPORT2 -res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength); +res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength); + +U_INTERNAL const UChar * U_EXPORT2 +res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength); U_INTERNAL Resource U_EXPORT2 res_getResource(const ResourceData *pResData, const char *key); @@ -470,17 +476,55 @@ #ifdef __cplusplus #include "resource.h" +#include "restrace.h" U_NAMESPACE_BEGIN +inline const UChar* res_getString(const ResourceTracer& traceInfo, + const ResourceData *pResData, Resource res, int32_t *pLength) { + traceInfo.trace("string"); + return res_getStringNoTrace(pResData, res, pLength); +} + +inline const uint8_t* res_getBinary(const ResourceTracer& traceInfo, + const ResourceData *pResData, Resource res, int32_t *pLength) { + traceInfo.trace("binary"); + return res_getBinaryNoTrace(pResData, res, pLength); +} + +inline const int32_t* res_getIntVector(const ResourceTracer& traceInfo, + const ResourceData *pResData, Resource res, int32_t *pLength) { + traceInfo.trace("intvector"); + return res_getIntVectorNoTrace(pResData, res, pLength); +} + +inline int32_t res_getInt(const ResourceTracer& traceInfo, Resource res) { + traceInfo.trace("int"); + return RES_GET_INT_NO_TRACE(res); +} + +inline uint32_t res_getUInt(const ResourceTracer& traceInfo, Resource res) { + traceInfo.trace("uint"); + return RES_GET_UINT_NO_TRACE(res); +} + class ResourceDataValue : public ResourceValue { public: - ResourceDataValue() : pResData(NULL), res(static_cast(URES_NONE)) {} + ResourceDataValue() : + res(static_cast(URES_NONE)), + fTraceInfo() {} virtual ~ResourceDataValue(); - void setData(const ResourceData *data) { pResData = data; } - void setResource(Resource r) { res = r; } + void setData(const ResourceData *data) { + resData = *data; + } + + void setResource(Resource r, ResourceTracer&& traceInfo) { + res = r; + fTraceInfo = traceInfo; + } + const ResourceData &getData() const { return resData; } virtual UResType getType() const; virtual const UChar *getString(int32_t &length, UErrorCode &errorCode) const; virtual const UChar *getAliasString(int32_t &length, UErrorCode &errorCode) const; @@ -497,10 +541,12 @@ UErrorCode &errorCode) const; virtual UnicodeString getStringOrFirstOfArray(UErrorCode &errorCode) const; - const ResourceData *pResData; - private: + // TODO(ICU-20769): If UResourceBundle.fResData becomes a pointer, + // then remove this value field again and just store a pResData pointer. + ResourceData resData; Resource res; + ResourceTracer fTraceInfo; }; U_NAMESPACE_END diff -Nru icu-64.2/source/common/uresimp.h icu-65.1/source/common/uresimp.h --- icu-64.2/source/common/uresimp.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/uresimp.h 2019-10-03 11:16:41.000000000 +0000 @@ -67,6 +67,9 @@ char *fVersion; UResourceDataEntry *fTopLevelData; /* for getting the valid locale */ char *fResPath; /* full path to the resource: "zh_TW/CollationElements/Sequence" */ + // TODO(ICU-20769): Try to change the by-value fResData into a pointer, + // with the struct in only one place for each bundle. + // Also replace class ResourceDataValue.resData with a pResData pointer again. ResourceData fResData; char fResBuf[RES_BUFSIZE]; int32_t fResPathLen; @@ -282,6 +285,11 @@ #ifdef __cplusplus U_CAPI void U_EXPORT2 +ures_getValueWithFallback(const UResourceBundle *bundle, const char *path, + UResourceBundle *tempFillIn, + icu::ResourceDataValue &value, UErrorCode &errorCode); + +U_CAPI void U_EXPORT2 ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path, icu::ResourceSink &sink, UErrorCode &errorCode); diff -Nru icu-64.2/source/common/usprep.cpp icu-65.1/source/common/usprep.cpp --- icu-64.2/source/common/usprep.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/usprep.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -45,13 +45,9 @@ Static cache for already opened StringPrep profiles */ static UHashtable *SHARED_DATA_HASHTABLE = NULL; -static icu::UInitOnce gSharedDataInitOnce; - -static UMutex *usprepMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UInitOnce gSharedDataInitOnce = U_INITONCE_INITIALIZER; +static UMutex usprepMutex; /* format version of spp file */ //static uint8_t formatVersion[4]={ 0, 0, 0, 0 }; @@ -151,9 +147,9 @@ * if shared data hasn't even been lazy evaluated yet * return 0 */ - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); if (SHARED_DATA_HASHTABLE == NULL) { - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); return 0; } @@ -184,7 +180,7 @@ } } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); return deletedNum; } @@ -262,7 +258,7 @@ } /* in the mutex block, set the data for this process */ - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); if(profile->sprepData==NULL) { profile->sprepData=dataMemory; dataMemory=NULL; @@ -271,7 +267,7 @@ } else { p=(const int32_t *)udata_getMemory(profile->sprepData); } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); /* initialize some variables */ profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]); @@ -328,12 +324,12 @@ stackKey.path = (char*) path; /* fetch the data from the cache */ - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { profile->refCount++; } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); if(profile == NULL) { /* else load the data and put the data in the cache */ @@ -365,7 +361,7 @@ return NULL; } - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); // If another thread already inserted the same key/value, refcount and cleanup our thread data profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { @@ -386,7 +382,7 @@ profile->refCount = 1; uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status); } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); } return profile; @@ -425,12 +421,12 @@ return; } - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); /* decrement the ref count*/ if(profile->refCount > 0){ profile->refCount--; } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); } diff -Nru icu-64.2/source/common/ustring.cpp icu-65.1/source/common/ustring.cpp --- icu-64.2/source/common/ustring.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ustring.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1428,7 +1428,7 @@ * NUL-terminate a string no matter what its type. * Set warning and error codes accordingly. */ -#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) \ +#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) UPRV_BLOCK_MACRO_BEGIN { \ if(pErrorCode!=NULL && U_SUCCESS(*pErrorCode)) { \ /* not a public function, so no complete argument checking */ \ \ @@ -1448,7 +1448,8 @@ /* even the string itself did not fit - set an error code */ \ *pErrorCode=U_BUFFER_OVERFLOW_ERROR; \ } \ - } + } \ +} UPRV_BLOCK_MACRO_END U_CAPI int32_t U_EXPORT2 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) { @@ -1488,7 +1489,7 @@ the output range. [LIU] */ -#define STRING_HASH(TYPE, STR, STRLEN, DEREF) \ +#define STRING_HASH(TYPE, STR, STRLEN, DEREF) UPRV_BLOCK_MACRO_BEGIN { \ uint32_t hash = 0; \ const TYPE *p = (const TYPE*) STR; \ if (p != NULL) { \ @@ -1500,7 +1501,8 @@ p += inc; \ } \ } \ - return static_cast(hash) + return static_cast(hash); \ +} UPRV_BLOCK_MACRO_END /* Used by UnicodeString to compute its hashcode - Not public API. */ U_CAPI int32_t U_EXPORT2 diff -Nru icu-64.2/source/common/ustr_titlecase_brkiter.cpp icu-65.1/source/common/ustr_titlecase_brkiter.cpp --- icu-64.2/source/common/ustr_titlecase_brkiter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/ustr_titlecase_brkiter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -45,7 +45,7 @@ WholeStringBreakIterator() : BreakIterator(), length(0) {} ~WholeStringBreakIterator() U_OVERRIDE; UBool operator==(const BreakIterator&) const U_OVERRIDE; - BreakIterator *clone() const U_OVERRIDE; + WholeStringBreakIterator *clone() const U_OVERRIDE; static UClassID U_EXPORT2 getStaticClassID(); UClassID getDynamicClassID() const U_OVERRIDE; CharacterIterator &getText() const U_OVERRIDE; @@ -62,9 +62,9 @@ int32_t preceding(int32_t offset) U_OVERRIDE; UBool isBoundary(int32_t offset) U_OVERRIDE; int32_t next(int32_t n) U_OVERRIDE; - BreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize, - UErrorCode &errorCode) U_OVERRIDE; - BreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE; + WholeStringBreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize, + UErrorCode &errorCode) U_OVERRIDE; + WholeStringBreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE; private: int32_t length; @@ -74,7 +74,7 @@ WholeStringBreakIterator::~WholeStringBreakIterator() {} UBool WholeStringBreakIterator::operator==(const BreakIterator&) const { return FALSE; } -BreakIterator *WholeStringBreakIterator::clone() const { return nullptr; } +WholeStringBreakIterator *WholeStringBreakIterator::clone() const { return nullptr; } CharacterIterator &WholeStringBreakIterator::getText() const { UPRV_UNREACHABLE; // really should not be called @@ -113,14 +113,14 @@ UBool WholeStringBreakIterator::isBoundary(int32_t /*offset*/) { return FALSE; } int32_t WholeStringBreakIterator::next(int32_t /*n*/) { return length; } -BreakIterator *WholeStringBreakIterator::createBufferClone( +WholeStringBreakIterator *WholeStringBreakIterator::createBufferClone( void * /*stackBuffer*/, int32_t & /*BufferSize*/, UErrorCode &errorCode) { if (U_SUCCESS(errorCode)) { errorCode = U_UNSUPPORTED_ERROR; } return nullptr; } -BreakIterator &WholeStringBreakIterator::refreshInputText( +WholeStringBreakIterator &WholeStringBreakIterator::refreshInputText( UText * /*input*/, UErrorCode &errorCode) { if (U_SUCCESS(errorCode)) { errorCode = U_UNSUPPORTED_ERROR; diff -Nru icu-64.2/source/common/utext.cpp icu-65.1/source/common/utext.cpp --- icu-64.2/source/common/utext.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/utext.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -567,7 +567,7 @@ struct ExtendedUText { UText ut; - UAlignedMemory extension; + max_align_t extension; }; static const UText emptyText = UTEXT_INITIALIZER; @@ -582,7 +582,7 @@ // We need to heap-allocate storage for the new UText int32_t spaceRequired = sizeof(UText); if (extraSpace > 0) { - spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(UAlignedMemory); + spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(max_align_t); } ut = (UText *)uprv_malloc(spaceRequired); if (ut == NULL) { diff -Nru icu-64.2/source/common/util.cpp icu-65.1/source/common/util.cpp --- icu-64.2/source/common/util.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/util.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -276,6 +276,16 @@ return -1; // text ended before end of pat } +int32_t ICU_Utility::parseAsciiInteger(const UnicodeString& str, int32_t& pos) { + int32_t result = 0; + UChar c; + while (pos < str.length() && (c = str.charAt(pos)) >= u'0' && c <= u'9') { + result = result * 10 + (c - u'0'); + pos++; + } + return result; +} + /** * Append a character to a rule that is being built up. To flush * the quoteBuf to rule, make one final call with isLiteral == TRUE. diff -Nru icu-64.2/source/common/util.h icu-65.1/source/common/util.h --- icu-64.2/source/common/util.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/util.h 2019-10-03 11:16:41.000000000 +0000 @@ -179,13 +179,22 @@ * Parse an integer at pos, either of the form \d+ or of the form * 0x[0-9A-Fa-f]+ or 0[0-7]+, that is, in standard decimal, hex, * or octal format. - * @param pos INPUT-OUTPUT parameter. On input, the first - * character to parse. On output, the character after the last - * parsed character. + * @param pos INPUT-OUTPUT parameter. On input, the index of the first + * character to parse. On output, the index of the character after the + * last parsed character. */ static int32_t parseInteger(const UnicodeString& rule, int32_t& pos, int32_t limit); /** + * Parse an integer at pos using only ASCII digits. + * Base 10 only. + * @param pos INPUT-OUTPUT parameter. On input, the index of the first + * character to parse. On output, the index of the character after the + * last parsed character. + */ + static int32_t parseAsciiInteger(const UnicodeString& str, int32_t& pos); + + /** * Parse a Unicode identifier from the given string at the given * position. Return the identifier, or an empty string if there * is no identifier. diff -Nru icu-64.2/source/common/utrace.cpp icu-65.1/source/common/utrace.cpp --- icu-64.2/source/common/utrace.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/utrace.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -476,6 +476,16 @@ NULL }; + +static const char* const +trResDataNames[] = { + "resc", + "bundle-open", + "file-open", + "res-open", + NULL +}; + U_CAPI const char * U_EXPORT2 utrace_functionName(int32_t fnNumber) { @@ -485,6 +495,8 @@ return trConvNames[fnNumber - UTRACE_CONVERSION_START]; } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){ return trCollNames[fnNumber - UTRACE_COLLATION_START]; + } else if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){ + return trResDataNames[fnNumber - UTRACE_UDATA_START]; } else { return "[BOGUS Trace Function Number]"; } diff -Nru icu-64.2/source/common/utracimp.h icu-65.1/source/common/utracimp.h --- icu-64.2/source/common/utracimp.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/utracimp.h 2019-10-03 11:16:41.000000000 +0000 @@ -144,10 +144,12 @@ */ #define UTRACE_ENTRY(fnNumber) \ int32_t utraceFnNumber=(fnNumber); \ +UPRV_BLOCK_MACRO_BEGIN { \ if(utrace_getLevel()>=UTRACE_INFO) { \ utrace_entry(fnNumber); \ utraceFnNumber |= UTRACE_TRACED_ENTRY; \ - } + } \ +} UPRV_BLOCK_MACRO_END /** @@ -162,10 +164,12 @@ */ #define UTRACE_ENTRY_OC(fnNumber) \ int32_t utraceFnNumber=(fnNumber); \ +UPRV_BLOCK_MACRO_BEGIN { \ if(utrace_getLevel()>=UTRACE_OPEN_CLOSE) { \ utrace_entry(fnNumber); \ utraceFnNumber |= UTRACE_TRACED_ENTRY; \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement for each exit point of a function that has a UTRACE_ENTRY() @@ -179,10 +183,11 @@ * * @internal */ -#define UTRACE_EXIT() \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT() UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_NONE); \ - }} + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement for each exit point of a function that has a UTRACE_ENTRY() @@ -192,25 +197,29 @@ * * @internal */ -#define UTRACE_EXIT_VALUE(val) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_VALUE(val) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_I32, val); \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define UTRACE_EXIT_STATUS(status) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_STATUS, status); \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define UTRACE_EXIT_VALUE_STATUS(val, status) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_VALUE_STATUS(val, status) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS), val, status); \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define UTRACE_EXIT_PTR_STATUS(ptr, status) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_PTR_STATUS(ptr, status) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS), ptr, status); \ - }} + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -220,10 +229,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA0(level, fmt) \ +#define UTRACE_DATA0(level, fmt) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -233,10 +243,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA1(level, fmt, a) \ +#define UTRACE_DATA1(level, fmt, a) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -246,10 +257,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA2(level, fmt, a, b) \ +#define UTRACE_DATA2(level, fmt, a, b) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a), (b)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -259,10 +271,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA3(level, fmt, a, b, c) \ +#define UTRACE_DATA3(level, fmt, a, b, c) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -272,10 +285,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA4(level, fmt, a, b, c, d) \ +#define UTRACE_DATA4(level, fmt, a, b, c, d) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -285,10 +299,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA5(level, fmt, a, b, c, d, e) \ +#define UTRACE_DATA5(level, fmt, a, b, c, d, e) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -298,10 +313,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) \ +#define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -311,10 +327,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) \ +#define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -324,10 +341,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) \ +#define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -337,10 +355,11 @@ * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) \ +#define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h), (i)); \ - } + } \ +} UPRV_BLOCK_MACRO_END #else diff -Nru icu-64.2/source/common/utrie2.h icu-65.1/source/common/utrie2.h --- icu-64.2/source/common/utrie2.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/utrie2.h 2019-10-03 11:16:41.000000000 +0000 @@ -871,7 +871,7 @@ (trie)->data[_UTRIE2_INDEX_FROM_CP(trie, asciiOffset, c)] /** Internal next-post-increment: get the next code point (c) and its data. */ -#define _UTRIE2_U16_NEXT(trie, data, src, limit, c, result) { \ +#define _UTRIE2_U16_NEXT(trie, data, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \ { \ uint16_t __c2; \ (c)=*(src)++; \ @@ -885,10 +885,10 @@ (result)=_UTRIE2_GET_FROM_SUPP((trie), data, (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal pre-decrement-previous: get the previous code point (c) and its data */ -#define _UTRIE2_U16_PREV(trie, data, start, src, c, result) { \ +#define _UTRIE2_U16_PREV(trie, data, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \ { \ uint16_t __c2; \ (c)=*--(src); \ @@ -900,10 +900,10 @@ (result)=_UTRIE2_GET_FROM_SUPP((trie), data, (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal UTF-8 next-post-increment: get the next code point's data. */ -#define _UTRIE2_U8_NEXT(trie, ascii, data, src, limit, result) { \ +#define _UTRIE2_U8_NEXT(trie, ascii, data, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \ uint8_t __lead=(uint8_t)*(src)++; \ if(U8_IS_SINGLE(__lead)) { \ (result)=(trie)->ascii[__lead]; \ @@ -935,10 +935,10 @@ (result)=(trie)->data[__index>>3]; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal UTF-8 pre-decrement-previous: get the previous code point's data. */ -#define _UTRIE2_U8_PREV(trie, ascii, data, start, src, result) { \ +#define _UTRIE2_U8_PREV(trie, ascii, data, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \ uint8_t __b=(uint8_t)*--(src); \ if(U8_IS_SINGLE(__b)) { \ (result)=(trie)->ascii[__b]; \ @@ -948,7 +948,7 @@ (src)-=__index&7; \ (result)=(trie)->data[__index>>3]; \ } \ -} +} UPRV_BLOCK_MACRO_END U_CDECL_END diff -Nru icu-64.2/source/common/utrie.h icu-65.1/source/common/utrie.h --- icu-64.2/source/common/utrie.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/common/utrie.h 2019-10-03 11:16:41.000000000 +0000 @@ -182,7 +182,7 @@ ] /** Internal trie getter from a pair of surrogates */ -#define _UTRIE_GET_FROM_PAIR(trie, data, c, c2, result, resultType) { \ +#define _UTRIE_GET_FROM_PAIR(trie, data, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __offset; \ \ /* get data for lead surrogate */ \ @@ -195,18 +195,18 @@ } else { \ (result)=(resultType)((trie)->initialValue); \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal trie getter from a BMP code point, treating a lead surrogate as a normal code point */ #define _UTRIE_GET_FROM_BMP(trie, data, c16) \ - _UTRIE_GET_RAW(trie, data, 0xd800<=(c16) && (c16)<=0xdbff ? UTRIE_LEAD_INDEX_DISP : 0, c16); + _UTRIE_GET_RAW(trie, data, 0xd800<=(c16) && (c16)<=0xdbff ? UTRIE_LEAD_INDEX_DISP : 0, c16) /** * Internal trie getter from a code point. * Could be faster(?) but longer with * if((c32)<=0xd7ff) { (result)=_UTRIE_GET_RAW(trie, data, 0, c32); } */ -#define _UTRIE_GET(trie, data, c32, result, resultType) \ +#define _UTRIE_GET(trie, data, c32, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c32)<=0xffff) { \ /* BMP code points */ \ (result)=_UTRIE_GET_FROM_BMP(trie, data, c32); \ @@ -217,10 +217,11 @@ } else { \ /* out of range */ \ (result)=(resultType)((trie)->initialValue); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** Internal next-post-increment: get the next code point (c, c2) and its data */ -#define _UTRIE_NEXT(trie, data, src, limit, c, c2, result, resultType) { \ +#define _UTRIE_NEXT(trie, data, src, limit, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ (c)=*(src)++; \ if(!U16_IS_LEAD(c)) { \ (c2)=0; \ @@ -233,10 +234,10 @@ (c2)=0; \ (result)=_UTRIE_GET_RAW((trie), data, UTRIE_LEAD_INDEX_DISP, (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal previous: get the previous code point (c, c2) and its data */ -#define _UTRIE_PREVIOUS(trie, data, start, src, c, c2, result, resultType) { \ +#define _UTRIE_PREVIOUS(trie, data, start, src, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ (c)=*--(src); \ if(!U16_IS_SURROGATE(c)) { \ (c2)=0; \ @@ -257,7 +258,7 @@ (c2)=0; \ (result)=_UTRIE_GET_RAW((trie), data, UTRIE_LEAD_INDEX_DISP, (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /* Public UTrie API ---------------------------------------------------------*/ diff -Nru icu-64.2/source/config/mh-cygwin-msvc icu-65.1/source/config/mh-cygwin-msvc --- icu-64.2/source/config/mh-cygwin-msvc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/config/mh-cygwin-msvc 2019-10-03 11:16:41.000000000 +0000 @@ -121,13 +121,13 @@ LIBICUTOOLUTIL= $(LIBDIR)/$(LIBICU)$(TOOLUTIL_STUBNAME)$(ICULIBSUFFIX).lib ## These are the library specific LDFLAGS -LDFLAGSICUDT+= -base:"0x4ad00000" -NOENTRY# The NOENTRY option is required for creating a resource-only DLL. -LDFLAGSICUUC= -base:"0x4a800000"# in-uc = 1MB -LDFLAGSICUI18N= -base:"0x4a900000"# io-in = 2MB -LDFLAGSICUIO= -base:"0x4ab00000"# le-io = 1MB -LDFLAGSICULX= -base:"0x4ac80000" +LDFLAGSICUDT+= -NOENTRY# The NOENTRY option is required for creating a resource-only DLL. +LDFLAGSICUUC=# Unused for now. +LDFLAGSICUI18N=# Unused for now. +LDFLAGSICUIO=# Unused for now. +LDFLAGSICULX=# Unused for now. LDFLAGSCTESTFW=# Unused for now. -LDFLAGSICUTOOLUTIL= -base:"0x4ac00000"# Same as layout. Layout and tools probably won't mix. +LDFLAGSICUTOOLUTIL=# Unused for now. # The #M# is used to delete lines for icu-config # Current full path directory. diff -Nru icu-64.2/source/config/mh-mingw icu-65.1/source/config/mh-mingw --- icu-64.2/source/config/mh-mingw 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/config/mh-mingw 2019-10-03 11:16:41.000000000 +0000 @@ -103,13 +103,29 @@ #SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well. #SH#ICULIBS="${ICULIBS_BASE} ${ICULIBS_I18N} ${ICULIBS_COMMON} ${ICULIBS_DATA} " -# The #M# is used to delete lines for icu-config -# Current full path directory. -#CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS -CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell -# Current full path directory for use in source code in a -D compiler option. -#CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS -CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell +# Note: The #M# is used to delete lines for icu-config +MSYS_VERSION ?= $(if $(findstring Msys, $(shell uname -o)),$(word 1, $(subst ., ,$(shell uname -r))),0)#M# +$(info Detected MSYS version: $(MSYS_VERSION)) + +ifeq ($(MSYS_VERSION),$(filter $(MSYS_VERSION),0 1)) + # Older versions of MSYS don't have cygpath by default. #M# + + # Current full path directory. #M# + #CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS + CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell + + # Current full path directory for use in source code in a -D compiler option. #M# + #CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS + CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell +else + # MSYS2 and up have cygpath by default #M# + + # Current full path directory. #M# + CURR_FULL_DIR?=$(shell cygpath . -a -m)#M# + + # Current full path directory for use in source code in a -D compiler option. #M# + CURR_SRCCODE_FULL_DIR=$(shell cygpath . -a -m)#M# +endif ## Compilation rules %.$(STATIC_O): $(srcdir)/%.c diff -Nru icu-64.2/source/config/mh-mingw64 icu-65.1/source/config/mh-mingw64 --- icu-64.2/source/config/mh-mingw64 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/config/mh-mingw64 2019-10-03 11:16:41.000000000 +0000 @@ -103,13 +103,29 @@ #SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well. #SH#ICULIBS="${ICULIBS_BASE} ${ICULIBS_I18N} ${ICULIBS_COMMON} ${ICULIBS_DATA} " -# The #M# is used to delete lines for icu-config -# Current full path directory. -#CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS -CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell -# Current full path directory for use in source code in a -D compiler option. -#CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS -CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell +# Note: The #M# is used to delete lines for icu-config +MSYS_VERSION ?= $(if $(findstring Msys, $(shell uname -o)),$(word 1, $(subst ., ,$(shell uname -r))),0)#M# +$(info Detected MSYS version: $(MSYS_VERSION)) + +ifeq ($(MSYS_VERSION),$(filter $(MSYS_VERSION),0 1)) + # Older versions of MSYS don't have cygpath by default. #M# + + # Current full path directory. #M# + #CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS + CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell + + # Current full path directory for use in source code in a -D compiler option. #M# + #CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS + CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell +else + # MSYS2 and up have cygpath by default #M# + + # Current full path directory. #M# + CURR_FULL_DIR?=$(shell cygpath . -a -m)#M# + + # Current full path directory for use in source code in a -D compiler option. #M# + CURR_SRCCODE_FULL_DIR=$(shell cygpath . -a -m)#M# +endif ## Compilation rules %.$(STATIC_O): $(srcdir)/%.c diff -Nru icu-64.2/source/config/mh-msys-msvc icu-65.1/source/config/mh-msys-msvc --- icu-64.2/source/config/mh-msys-msvc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/config/mh-msys-msvc 2019-10-03 11:16:41.000000000 +0000 @@ -122,13 +122,13 @@ LIBICUTOOLUTIL= $(LIBDIR)/$(LIBICU)$(TOOLUTIL_STUBNAME)$(ICULIBSUFFIX).lib ## These are the library specific LDFLAGS -LDFLAGSICUDT+= -base:"0x4ad00000" -NOENTRY# The NOENTRY option is required for creating a resource-only DLL. -LDFLAGSICUUC= -base:"0x4a800000"# in-uc = 1MB -LDFLAGSICUI18N= -base:"0x4a900000"# io-in = 2MB -LDFLAGSICUIO= -base:"0x4ab00000"# le-io = 1MB -LDFLAGSICULX= -base:"0x4ac80000" +LDFLAGSICUDT+= -NOENTRY# The NOENTRY option is required for creating a resource-only DLL. +LDFLAGSICUUC=# Unused for now. +LDFLAGSICUI18N=# Unused for now. +LDFLAGSICUIO=# Unused for now. +LDFLAGSICULX=# Unused for now. LDFLAGSCTESTFW=# Unused for now. -LDFLAGSICUTOOLUTIL= -base:"0x4ac00000"# Same as layout. Layout and tools probably won't mix. +LDFLAGSICUTOOLUTIL=# Unused for now. ## Compilation rules %.$(STATIC_O): $(srcdir)/%.c diff -Nru icu-64.2/source/configure icu-65.1/source/configure --- icu-64.2/source/configure 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/configure 2019-10-03 11:16:41.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for ICU 64.2. +# Generated by GNU Autoconf 2.69 for ICU 65.1. # # Report bugs to . # @@ -582,8 +582,8 @@ # Identity of this package. PACKAGE_NAME='ICU' PACKAGE_TARNAME='International Components for Unicode' -PACKAGE_VERSION='64.2' -PACKAGE_STRING='ICU 64.2' +PACKAGE_VERSION='65.1' +PACKAGE_STRING='ICU 65.1' PACKAGE_BUGREPORT='http://icu-project.org/bugs' PACKAGE_URL='http://icu-project.org' @@ -645,6 +645,8 @@ DATA_PACKAGING_MODE thepkgicudatadir pkgicudatadir +U_HAVE_FUZZER +FUZZER_TRUE U_HAVE_TOOLS TOOLS_TRUE U_HAVE_LAYOUTEX @@ -797,6 +799,7 @@ enable_layoutex enable_layout enable_tools +enable_fuzzer with_data_packaging with_library_suffix enable_tests @@ -1359,7 +1362,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures ICU 64.2 to adapt to many kinds of systems. +\`configure' configures ICU 65.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1425,7 +1428,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ICU 64.2:";; + short | recursive ) echo "Configuration of ICU 65.1:";; esac cat <<\_ACEOF @@ -1454,6 +1457,7 @@ icu-le-hb must be installed via pkg-config. See http://harfbuzz.org --enable-tools build ICU's tools default=yes + --enable-fuzzer build ICU's fuzzer test targets default=no --enable-tests build ICU tests default=yes --enable-samples build ICU samples default=yes @@ -1562,7 +1566,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ICU configure 64.2 +ICU configure 65.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2197,6 +2201,60 @@ } # ac_fn_c_check_func +# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES +# --------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_cxx_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_type + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -2254,7 +2312,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ICU $as_me 64.2, which was +It was created by ICU $as_me 65.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -7149,6 +7207,29 @@ fi +# Check if C++17 std::string_view is available. +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +ac_fn_cxx_check_type "$LINENO" "std::string_view" "ac_cv_type_std__string_view" "#include +" +if test "x$ac_cv_type_std__string_view" = xyes; then : + +fi + +if test "x$ac_cv_type_std__string_view" = xyes; then : + CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRING_VIEW=1" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + # Checks for typedefs ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" if test "x$ac_cv_type_int8_t" = xyes; then : @@ -7665,6 +7746,28 @@ U_HAVE_TOOLS=0 fi +# Enable/disable fuzzer target tests. +# Check whether --enable-fuzzer was given. +if test "${enable_fuzzer+set}" = set; then : + enableval=$enable_fuzzer; case "${enableval}" in + yes) fuzzer=true ;; + no) fuzzer=false ;; + *) as_fn_error $? "bad value ${enableval} for --enable-fuzzer" "$LINENO" 5 ;; + esac +else + fuzzer=false +fi + + + +if test "$fuzzer" = true; then + FUZZER_TRUE= + U_HAVE_FUZZER=1 +else + FUZZER_TRUE='#' + U_HAVE_FUZZER=0 +fi + # Check whether --with-data-packaging was given. if test "${with_data_packaging+set}" = set; then : @@ -7863,6 +7966,7 @@ if test "${CXX}" = "clang++"; then CLANGCXXFLAGS="-Qunused-arguments -Wno-parentheses-equality" + LIBCXXFLAGS="$LIBCXXFLAGS -Wglobal-constructors" else CLANGCXXFLAGS="" fi @@ -7883,7 +7987,7 @@ # output the Makefiles -ac_config_files="$ac_config_files icudefs.mk Makefile data/pkgdataMakefile config/Makefile.inc config/icu.pc config/pkgdataMakefile data/Makefile stubdata/Makefile common/Makefile i18n/Makefile layoutex/Makefile io/Makefile extra/Makefile extra/uconv/Makefile extra/uconv/pkgdataMakefile extra/scrptrun/Makefile tools/Makefile tools/ctestfw/Makefile tools/toolutil/Makefile tools/makeconv/Makefile tools/genrb/Makefile tools/genccode/Makefile tools/gencmn/Makefile tools/gencnval/Makefile tools/gendict/Makefile tools/gentest/Makefile tools/gennorm2/Makefile tools/genbrk/Makefile tools/gensprep/Makefile tools/icuinfo/Makefile tools/icupkg/Makefile tools/icuswap/Makefile tools/pkgdata/Makefile tools/tzcode/Makefile tools/gencfu/Makefile tools/escapesrc/Makefile test/Makefile test/compat/Makefile test/testdata/Makefile test/testdata/pkgdataMakefile test/hdrtst/Makefile test/intltest/Makefile test/cintltst/Makefile test/iotest/Makefile test/letest/Makefile test/perf/Makefile test/perf/collationperf/Makefile test/perf/collperf/Makefile test/perf/collperf2/Makefile test/perf/dicttrieperf/Makefile test/perf/ubrkperf/Makefile test/perf/charperf/Makefile test/perf/convperf/Makefile test/perf/normperf/Makefile test/perf/DateFmtPerf/Makefile test/perf/howExpensiveIs/Makefile test/perf/strsrchperf/Makefile test/perf/unisetperf/Makefile test/perf/usetperf/Makefile test/perf/ustrperf/Makefile test/perf/utfperf/Makefile test/perf/utrie2perf/Makefile test/perf/leperf/Makefile samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile" +ac_config_files="$ac_config_files icudefs.mk Makefile data/pkgdataMakefile config/Makefile.inc config/icu.pc config/pkgdataMakefile data/Makefile stubdata/Makefile common/Makefile i18n/Makefile layoutex/Makefile io/Makefile extra/Makefile extra/uconv/Makefile extra/uconv/pkgdataMakefile extra/scrptrun/Makefile tools/Makefile tools/ctestfw/Makefile tools/toolutil/Makefile tools/makeconv/Makefile tools/genrb/Makefile tools/genccode/Makefile tools/gencmn/Makefile tools/gencnval/Makefile tools/gendict/Makefile tools/gentest/Makefile tools/gennorm2/Makefile tools/genbrk/Makefile tools/gensprep/Makefile tools/icuinfo/Makefile tools/icupkg/Makefile tools/icuswap/Makefile tools/pkgdata/Makefile tools/tzcode/Makefile tools/gencfu/Makefile tools/escapesrc/Makefile test/Makefile test/compat/Makefile test/testdata/Makefile test/testdata/pkgdataMakefile test/hdrtst/Makefile test/intltest/Makefile test/cintltst/Makefile test/iotest/Makefile test/letest/Makefile test/perf/Makefile test/perf/collationperf/Makefile test/perf/collperf/Makefile test/perf/collperf2/Makefile test/perf/dicttrieperf/Makefile test/perf/ubrkperf/Makefile test/perf/charperf/Makefile test/perf/convperf/Makefile test/perf/normperf/Makefile test/perf/DateFmtPerf/Makefile test/perf/howExpensiveIs/Makefile test/perf/strsrchperf/Makefile test/perf/unisetperf/Makefile test/perf/usetperf/Makefile test/perf/ustrperf/Makefile test/perf/utfperf/Makefile test/perf/utrie2perf/Makefile test/perf/leperf/Makefile test/fuzzer/Makefile samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -8428,7 +8532,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ICU $as_me 64.2, which was +This file was extended by ICU $as_me 65.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8482,7 +8586,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -ICU config.status 64.2 +ICU config.status 65.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -8656,6 +8760,7 @@ "test/perf/utfperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/utfperf/Makefile" ;; "test/perf/utrie2perf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/utrie2perf/Makefile" ;; "test/perf/leperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/leperf/Makefile" ;; + "test/fuzzer/Makefile") CONFIG_FILES="$CONFIG_FILES test/fuzzer/Makefile" ;; "samples/Makefile") CONFIG_FILES="$CONFIG_FILES samples/Makefile" ;; "samples/date/Makefile") CONFIG_FILES="$CONFIG_FILES samples/date/Makefile" ;; "samples/cal/Makefile") CONFIG_FILES="$CONFIG_FILES samples/cal/Makefile" ;; @@ -9123,7 +9228,8 @@ if test -f "$srcdir/data/locales/root.txt"; then echo "Spawning Python to generate data/rules.mk..." - PYTHONPATH="$srcdir/data" $PYTHON -m buildtool \ + PYTHONPATH="$srcdir/python" \ + $PYTHON -m icutools.databuilder \ --mode gnumake \ --seqmode parallel \ --src_dir "$srcdir/data" \ @@ -9138,7 +9244,8 @@ touch data/rules.mk fi echo "Spawning Python to generate test/testdata/rules.mk..." - PYTHONPATH="$srcdir/test/testdata:$srcdir/data" $PYTHON -m buildtool \ + PYTHONPATH="$srcdir/python" \ + $PYTHON -m icutools.databuilder \ --mode gnumake \ --seqmode parallel \ --src_dir "$srcdir/test/testdata" \ diff -Nru icu-64.2/source/configure.ac icu-65.1/source/configure.ac --- icu-64.2/source/configure.ac 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/configure.ac 2019-10-03 11:16:41.000000000 +0000 @@ -903,6 +903,14 @@ fi AC_SUBST(U_HAVE_STRTOD_L) +# Check if C++17 std::string_view is available. +AC_LANG_PUSH([C++]) +AC_CHECK_TYPE(std::string_view, [], [], [[#include ]]) +if test "x$ac_cv_type_std__string_view" = xyes; then : + CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRING_VIEW=1" +fi +AC_LANG_POP([C++]) + # Checks for typedefs AC_CHECK_TYPE(int8_t,signed char) AC_CHECK_TYPE(uint8_t,unsigned char) @@ -1124,6 +1132,17 @@ tools=true) ICU_CONDITIONAL(TOOLS, test "$tools" = true) +# Enable/disable fuzzer target tests. +AC_ARG_ENABLE(fuzzer, + [ --enable-fuzzer build ICU's fuzzer test targets [default=no]], + [case "${enableval}" in + yes) fuzzer=true ;; + no) fuzzer=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-fuzzer) ;; + esac], + fuzzer=false) +ICU_CONDITIONAL(FUZZER, test "$fuzzer" = true) + AC_ARG_WITH(data-packaging, [ --with-data-packaging specify how to package ICU data. Possible values: files raw files (.res, etc) @@ -1304,6 +1323,7 @@ if test "${CXX}" = "clang++"; then CLANGCXXFLAGS="-Qunused-arguments -Wno-parentheses-equality" + LIBCXXFLAGS="$LIBCXXFLAGS -Wglobal-constructors" else CLANGCXXFLAGS="" fi @@ -1387,6 +1407,7 @@ test/perf/utfperf/Makefile \ test/perf/utrie2perf/Makefile \ test/perf/leperf/Makefile \ + test/fuzzer/Makefile \ samples/Makefile samples/date/Makefile \ samples/cal/Makefile samples/layout/Makefile]) AC_OUTPUT @@ -1399,7 +1420,8 @@ if test -f "$srcdir/data/locales/root.txt"; then echo "Spawning Python to generate data/rules.mk..." - PYTHONPATH="$srcdir/data" $PYTHON -m buildtool \ + PYTHONPATH="$srcdir/python" \ + $PYTHON -m icutools.databuilder \ --mode gnumake \ --seqmode parallel \ --src_dir "$srcdir/data" \ @@ -1414,7 +1436,8 @@ touch data/rules.mk fi echo "Spawning Python to generate test/testdata/rules.mk..." - PYTHONPATH="$srcdir/test/testdata:$srcdir/data" $PYTHON -m buildtool \ + PYTHONPATH="$srcdir/python" \ + $PYTHON -m icutools.databuilder \ --mode gnumake \ --seqmode parallel \ --src_dir "$srcdir/test/testdata" \ diff -Nru icu-64.2/source/data/BUILDRULES.py icu-65.1/source/data/BUILDRULES.py --- icu-64.2/source/data/BUILDRULES.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/BUILDRULES.py 2019-10-03 11:16:41.000000000 +0000 @@ -5,14 +5,13 @@ # TODO(ICU-20301): Remove this. from __future__ import print_function -from buildtool import * -from buildtool import locale_dependencies -from buildtool import utils -from buildtool.request_types import * +from icutools.databuilder import * +from icutools.databuilder import locale_dependencies +from icutools.databuilder import utils +from icutools.databuilder.request_types import * import os import sys -import xml.etree.ElementTree as ET def generate(config, glob, common_vars): @@ -23,6 +22,7 @@ exit(1) requests += generate_cnvalias(config, glob, common_vars) + requests += generate_ulayout(config, glob, common_vars) requests += generate_confusables(config, glob, common_vars) requests += generate_conversion_mappings(config, glob, common_vars) requests += generate_brkitr_brk(config, glob, common_vars) @@ -32,7 +32,6 @@ requests += generate_coll_ucadata(config, glob, common_vars) requests += generate_full_unicore_data(config, glob, common_vars) requests += generate_unames(config, glob, common_vars) - requests += generate_ulayout(config, glob, common_vars) requests += generate_misc(config, glob, common_vars) requests += generate_curr_supplemental(config, glob, common_vars) requests += generate_translit(config, glob, common_vars) @@ -43,48 +42,49 @@ "locales", None, "icu-locale-deprecates.xml", - True, + config.use_pool_bundle, []) requests += generate_tree(config, glob, common_vars, "curr", "curr", "icu-locale-deprecates.xml", - True, + config.use_pool_bundle, []) requests += generate_tree(config, glob, common_vars, "lang", "lang", "icu-locale-deprecates.xml", - True, + config.use_pool_bundle, []) requests += generate_tree(config, glob, common_vars, "region", "region", "icu-locale-deprecates.xml", - True, + config.use_pool_bundle, []) requests += generate_tree(config, glob, common_vars, "zone", "zone", "icu-locale-deprecates.xml", - True, + config.use_pool_bundle, []) requests += generate_tree(config, glob, common_vars, "unit", "unit", "icu-locale-deprecates.xml", - True, + config.use_pool_bundle, []) requests += generate_tree(config, glob, common_vars, "coll", "coll", "icu-coll-deprecates.xml", + # Never use pool bundle for coll, brkitr, or rbnf False, # Depends on timezoneTypes.res and keyTypeData.res. # TODO: We should not need this dependency to build collation. @@ -95,6 +95,7 @@ "brkitr", "brkitr", "icu-locale-deprecates.xml", + # Never use pool bundle for coll, brkitr, or rbnf False, [DepTarget("brkitr_brk"), DepTarget("dictionaries")]) @@ -102,6 +103,7 @@ "rbnf", "rbnf", "icu-rbnf-deprecates.xml", + # Never use pool bundle for coll, brkitr, or rbnf False, []) @@ -187,7 +189,7 @@ RepeatedExecutionRequest( name = "brkitr_brk", category = "brkitr_rules", - dep_targets = [DepTarget("cnvalias")], + dep_targets = [DepTarget("cnvalias"), DepTarget("ulayout")], input_files = input_files, output_files = output_files, tool = IcuTool("genbrk"), @@ -516,54 +518,48 @@ ) ] - # Generate index txt file - synthetic_locales = set() - deprecates_xml_path = os.path.join(os.path.dirname(__file__), xml_filename) - deprecates_xml = ET.parse(deprecates_xml_path) - for child in deprecates_xml.getroot(): - if child.tag == "alias": - synthetic_locales.add(child.attrib["from"]) - elif child.tag == "emptyLocale": - synthetic_locales.add(child.attrib["locale"]) - else: - raise ValueError("Unknown tag in deprecates XML: %s" % child.tag) - index_input_files = [] + # Generate res_index file + # Exclude the deprecated locale variants and root; see ICU-20628. This + # could be data-driven, but we do not want to perform I/O in this script + # (for example, we do not want to read from an XML file). + excluded_locales = set([ + "ja_JP_TRADITIONAL", + "th_TH_TRADITIONAL", + "de_", + "de__PHONEBOOK", + "es_", + "es__TRADITIONAL", + "root", + ]) + # Put alias locales in a separate structure; see ICU-20627 + alias_locales = set(locale_dependencies.data["aliases"].keys()) + alias_files = [] + installed_files = [] for f in input_files: - file_stem = f.filename[f.filename.rfind("/")+1:-4] - if file_stem == "root": - continue - if file_stem in synthetic_locales: + file_stem = IndexRequest.locale_file_stem(f) + if file_stem in excluded_locales: continue - index_input_files.append(f) + destination = alias_files if file_stem in alias_locales else installed_files + destination.append(f) cldr_version = locale_dependencies.data["cldrVersion"] if sub_dir == "locales" else None index_file_txt = TmpFile("{IN_SUB_DIR}/{INDEX_NAME}.txt".format( IN_SUB_DIR = sub_dir, **common_vars )) - index_file_target_name = "%s_index_txt" % sub_dir - requests += [ - IndexTxtRequest( - name = index_file_target_name, - category = category, - input_files = index_input_files, - output_file = index_file_txt, - cldr_version = cldr_version - ) - ] - - # Generate index res file index_res_file = OutFile("{OUT_PREFIX}{INDEX_NAME}.res".format( OUT_PREFIX = out_prefix, **common_vars )) + index_file_target_name = "%s_index_txt" % sub_dir requests += [ - SingleExecutionRequest( - name = "%s_index_res" % sub_dir, + IndexRequest( + name = index_file_target_name, category = category, - dep_targets = [DepTarget(index_file_target_name)], - input_files = [], - output_files = [index_res_file], - tool = IcuTool("genrb"), + installed_files = installed_files, + alias_files = alias_files, + txt_file = index_file_txt, + output_file = index_res_file, + cldr_version = cldr_version, args = "-s {TMP_DIR}/{IN_SUB_DIR} -d {OUT_DIR}/{OUT_PREFIX} -i {OUT_DIR} " "-k " "{INDEX_NAME}.txt", diff -Nru icu-64.2/source/data/buildtool/comment_stripper.py icu-65.1/source/data/buildtool/comment_stripper.py --- icu-64.2/source/data/buildtool/comment_stripper.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/comment_stripper.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -import io - -class CommentStripper(object): - """Removes lines starting with "//" from a file stream.""" - - def __init__(self, f): - self.f = f - self.state = 0 - - def read(self, size=-1): - bytes = self.f.read(size) - # TODO: Do we need to read more bytes if comments were stripped - # in order to obey the size request? - return "".join(self._strip_comments(bytes)) - - def _strip_comments(self, bytes): - for byte in bytes: - if self.state == 0: - # state 0: start of a line - if byte == "/": - self.state = 1 - elif byte == "\n": - self.state = 0 - yield byte - else: - self.state = 2 - yield byte - elif self.state == 1: - # state 1: read a single '/' - if byte == "/": - self.state = 3 - elif byte == "\n": - self.state = 0 - yield "/" # the one that was skipped - yield "\n" - else: - self.state = 2 - yield "/" # the one that was skipped - yield byte - elif self.state == 2: - # state 2: middle of a line, no comment - if byte == "\n": - self.state = 0 - yield byte - elif self.state == 3: - # state 3: inside a comment - if byte == "\n": - self.state = 0 diff -Nru icu-64.2/source/data/buildtool/filtration.py icu-65.1/source/data/buildtool/filtration.py --- icu-64.2/source/data/buildtool/filtration.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/filtration.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,385 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -# Python 2/3 Compatibility (ICU-20299) -# TODO(ICU-20301): Remove this. -from __future__ import print_function - -from abc import abstractmethod -from collections import defaultdict -import re -import sys - -from . import * -from . import utils -from .locale_dependencies import data as DEPENDENCY_DATA -from .request_types import * - - -# Note: for this to be a proper abstract class, it should extend abc.ABC. -# There is no nice way to do this that works in both Python 2 and 3. -# TODO(ICU-20301): Make this inherit from abc.ABC. -class Filter(object): - @staticmethod - def create_from_json(json_data): - if "filterType" in json_data: - filter_type = json_data["filterType"] - else: - filter_type = "file-stem" - - if filter_type == "file-stem": - return FileStemFilter(json_data) - elif filter_type == "language": - return LanguageFilter(json_data) - elif filter_type == "regex": - return RegexFilter(json_data) - elif filter_type == "exclude": - return ExclusionFilter() - elif filter_type == "union": - return UnionFilter(json_data) - elif filter_type == "locale": - return LocaleFilter(json_data) - else: - print("Error: Unknown filterType option: %s" % filter_type, file=sys.stderr) - return None - - def filter(self, request): - if not request.apply_file_filter(self): - return [] - for file in request.all_input_files(): - assert self.match(file) - return [request] - - @classmethod - def _file_to_file_stem(cls, file): - start = file.filename.rfind("/") - limit = file.filename.rfind(".") - return file.filename[start+1:limit] - - @abstractmethod - def match(self, file): - pass - - -class InclusionFilter(Filter): - def match(self, file): - return True - - -class ExclusionFilter(Filter): - def match(self, file): - return False - - -class WhitelistBlacklistFilter(Filter): - def __init__(self, json_data): - if "whitelist" in json_data: - self.is_whitelist = True - self.whitelist = json_data["whitelist"] - else: - assert "blacklist" in json_data, "Need either whitelist or blacklist: %s" % str(json_data) - self.is_whitelist = False - self.blacklist = json_data["blacklist"] - - def match(self, file): - file_stem = self._file_to_file_stem(file) - return self._should_include(file_stem) - - @abstractmethod - def _should_include(self, file_stem): - pass - - -class FileStemFilter(WhitelistBlacklistFilter): - def _should_include(self, file_stem): - if self.is_whitelist: - return file_stem in self.whitelist - else: - return file_stem not in self.blacklist - - -class LanguageFilter(WhitelistBlacklistFilter): - def _should_include(self, file_stem): - language = file_stem.split("_")[0] - if language == "root": - # Always include root.txt - return True - if self.is_whitelist: - return language in self.whitelist - else: - return language not in self.blacklist - - -class RegexFilter(WhitelistBlacklistFilter): - def __init__(self, *args): - # TODO(ICU-20301): Change this to: super().__init__(*args) - super(RegexFilter, self).__init__(*args) - if self.is_whitelist: - self.whitelist = [re.compile(pat) for pat in self.whitelist] - else: - self.blacklist = [re.compile(pat) for pat in self.blacklist] - - def _should_include(self, file_stem): - if self.is_whitelist: - for pattern in self.whitelist: - if pattern.match(file_stem): - return True - return False - else: - for pattern in self.blacklist: - if pattern.match(file_stem): - return False - return True - - -class UnionFilter(Filter): - def __init__(self, json_data): - # Collect the sub-filters. - self.sub_filters = [] - for filter_json in json_data["unionOf"]: - self.sub_filters.append(Filter.create_from_json(filter_json)) - - def match(self, file): - """Match iff any of the sub-filters match.""" - for filter in self.sub_filters: - if filter.match(file): - return True - return False - - -LANGUAGE_SCRIPT_REGEX = re.compile(r"^([a-z]{2,3})_[A-Z][a-z]{3}$") -LANGUAGE_ONLY_REGEX = re.compile(r"^[a-z]{2,3}$") - -class LocaleFilter(Filter): - def __init__(self, json_data): - self.locales_requested = set() - self.locales_required = set() - self.include_children = json_data.get("includeChildren", True) - self.include_scripts = json_data.get("includeScripts", False) - - # Compute the requested and required locales. - for locale in json_data["whitelist"]: - self._add_locale_and_parents(locale) - - def _add_locale_and_parents(self, locale): - # Store the locale as *requested* - self.locales_requested.add(locale) - # Store the locale and its dependencies as *required* - while locale is not None: - self.locales_required.add(locale) - locale = self._get_parent_locale(locale) - - def match(self, file): - locale = self._file_to_file_stem(file) - - # A locale is *required* if it is *requested* or an ancestor of a - # *requested* locale. - if locale in self.locales_required: - return True - - # Resolve include_scripts and include_children. - return self._match_recursive(locale) - - def _match_recursive(self, locale): - # Base case: return True if we reached a *requested* locale, - # or False if we ascend out of the locale tree. - if locale is None: - return False - if locale in self.locales_requested: - return True - - # Check for alternative scripts. - # This causes sr_Latn to check sr instead of going directly to root. - if self.include_scripts: - match = LANGUAGE_SCRIPT_REGEX.match(locale) - if match and self._match_recursive(match.group(1)): - return True - - # Check if we are a descendant of a *requested* locale. - if self.include_children: - parent = self._get_parent_locale(locale) - if self._match_recursive(parent): - return True - - # No matches. - return False - - @classmethod - def _get_parent_locale(cls, locale): - if locale in DEPENDENCY_DATA["parents"]: - return DEPENDENCY_DATA["parents"][locale] - if locale in DEPENDENCY_DATA["aliases"]: - return DEPENDENCY_DATA["aliases"][locale] - if LANGUAGE_ONLY_REGEX.match(locale): - return "root" - i = locale.rfind("_") - if i < 0: - return None - return locale[:i] - - -def apply_filters(requests, config): - """Runs the filters and returns a new list of requests.""" - requests = _apply_file_filters(requests, config) - requests = _apply_resource_filters(requests, config) - return requests - - -def _apply_file_filters(old_requests, config): - """Filters out entire files.""" - filters = _preprocess_file_filters(old_requests, config) - new_requests = [] - for request in old_requests: - category = request.category - if category in filters: - new_requests += filters[category].filter(request) - else: - new_requests.append(request) - return new_requests - - -def _preprocess_file_filters(requests, config): - all_categories = set( - request.category - for request in requests - ) - all_categories.remove(None) - all_categories = list(sorted(all_categories)) - json_data = config.filters_json_data - filters = {} - for category in all_categories: - if "featureFilters" in json_data and category in json_data["featureFilters"]: - filters[category] = Filter.create_from_json( - json_data["featureFilters"][category] - ) - elif "localeFilter" in json_data and category[-5:] == "_tree": - filters[category] = Filter.create_from_json( - json_data["localeFilter"] - ) - if "featureFilters" in json_data: - for category in json_data["featureFilters"]: - if category not in all_categories: - print("Warning: category %s is not known" % category, file=sys.stderr) - return filters - - -class ResourceFilterInfo(object): - def __init__(self, category): - self.category = category - self.filter_tmp_dir = "filters/%s" % category - self.input_files = None - self.filter_files = None - self.rules_by_file = None - - def apply_to_requests(self, all_requests): - # Call this method only once per list of requests. - assert self.input_files is None - for request in all_requests: - if request.category != self.category: - continue - if not isinstance(request, AbstractExecutionRequest): - continue - if request.tool != IcuTool("genrb"): - continue - if not request.input_files: - continue - self._set_files(request.input_files) - request.dep_targets += [self.filter_files[:]] - arg_str = "--filterDir {TMP_DIR}/%s" % self.filter_tmp_dir - request.args = "%s %s" % (arg_str, request.args) - - # Make sure we found the target request - if self.input_files is None: - print("WARNING: Category not found: %s" % self.category, file=sys.stderr) - self.input_files = [] - self.filter_files = [] - self.rules_by_file = [] - - def _set_files(self, files): - # Note: The input files to genrb for a certain category should always - # be the same. For example, there are often two genrb calls: one for - # --writePoolBundle, and the other for --usePoolBundle. They are both - # expected to have the same list of input files. - if self.input_files is not None: - assert self.input_files == files - return - self.input_files = list(files) - self.filter_files = [ - TmpFile("%s/%s" % (self.filter_tmp_dir, basename)) - for basename in ( - file.filename[file.filename.rfind("/")+1:] - for file in files - ) - ] - self.rules_by_file = [[] for _ in range(len(files))] - - def add_rules(self, file_filter, rules): - for file, rule_list in zip(self.input_files, self.rules_by_file): - if file_filter.match(file): - rule_list += rules - - def make_requests(self): - # Map from rule list to filter files with that rule list - unique_rules = defaultdict(list) - for filter_file, rules in zip(self.filter_files, self.rules_by_file): - unique_rules[tuple(rules)].append(filter_file) - - new_requests = [] - i = 0 - for rules, filter_files in unique_rules.items(): - base_filter_file = filter_files[0] - new_requests += [ - PrintFileRequest( - name = "%s_print_%d" % (self.category, i), - output_file = base_filter_file, - content = self._generate_resource_filter_txt(rules) - ) - ] - i += 1 - for filter_file in filter_files[1:]: - new_requests += [ - CopyRequest( - name = "%s_copy_%d" % (self.category, i), - input_file = base_filter_file, - output_file = filter_file - ) - ] - i += 1 - return new_requests - - @classmethod - def _generate_resource_filter_txt(cls, rules): - result = "# Caution: This file is automatically generated\n\n" - result += "\n".join(rules) - return result - - -def _apply_resource_filters(all_requests, config): - """Creates filters for looking within resource bundle files.""" - json_data = config.filters_json_data - if "resourceFilters" not in json_data: - return all_requests - - collected = {} - for entry in json_data["resourceFilters"]: - if "files" in entry: - file_filter = Filter.create_from_json(entry["files"]) - else: - file_filter = InclusionFilter() - for category in entry["categories"]: - # not defaultdict because we need to pass arguments to the constructor - if category not in collected: - filter_info = ResourceFilterInfo(category) - filter_info.apply_to_requests(all_requests) - collected[category] = filter_info - else: - filter_info = collected[category] - filter_info.add_rules(file_filter, entry["rules"]) - - # Add the filter generation requests to the beginning so that by default - # they are made before genrb gets run (order is required by windirect) - new_requests = [] - for filter_info in collected.values(): - new_requests += filter_info.make_requests() - new_requests += all_requests - return new_requests diff -Nru icu-64.2/source/data/buildtool/filtration_schema.json icu-65.1/source/data/buildtool/filtration_schema.json --- icu-64.2/source/data/buildtool/filtration_schema.json 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/filtration_schema.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -// Copyright (C) 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -{ - "$id": "http://unicode.org/icu-filter-schema", - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "JSON Schema for an ICU data filter file", - "type": "object", - "properties": { - "localeFilter": { "$ref": "#/definitions/filter" }, - "featureFilters": { - "type": "object", - "additionalProperties": { "$ref": "#/definitions/filter" } - }, - "resourceFilters": { - "type": "array", - "items": { - "type": "object", - "properties": { - "categories": { - "type": "array", - "items": { "type": "string" } - }, - "files": { "$ref": "#/definitions/filter" }, - "rules": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[+-]/((\\w+|\\*)(/\\w+|/\\*)*)?$" - } - } - }, - "required": ["categories", "rules"], - "additionalProperties": false - } - }, - "fileReplacements": { - "type": "object", - "properties": { - "directory": { "type": "string" }, - "replacements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "src": { "type": "string" }, - "dest": { "type": "string" } - }, - "additionalProperties": false, - "required": ["src", "dest"] - } - } - }, - "additionalProperties": false, - "required": ["directory", "replacements"] - }, - "collationUCAData": { - "type": "string", - "enum": ["unihan", "implicithan"] - } - }, - "additionalProperties": false, - "definitions": { - "filter": { - "type": "object", - "oneOf": [ - { - "properties": { - "filterType": { - "$ref": "#/definitions/blacklistWhitelistFilterTypes" - }, - "whitelist": { "$ref": "#/definitions/stringList" } - }, - "required": ["whitelist"], - "additionalProperties": false - }, - { - "properties": { - "filterType": { - "$ref": "#/definitions/blacklistWhitelistFilterTypes" - }, - "blacklist": { "$ref": "#/definitions/stringList" } - }, - "required": ["blacklist"], - "additionalProperties": false - }, - { - "properties": { - "filterType": { - "type": "string", - "enum": ["exclude"] - } - }, - "required": ["filterType"], - "additionalProperties": false - }, - { - "properties": { - "filterType": { - "type": "string", - "enum": ["locale"] - }, - "includeChildren": { - "type": "boolean" - }, - "includeScripts": { - "type": "boolean" - }, - "whitelist": { "$ref": "#/definitions/stringList" } - }, - "required": ["filterType", "whitelist"], - "additionalProperties": false - }, - { - "properties": { - "filterType": { - "type": "string", - "enum": ["union"] - }, - "unionOf": { - "type": "array", - "items": { "$ref": "#/definitions/filter" } - } - }, - "required": ["filterType", "unionOf"], - "additionalProperties": false - } - ] - }, - "blacklistWhitelistFilterTypes": { - "type": "string", - "enum": [ - "language", - "regex" - ] - }, - "stringList": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1, - "uniqueItems": true - } - } -} diff -Nru icu-64.2/source/data/buildtool/__init__.py icu-65.1/source/data/buildtool/__init__.py --- icu-64.2/source/data/buildtool/__init__.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -from collections import namedtuple - -LocalFile = namedtuple("LocalFile", ["dirname", "filename"]) -SrcFile = namedtuple("SrcFile", ["filename"]) -InFile = namedtuple("InFile", ["filename"]) -TmpFile = namedtuple("TmpFile", ["filename"]) -OutFile = namedtuple("OutFile", ["filename"]) -PkgFile = namedtuple("PkgFile", ["filename"]) - -IcuTool = namedtuple("IcuTool", ["name"]) -SystemTool = namedtuple("SystemTool", ["name"]) - -DepTarget = namedtuple("DepTarget", ["name"]) diff -Nru icu-64.2/source/data/buildtool/locale_dependencies.py icu-65.1/source/data/buildtool/locale_dependencies.py --- icu-64.2/source/data/buildtool/locale_dependencies.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/locale_dependencies.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,224 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2019 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html#License - -data = { - "cldrVersion": "35.1", - "aliases": { - "ars": "ar_SA", - "az_AZ": "az_Latn_AZ", - "bs_BA": "bs_Latn_BA", - "en_NH": "en_VU", - "en_RH": "en_ZW", - "ff_CM": "ff_Latn_CM", - "ff_GN": "ff_Latn_GN", - "ff_MR": "ff_Latn_MR", - "ff_SN": "ff_Latn_SN", - "in": "id", - "in_ID": "id_ID", - "iw": "he", - "iw_IL": "he_IL", - "mo": "ro", - "no_NO": "nb_NO", - "no_NO_NY": "nn_NO", - "no": "nb", - "pa_IN": "pa_Guru_IN", - "pa_PK": "pa_Arab_PK", - "sh": "sr_Latn", - "sh_BA": "sr_Latn_BA", - "sh_CS": "sr_Latn_RS", - "sh_YU": "sr_Latn_RS", - "shi_MA": "shi_Tfng_MA", - "sr_BA": "sr_Cyrl_BA", - "sr_CS": "sr_Cyrl_RS", - "sr_ME": "sr_Latn_ME", - "sr_RS": "sr_Cyrl_RS", - "sr_XK": "sr_Cyrl_XK", - "sr_YU": "sr_Cyrl_RS", - "sr_Cyrl_YU": "sr_Cyrl_RS", - "sr_Cyrl_CS": "sr_Cyrl_RS", - "sr_Latn_YU": "sr_Latn_RS", - "sr_Latn_CS": "sr_Latn_RS", - "tl": "fil", - "tl_PH": "fil_PH", - "uz_AF": "uz_Arab_AF", - "uz_UZ": "uz_Latn_UZ", - "vai_LR": "vai_Vaii_LR", - "yue_CN": "yue_Hans_CN", - "yue_HK": "yue_Hant_HK", - "zh_CN": "zh_Hans_CN", - "zh_HK": "zh_Hant_HK", - "zh_MO": "zh_Hant_MO", - "zh_SG": "zh_Hans_SG", - "zh_TW": "zh_Hant_TW" - }, - "parents": { - "ff_Adlm": "root", - "en_CM": "en_001", - "so_Arab": "root", - "en_KY": "en_001", - "en_TC": "en_001", - "yue_Hans": "root", - "en_CX": "en_001", - "es_EC": "es_419", - "es_US": "es_419", - "byn_Latn": "root", - "en_CY": "en_001", - "en_LC": "en_001", - "en_TK": "en_001", - "tg_Arab": "root", - "es_UY": "es_419", - "ky_Latn": "root", - "en_TO": "en_001", - "en_TT": "en_001", - "en_DE": "en_150", - "es_MX": "es_419", - "en_TV": "en_001", - "en_DG": "en_001", - "pt_ST": "pt_PT", - "en_DM": "en_001", - "en_LR": "en_001", - "en_TZ": "en_001", - "en_LS": "en_001", - "en_DK": "en_150", - "blt_Latn": "root", - "es_VE": "es_419", - "es_NI": "es_419", - "sd_Khoj": "root", - "pt_AO": "pt_PT", - "en_UG": "en_001", - "yo_Arab": "root", - "dje_Arab": "root", - "en_MG": "en_001", - "en_MO": "en_001", - "en_MU": "en_001", - "en_MS": "en_001", - "en_MT": "en_001", - "shi_Latn": "root", - "es_BR": "es_419", - "en_AU": "en_001", - "en_ZM": "en_001", - "en_AT": "en_150", - "es_BZ": "es_419", - "uz_Arab": "root", - "az_Cyrl": "root", - "es_SV": "es_419", - "en_ZW": "en_001", - "en_JE": "en_001", - "en_BB": "en_001", - "sd_Deva": "root", - "pa_Arab": "root", - "en_RW": "en_001", - "es_CO": "es_419", - "en_JM": "en_001", - "en_BE": "en_150", - "dyo_Arab": "root", - "es_CL": "es_419", - "en_BM": "en_001", - "en_SC": "en_001", - "es_CR": "es_419", - "en_150": "en_001", - "en_BS": "en_001", - "en_SD": "en_001", - "pt_GQ": "pt_PT", - "en_SB": "en_001", - "es_CU": "es_419", - "en_SG": "en_001", - "uz_Cyrl": "root", - "en_BW": "en_001", - "en_SH": "en_001", - "en_SE": "en_150", - "pt_GW": "pt_PT", - "ky_Arab": "root", - "en_BZ": "en_001", - "en_SL": "en_001", - "en_SI": "en_150", - "ff_Arab": "root", - "en_KE": "en_001", - "bm_Nkoo": "root", - "en_CC": "en_001", - "en_SS": "en_001", - "iu_Latn": "root", - "en_CA": "en_001", - "en_KI": "en_001", - "es_DO": "es_419", - "en_SX": "en_001", - "en_CH": "en_150", - "en_KN": "en_001", - "en_CK": "en_001", - "ml_Arab": "root", - "en_SZ": "en_001", - "pt_FR": "pt_PT", - "ug_Cyrl": "root", - "en_GY": "en_001", - "en_PH": "en_001", - "en_PG": "en_001", - "en_PK": "en_001", - "cu_Glag": "root", - "en_PN": "en_001", - "kk_Arab": "root", - "en_HK": "en_001", - "zh_Hant": "root", - "en_PW": "en_001", - "es_AR": "es_419", - "pt_MZ": "pt_PT", - "sd_Sind": "root", - "en_Shaw": "root", - "en_IE": "en_001", - "ms_Arab": "root", - "en_IM": "en_001", - "en_IN": "en_001", - "es_BO": "es_419", - "en_IL": "en_001", - "en_AI": "en_001", - "az_Arab": "root", - "en_AG": "en_001", - "en_IO": "en_001", - "en_ZA": "en_001", - "en_MY": "en_001", - "en_ER": "en_001", - "en_VC": "en_001", - "mn_Mong": "root", - "vai_Latn": "root", - "en_MW": "en_001", - "pt_LU": "pt_PT", - "bs_Cyrl": "root", - "en_VG": "en_001", - "en_NA": "en_001", - "en_NF": "en_001", - "en_NG": "en_001", - "ha_Arab": "root", - "en_NL": "en_150", - "zh_Hant_MO": "zh_Hant_HK", - "en_VU": "en_001", - "en_FJ": "en_001", - "en_NR": "en_001", - "en_FK": "en_001", - "es_GT": "es_419", - "en_FI": "en_150", - "ku_Arab": "root", - "pt_MO": "pt_PT", - "en_FM": "en_001", - "en_NU": "en_001", - "en_NZ": "en_001", - "pt_CH": "pt_PT", - "en_Dsrt": "root", - "es_PE": "es_419", - "es_PA": "es_419", - "pt_CV": "pt_PT", - "wo_Arab": "root", - "en_WS": "en_001", - "en_GD": "en_001", - "en_GB": "en_001", - "es_HN": "es_419", - "pt_TL": "pt_PT", - "en_GG": "en_001", - "en_GH": "en_001", - "es_PR": "es_419", - "sw_Arab": "root", - "en_GI": "en_001", - "sr_Latn": "root", - "en_GM": "en_001", - "es_PY": "es_419" - } -} diff -Nru icu-64.2/source/data/buildtool/__main__.py icu-65.1/source/data/buildtool/__main__.py --- icu-64.2/source/data/buildtool/__main__.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/__main__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,292 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -# Python 2/3 Compatibility (ICU-20299) -# TODO(ICU-20301): Remove this. -from __future__ import print_function - -import argparse -import glob as pyglob -import json -import os -import sys - -from . import * -from .comment_stripper import CommentStripper -from .request_types import CopyRequest -from .renderers import makefile, unix_exec, windows_exec -from . import filtration, utils -import BUILDRULES - -flag_parser = argparse.ArgumentParser( - description = """Generates rules for building ICU binary data files from text -and other input files in source control. - -Use the --mode option to declare how to execute those rules, either exporting -the rules to a Makefile or spawning child processes to run them immediately: - - --mode=gnumake prints a Makefile to standard out. - --mode=unix-exec spawns child processes in a Unix-like environment. - --mode=windows-exec spawns child processes in a Windows-like environment. - -Tips for --mode=unix-exec -========================= - -Create two empty directories for out_dir and tmp_dir. They will get filled -with a lot of intermediate files. - -Set LD_LIBRARY_PATH to include the lib directory. e.g., from icu4c/source: - - $ LD_LIBRARY_PATH=lib PYTHONPATH=data python3 -m buildtool ... - -Once buildtool finishes, you have compiled the data, but you have not packaged -it into a .dat or .so file. This is done by the separate pkgdata tool in bin. -Read the docs of pkgdata: - - $ LD_LIBRARY_PATH=lib ./bin/pkgdata --help - -Example command line to call pkgdata: - - $ LD_LIBRARY_PATH=lib ./bin/pkgdata -m common -p icudt63l -c \\ - -O data/icupkg.inc -s $OUTDIR -d $TMPDIR $TMPDIR/icudata.lst - -where $OUTDIR and $TMPDIR are your out and tmp directories, respectively. -The above command will create icudt63l.dat in the tmpdir. - -Command-Line Arguments -====================== -""", - formatter_class = argparse.RawDescriptionHelpFormatter -) - -arg_group_required = flag_parser.add_argument_group("required arguments") -arg_group_required.add_argument( - "--mode", - help = "What to do with the generated rules.", - choices = ["gnumake", "unix-exec", "windows-exec"], - required = True -) - -flag_parser.add_argument( - "--src_dir", - help = "Path to data source folder (icu4c/source/data).", - default = "." -) -flag_parser.add_argument( - "--filter_file", - metavar = "PATH", - help = "Path to an ICU data filter JSON file.", - default = None -) -flag_parser.add_argument( - "--include_uni_core_data", - help = "Include the full Unicode core data in the dat file.", - default = False, - action = "store_true" -) -flag_parser.add_argument( - "--seqmode", - help = "Whether to optimize rules to be run sequentially (fewer threads) or in parallel (many threads). Defaults to 'sequential', which is better for unix-exec and windows-exec modes. 'parallel' is often better for massively parallel build systems.", - choices = ["sequential", "parallel"], - default = "sequential" -) - -arg_group_exec = flag_parser.add_argument_group("arguments for unix-exec and windows-exec modes") -arg_group_exec.add_argument( - "--out_dir", - help = "Path to where to save output data files.", - default = "icudata" -) -arg_group_exec.add_argument( - "--tmp_dir", - help = "Path to where to save temporary files.", - default = "icutmp" -) -arg_group_exec.add_argument( - "--tool_dir", - help = "Path to where to find binary tools (genrb, etc).", - default = "../bin" -) -arg_group_exec.add_argument( - "--tool_cfg", - help = "The build configuration of the tools. Used in 'windows-exec' mode only.", - default = "x86/Debug" -) - - -class Config(object): - - def __init__(self, args): - # Process arguments - self.max_parallel = (args.seqmode == "parallel") - - # Boolean: Whether to include core Unicode data files in the .dat file - self.include_uni_core_data = args.include_uni_core_data - - # Default fields before processing filter file - self.filters_json_data = {} - - # Process filter file - if args.filter_file: - try: - with open(args.filter_file, "r") as f: - print("Note: Applying filters from %s." % args.filter_file, file=sys.stderr) - self._parse_filter_file(f) - except IOError: - print("Error: Could not read filter file %s." % args.filter_file, file=sys.stderr) - exit(1) - - # Either "unihan" or "implicithan" - self.coll_han_type = "unihan" - if "collationUCAData" in self.filters_json_data: - self.coll_han_type = self.filters_json_data["collationUCAData"] - - def _parse_filter_file(self, f): - # Use the Hjson parser if it is available; otherwise, use vanilla JSON. - try: - import hjson - self.filters_json_data = hjson.load(f) - except ImportError: - self.filters_json_data = json.load(CommentStripper(f)) - - # Optionally pre-validate the JSON schema before further processing. - # Some schema errors will be caught later, but this step ensures - # maximal validity. - try: - import jsonschema - schema_path = os.path.join(os.path.dirname(__file__), "filtration_schema.json") - with open(schema_path) as schema_f: - schema = json.load(CommentStripper(schema_f)) - validator = jsonschema.Draft4Validator(schema) - for error in validator.iter_errors(self.filters_json_data, schema): - print("WARNING: ICU data filter JSON file:", error.message, - "at", "".join( - "[%d]" % part if isinstance(part, int) else ".%s" % part - for part in error.absolute_path - ), - file=sys.stderr) - except ImportError: - print("Tip: to validate your filter file, install the Pip package 'jsonschema'", file=sys.stderr) - pass - - -def add_copy_input_requests(requests, config, common_vars): - files_to_copy = set() - for request in requests: - for f in request.all_input_files(): - if isinstance(f, InFile): - files_to_copy.add(f) - - result = [] - id = 0 - - json_data = config.filters_json_data["fileReplacements"] - dirname = json_data["directory"] - for directive in json_data["replacements"]: - input_file = LocalFile(dirname, directive["src"]) - output_file = InFile(directive["dest"]) - result += [ - CopyRequest( - name = "input_copy_%d" % id, - input_file = input_file, - output_file = output_file - ) - ] - files_to_copy.remove(output_file) - id += 1 - - for f in files_to_copy: - result += [ - CopyRequest( - name = "input_copy_%d" % id, - input_file = SrcFile(f.filename), - output_file = f - ) - ] - id += 1 - - result += requests - return result - - -def main(): - args = flag_parser.parse_args() - config = Config(args) - - if args.mode == "gnumake": - makefile_vars = { - "SRC_DIR": "$(srcdir)", - "IN_DIR": "$(srcdir)", - "INDEX_NAME": "res_index" - } - makefile_env = ["ICUDATA_CHAR", "OUT_DIR", "TMP_DIR"] - common = { - key: "$(%s)" % key - for key in list(makefile_vars.keys()) + makefile_env - } - common["GLOB_DIR"] = args.src_dir - else: - common = { - # GLOB_DIR is used now, whereas IN_DIR is used during execution phase. - # There is no useful distinction in unix-exec or windows-exec mode. - "GLOB_DIR": args.src_dir, - "SRC_DIR": args.src_dir, - "IN_DIR": args.src_dir, - "OUT_DIR": args.out_dir, - "TMP_DIR": args.tmp_dir, - "INDEX_NAME": "res_index", - # TODO: Pull this from configure script: - "ICUDATA_CHAR": "l" - } - - def glob(pattern): - result_paths = pyglob.glob("{GLOB_DIR}/{PATTERN}".format( - GLOB_DIR = args.src_dir, - PATTERN = pattern - )) - # For the purposes of buildtool, force Unix-style directory separators. - return [v.replace("\\", "/")[len(args.src_dir)+1:] for v in sorted(result_paths)] - - requests = BUILDRULES.generate(config, glob, common) - requests = filtration.apply_filters(requests, config) - requests = utils.flatten_requests(requests, config, common) - - if "fileReplacements" in config.filters_json_data: - tmp_in_dir = "{TMP_DIR}/in".format(**common) - if makefile_vars: - makefile_vars["IN_DIR"] = tmp_in_dir - else: - common["IN_DIR"] = tmp_in_dir - requests = add_copy_input_requests(requests, config, common) - - build_dirs = utils.compute_directories(requests) - - if args.mode == "gnumake": - print(makefile.get_gnumake_rules( - build_dirs, - requests, - makefile_vars, - common_vars = common - )) - elif args.mode == "windows-exec": - return windows_exec.run( - build_dirs = build_dirs, - requests = requests, - common_vars = common, - tool_dir = args.tool_dir, - tool_cfg = args.tool_cfg - ) - elif args.mode == "unix-exec": - return unix_exec.run( - build_dirs = build_dirs, - requests = requests, - common_vars = common, - tool_dir = args.tool_dir - ) - else: - print("Mode not supported: %s" % args.mode) - return 1 - return 0 - -if __name__ == "__main__": - exit(main()) diff -Nru icu-64.2/source/data/buildtool/renderers/common_exec.py icu-65.1/source/data/buildtool/renderers/common_exec.py --- icu-64.2/source/data/buildtool/renderers/common_exec.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/renderers/common_exec.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -from . import * -from .. import * -from .. import utils -from ..request_types import * - -import os -import shutil -import subprocess - -def run(build_dirs, requests, common_vars, **kwargs): - for bd in build_dirs: - os.makedirs(bd.format(**common_vars), exist_ok=True) - for request in requests: - status = run_helper(request, common_vars, **kwargs) - if status != 0: - print("!!! ERROR executing above command line: exit code %d" % status) - return 1 - print("All data build commands executed") - return 0 - -def run_helper(request, common_vars, is_windows, tool_dir, tool_cfg=None, **kwargs): - if isinstance(request, PrintFileRequest): - output_path = "{DIRNAME}/{FILENAME}".format( - DIRNAME = utils.dir_for(request.output_file).format(**common_vars), - FILENAME = request.output_file.filename, - ) - print("Printing to file: %s" % output_path) - with open(output_path, "w") as f: - f.write(request.content) - return 0 - if isinstance(request, CopyRequest): - input_path = "{DIRNAME}/{FILENAME}".format( - DIRNAME = utils.dir_for(request.input_file).format(**common_vars), - FILENAME = request.input_file.filename, - ) - output_path = "{DIRNAME}/{FILENAME}".format( - DIRNAME = utils.dir_for(request.output_file).format(**common_vars), - FILENAME = request.output_file.filename, - ) - print("Copying file to: %s" % output_path) - shutil.copyfile(input_path, output_path) - return 0 - if isinstance(request, VariableRequest): - # No-op - return 0 - - assert isinstance(request.tool, IcuTool) - if is_windows: - cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL_CFG}/{TOOL}.exe {{ARGS}}".format( - TOOL_DIR = tool_dir, - TOOL_CFG = tool_cfg, - TOOL = request.tool.name, - **common_vars - ) - else: - cmd_template = "{TOOL_DIR}/{TOOL} {{ARGS}}".format( - TOOL_DIR = tool_dir, - TOOL = request.tool.name, - **common_vars - ) - - if isinstance(request, RepeatedExecutionRequest): - for loop_vars in utils.repeated_execution_request_looper(request): - command_line = utils.format_repeated_request_command( - request, - cmd_template, - loop_vars, - common_vars - ) - if is_windows: - # Note: this / to \ substitution may be too aggressive? - command_line = command_line.replace("/", "\\") - print("Running: %s" % command_line) - res = subprocess.run(command_line, shell=True) - if res.returncode != 0: - return res.returncode - return 0 - if isinstance(request, SingleExecutionRequest): - command_line = utils.format_single_request_command( - request, - cmd_template, - common_vars - ) - if is_windows: - # Note: this / to \ substitution may be too aggressive? - command_line = command_line.replace("/", "\\") - print("Running: %s" % command_line) - res = subprocess.run(command_line, shell=True) - return res.returncode - assert False diff -Nru icu-64.2/source/data/buildtool/renderers/__init__.py icu-65.1/source/data/buildtool/renderers/__init__.py --- icu-64.2/source/data/buildtool/renderers/__init__.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/renderers/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -from collections import namedtuple - -MakeRule = namedtuple("MakeRule", ["name", "dep_literals", "dep_files", "output_file", "cmds"]) - -MakeFilesVar = namedtuple("MakeFilesVar", ["name", "files"]) - -MakeStringVar = namedtuple("MakeStringVar", ["name", "content"]) diff -Nru icu-64.2/source/data/buildtool/renderers/makefile.py icu-65.1/source/data/buildtool/renderers/makefile.py --- icu-64.2/source/data/buildtool/renderers/makefile.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/renderers/makefile.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,245 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -# Python 2/3 Compatibility (ICU-20299) -# TODO(ICU-20301): Remove this. -from __future__ import print_function - -from . import * -from .. import * -from .. import utils -from ..request_types import * - -def get_gnumake_rules(build_dirs, requests, makefile_vars, **kwargs): - makefile_string = "" - - # Common Variables - common_vars = kwargs["common_vars"] - for key, value in sorted(makefile_vars.items()): - makefile_string += "{KEY} = {VALUE}\n".format( - KEY = key, - VALUE = value - ) - makefile_string += "\n" - - # Directories - dirs_timestamp_file = "{TMP_DIR}/dirs.timestamp".format(**common_vars) - makefile_string += "DIRS = {TIMESTAMP_FILE}\n\n".format( - TIMESTAMP_FILE = dirs_timestamp_file - ) - makefile_string += "{TIMESTAMP_FILE}:\n\t$(MKINSTALLDIRS) {ALL_DIRS}\n\techo timestamp > {TIMESTAMP_FILE}\n\n".format( - TIMESTAMP_FILE = dirs_timestamp_file, - ALL_DIRS = " ".join(build_dirs).format(**common_vars) - ) - - # Generate Rules - make_rules = [] - for request in requests: - make_rules += get_gnumake_rules_helper(request, **kwargs) - - # Main Commands - for rule in make_rules: - if isinstance(rule, MakeFilesVar): - makefile_string += "{NAME} = {FILE_LIST}\n\n".format( - NAME = rule.name, - FILE_LIST = files_to_makefile(rule.files, wrap = True, **kwargs), - ) - continue - - if isinstance(rule, MakeStringVar): - makefile_string += "define {NAME}\n{CONTENT}\nendef\nexport {NAME}\n\n".format( - NAME = rule.name, - CONTENT = rule.content - ) - continue - - assert isinstance(rule, MakeRule) - header_line = "{OUT_FILE}: {DEP_FILES} {DEP_LITERALS} | $(DIRS)".format( - OUT_FILE = files_to_makefile([rule.output_file], **kwargs), - DEP_FILES = files_to_makefile(rule.dep_files, wrap = True, **kwargs), - DEP_LITERALS = " ".join(rule.dep_literals) - ) - - if len(rule.cmds) == 0: - makefile_string += "%s\n\n" % header_line - continue - - makefile_string += "{HEADER_LINE}\n{RULE_LINES}\n\n".format( - HEADER_LINE = header_line, - RULE_LINES = "\n".join("\t%s" % cmd for cmd in rule.cmds) - ) - - return makefile_string - -def files_to_makefile(files, common_vars, wrap = False, **kwargs): - if len(files) == 0: - return "" - dirnames = [utils.dir_for(file).format(**common_vars) for file in files] - join_str = " \\\n\t\t" if wrap and len(files) > 2 else " " - if len(files) == 1: - return "%s/%s" % (dirnames[0], files[0].filename) - elif len(set(dirnames)) == 1: - return "$(addprefix %s/,%s)" % (dirnames[0], join_str.join(file.filename for file in files)) - else: - return join_str.join("%s/%s" % (d, f.filename) for d,f in zip(dirnames, files)) - -def get_gnumake_rules_helper(request, common_vars, **kwargs): - - if isinstance(request, PrintFileRequest): - var_name = "%s_CONTENT" % request.name.upper() - return [ - MakeStringVar( - name = var_name, - content = request.content - ), - MakeRule( - name = request.name, - dep_literals = [], - dep_files = [], - output_file = request.output_file, - cmds = [ - "echo \"$${VAR_NAME}\" > {MAKEFILENAME}".format( - VAR_NAME = var_name, - MAKEFILENAME = files_to_makefile([request.output_file], common_vars), - **common_vars - ) - ] - ) - ] - - - if isinstance(request, CopyRequest): - return [ - MakeRule( - name = request.name, - dep_literals = [], - dep_files = [request.input_file], - output_file = request.output_file, - cmds = ["cp %s %s" % ( - files_to_makefile([request.input_file], common_vars), - files_to_makefile([request.output_file], common_vars)) - ] - ) - ] - - if isinstance(request, VariableRequest): - return [ - MakeFilesVar( - name = request.name.upper(), - files = request.input_files - ) - ] - - if request.tool.name == "make": - cmd_template = "$(MAKE) {ARGS}" - elif request.tool.name == "gentest": - cmd_template = "$(INVOKE) $(GENTEST) {ARGS}" - else: - assert isinstance(request.tool, IcuTool) - cmd_template = "$(INVOKE) $(TOOLBINDIR)/{TOOL} {{ARGS}}".format( - TOOL = request.tool.name - ) - - if isinstance(request, SingleExecutionRequest): - cmd = utils.format_single_request_command(request, cmd_template, common_vars) - dep_files = request.all_input_files() - - if len(request.output_files) > 1: - # Special case for multiple output files: Makefile rules should have only one - # output file apiece. More information: - # https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html - timestamp_var_name = "%s_ALL" % request.name.upper() - timestamp_file = TmpFile("%s.timestamp" % request.name) - rules = [ - MakeFilesVar( - name = timestamp_var_name, - files = [timestamp_file] - ), - MakeRule( - name = "%s_all" % request.name, - dep_literals = [], - dep_files = dep_files, - output_file = timestamp_file, - cmds = [ - cmd, - "echo timestamp > {MAKEFILENAME}".format( - MAKEFILENAME = files_to_makefile([timestamp_file], common_vars) - ) - ] - ) - ] - for i, file in enumerate(request.output_files): - rules += [ - MakeRule( - name = "%s_%d" % (request.name, i), - dep_literals = ["$(%s)" % timestamp_var_name], - dep_files = [], - output_file = file, - cmds = [] - ) - ] - return rules - - elif len(dep_files) > 5: - # For nicer printing, for long input lists, use a helper variable. - dep_var_name = "%s_DEPS" % request.name.upper() - return [ - MakeFilesVar( - name = dep_var_name, - files = dep_files - ), - MakeRule( - name = request.name, - dep_literals = ["$(%s)" % dep_var_name], - dep_files = [], - output_file = request.output_files[0], - cmds = [cmd] - ) - ] - - else: - return [ - MakeRule( - name = request.name, - dep_literals = [], - dep_files = dep_files, - output_file = request.output_files[0], - cmds = [cmd] - ) - ] - - if isinstance(request, RepeatedExecutionRequest): - rules = [] - dep_literals = [] - # To keep from repeating the same dep files many times, make a variable. - if len(request.common_dep_files) > 0: - dep_var_name = "%s_DEPS" % request.name.upper() - dep_literals = ["$(%s)" % dep_var_name] - rules += [ - MakeFilesVar( - name = dep_var_name, - files = request.common_dep_files - ) - ] - # Add a rule for each individual file. - for loop_vars in utils.repeated_execution_request_looper(request): - (_, specific_dep_files, input_file, output_file) = loop_vars - name_suffix = input_file[input_file.filename.rfind("/")+1:input_file.filename.rfind(".")] - cmd = utils.format_repeated_request_command( - request, - cmd_template, - loop_vars, - common_vars - ) - rules += [ - MakeRule( - name = "%s_%s" % (request.name, name_suffix), - dep_literals = dep_literals, - dep_files = specific_dep_files + [input_file], - output_file = output_file, - cmds = [cmd] - ) - ] - return rules - - assert False diff -Nru icu-64.2/source/data/buildtool/renderers/unix_exec.py icu-65.1/source/data/buildtool/renderers/unix_exec.py --- icu-64.2/source/data/buildtool/renderers/unix_exec.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/renderers/unix_exec.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -from . import common_exec - -def run(**kwargs): - return common_exec.run(is_windows=False, **kwargs) diff -Nru icu-64.2/source/data/buildtool/renderers/windows_exec.py icu-65.1/source/data/buildtool/renderers/windows_exec.py --- icu-64.2/source/data/buildtool/renderers/windows_exec.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/renderers/windows_exec.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -from . import common_exec - -def run(**kwargs): - return common_exec.run(is_windows=True, **kwargs) diff -Nru icu-64.2/source/data/buildtool/request_types.py icu-65.1/source/data/buildtool/request_types.py --- icu-64.2/source/data/buildtool/request_types.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/request_types.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,331 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -# Python 2/3 Compatibility (ICU-20299) -# TODO(ICU-20301): Remove this. -from __future__ import print_function - -from abc import abstractmethod -import copy -import sys - -from . import * -from . import utils - - -# TODO(ICU-20301): Remove arguments from all instances of super() in this file - -# Note: for this to be a proper abstract class, it should extend abc.ABC. -# There is no nice way to do this that works in both Python 2 and 3. -# TODO(ICU-20301): Make this inherit from abc.ABC. -class AbstractRequest(object): - def __init__(self, **kwargs): - - # Used for identification purposes - self.name = None - - # The filter category that applies to this request - self.category = None - - self._set_fields(kwargs) - - def _set_fields(self, kwargs): - for key, value in list(kwargs.items()): - if hasattr(self, key): - if isinstance(value, list): - value = copy.copy(value) - elif isinstance(value, dict): - value = copy.deepcopy(value) - setattr(self, key, value) - else: - raise ValueError("Unknown argument: %s" % key) - - def apply_file_filter(self, filter): - """ - Returns True if this request still has input files after filtering, - or False if the request is "empty" after filtering. - """ - return True - - def flatten(self, config, all_requests, common_vars): - return [self] - - def all_input_files(self): - return [] - - def all_output_files(self): - return [] - - -class AbstractExecutionRequest(AbstractRequest): - def __init__(self, **kwargs): - - # Names of targets (requests) or files that this request depends on. - # The entries of dep_targets may be any of the following types: - # - # 1. DepTarget, for the output of an execution request. - # 2. InFile, TmpFile, etc., for a specific file. - # 3. A list of InFile, TmpFile, etc., where the list is the same - # length as self.input_files and self.output_files. - # - # In cases 1 and 2, the dependency is added to all rules that the - # request generates. In case 3, the dependency is added only to the - # rule that generates the output file at the same array index. - self.dep_targets = [] - - # Computed during self.flatten(); don't edit directly. - self.common_dep_files = [] - - # Primary input files - self.input_files = [] - - # Output files; for some subclasses, this must be the same length - # as input_files - self.output_files = [] - - # What tool to execute - self.tool = None - - # Argument string to pass to the tool with optional placeholders - self.args = "" - - # Placeholders to substitute into the argument string; if any of these - # have a list type, the list must be equal in length to input_files - self.format_with = {} - - super(AbstractExecutionRequest, self).__init__(**kwargs) - - def apply_file_filter(self, filter): - i = 0 - while i < len(self.input_files): - if filter.match(self.input_files[i]): - i += 1 - continue - self._del_at(i) - return i > 0 - - def _del_at(self, i): - del self.input_files[i] - for _, v in self.format_with.items(): - if isinstance(v, list): - assert len(v) == len(self.input_files) + 1 - del v[i] - for v in self.dep_targets: - if isinstance(v, list): - assert len(v) == len(self.input_files) + 1 - del v[i] - - def flatten(self, config, all_requests, common_vars): - self._dep_targets_to_files(all_requests) - return super(AbstractExecutionRequest, self).flatten(config, all_requests, common_vars) - - def _dep_targets_to_files(self, all_requests): - if not self.dep_targets: - return - for dep_target in self.dep_targets: - if isinstance(dep_target, list): - if hasattr(self, "specific_dep_files"): - assert len(dep_target) == len(self.specific_dep_files) - for file, out_list in zip(dep_target, self.specific_dep_files): - assert hasattr(file, "filename") - out_list.append(file) - else: - self.common_dep_files += dep_target - continue - if not isinstance(dep_target, DepTarget): - # Copy file entries directly to dep_files. - assert hasattr(dep_target, "filename") - self.common_dep_files.append(dep_target) - continue - # For DepTarget entries, search for the target. - for request in all_requests: - if request.name == dep_target.name: - self.common_dep_files += request.all_output_files() - break - else: - print("Warning: Unable to find target %s, a dependency of %s" % ( - dep_target.name, - self.name - ), file=sys.stderr) - - def all_input_files(self): - return self.common_dep_files + self.input_files - - def all_output_files(self): - return self.output_files - - -class SingleExecutionRequest(AbstractExecutionRequest): - def __init__(self, **kwargs): - super(SingleExecutionRequest, self).__init__(**kwargs) - - -class RepeatedExecutionRequest(AbstractExecutionRequest): - def __init__(self, **kwargs): - - # Placeholders to substitute into the argument string unique to each - # iteration; all values must be lists equal in length to input_files - self.repeat_with = {} - - # Lists for dep files that are specific to individual resource bundle files - self.specific_dep_files = [[] for _ in range(len(kwargs["input_files"]))] - - super(RepeatedExecutionRequest, self).__init__(**kwargs) - - def _del_at(self, i): - super(RepeatedExecutionRequest, self)._del_at(i) - del self.output_files[i] - for _, v in self.repeat_with.items(): - if isinstance(v, list): - del v[i] - - def all_input_files(self): - files = super(RepeatedExecutionRequest, self).all_input_files() - for specific_file_list in self.specific_dep_files: - files += specific_file_list - return files - - -class RepeatedOrSingleExecutionRequest(AbstractExecutionRequest): - def __init__(self, **kwargs): - self.repeat_with = {} - super(RepeatedOrSingleExecutionRequest, self).__init__(**kwargs) - - def flatten(self, config, all_requests, common_vars): - if config.max_parallel: - new_request = RepeatedExecutionRequest( - name = self.name, - category = self.category, - dep_targets = self.dep_targets, - input_files = self.input_files, - output_files = self.output_files, - tool = self.tool, - args = self.args, - format_with = self.format_with, - repeat_with = self.repeat_with - ) - else: - new_request = SingleExecutionRequest( - name = self.name, - category = self.category, - dep_targets = self.dep_targets, - input_files = self.input_files, - output_files = self.output_files, - tool = self.tool, - args = self.args, - format_with = utils.concat_dicts(self.format_with, self.repeat_with) - ) - return new_request.flatten(config, all_requests, common_vars) - - def _del_at(self, i): - super(RepeatedOrSingleExecutionRequest, self)._del_at(i) - del self.output_files[i] - for _, v in self.repeat_with.items(): - if isinstance(v, list): - del v[i] - - -class PrintFileRequest(AbstractRequest): - def __init__(self, **kwargs): - self.output_file = None - self.content = None - super(PrintFileRequest, self).__init__(**kwargs) - - def all_output_files(self): - return [self.output_file] - - -class CopyRequest(AbstractRequest): - def __init__(self, **kwargs): - self.input_file = None - self.output_file = None - super(CopyRequest, self).__init__(**kwargs) - - def all_input_files(self): - return [self.input_file] - - def all_output_files(self): - return [self.output_file] - - -class VariableRequest(AbstractRequest): - def __init__(self, **kwargs): - self.input_files = [] - super(VariableRequest, self).__init__(**kwargs) - - def all_input_files(self): - return self.input_files - - -class ListRequest(AbstractRequest): - def __init__(self, **kwargs): - self.variable_name = None - self.output_file = None - self.include_tmp = None - super(ListRequest, self).__init__(**kwargs) - - def flatten(self, config, all_requests, common_vars): - list_files = list(sorted(utils.get_all_output_files(all_requests))) - if self.include_tmp: - variable_files = list(sorted(utils.get_all_output_files(all_requests, include_tmp=True))) - else: - # Always include the list file itself - variable_files = list_files + [self.output_file] - return PrintFileRequest( - name = self.name, - output_file = self.output_file, - content = "\n".join(file.filename for file in list_files) - ).flatten(config, all_requests, common_vars) + VariableRequest( - name = self.variable_name, - input_files = variable_files - ).flatten(config, all_requests, common_vars) - - def all_output_files(self): - return [self.output_file] - - -class IndexTxtRequest(AbstractRequest): - def __init__(self, **kwargs): - self.input_files = [] - self.output_file = None - self.cldr_version = "" - super(IndexTxtRequest, self).__init__(**kwargs) - - def apply_file_filter(self, filter): - i = 0 - while i < len(self.input_files): - if filter.match(self.input_files[i]): - i += 1 - continue - del self.input_files[i] - return i > 0 - - def flatten(self, config, all_requests, common_vars): - return PrintFileRequest( - name = self.name, - output_file = self.output_file, - content = self._generate_index_file(common_vars) - ).flatten(config, all_requests, common_vars) - - def _generate_index_file(self, common_vars): - locales = [f.filename[f.filename.rfind("/")+1:-4] for f in self.input_files] - formatted_version = " CLDRVersion { \"%s\" }\n" % self.cldr_version if self.cldr_version else "" - formatted_locales = "\n".join([" %s {\"\"}" % v for v in locales]) - # TODO: CLDRVersion is required only in the base file - return ("// Warning this file is automatically generated\n" - "{INDEX_NAME}:table(nofallback) {{\n" - "{FORMATTED_VERSION}" - " InstalledLocales {{\n" - "{FORMATTED_LOCALES}\n" - " }}\n" - "}}").format( - FORMATTED_VERSION = formatted_version, - FORMATTED_LOCALES = formatted_locales, - **common_vars - ) - - def all_input_files(self): - return self.input_files - - def all_output_files(self): - return [self.output_file] diff -Nru icu-64.2/source/data/buildtool/test/filtration_test.py icu-65.1/source/data/buildtool/test/filtration_test.py --- icu-64.2/source/data/buildtool/test/filtration_test.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/test/filtration_test.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,353 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -import unittest - -from .. import InFile -from ..filtration import Filter - -EXAMPLE_FILE_STEMS = [ - "af_NA", - "af_ZA", - "af", - "ar", - "ar_SA", - "ars", - "bs_BA", - "bs_Cyrl_BA", - "bs_Cyrl", - "bs_Latn_BA", - "bs_Latn", - "bs", - "en_001", - "en_150", - "en_DE", - "en_GB", - "en_US", - "root", - "sr_BA", - "sr_CS", - "sr_Cyrl_BA", - "sr_Cyrl_CS", - "sr_Cyrl_ME", - "sr_Cyrl", - "sr_Latn_BA", - "sr_Latn_CS", - "sr_Latn_ME", - "sr_Latn", - "sr_ME", - "sr", - "vai_Latn_LR", - "vai_Latn", - "vai_LR", - "vai_Vaii_LR", - "vai_Vaii", - "vai", - "zh_CN", - "zh_Hans_CN", - "zh_Hans_HK", - "zh_Hans_MO", - "zh_Hans_SG", - "zh_Hans", - "zh_Hant_HK", - "zh_Hant_MO", - "zh_Hant_TW", - "zh_Hant", - "zh_HK", - "zh_MO", - "zh_SG", - "zh_TW", - "zh" -] - -class FiltrationTest(unittest.TestCase): - - def test_exclude(self): - self._check_filter(Filter.create_from_json({ - "filterType": "exclude" - }), [ - ]) - - def test_default_whitelist(self): - self._check_filter(Filter.create_from_json({ - "whitelist": [ - "ars", - "zh_Hans" - ] - }), [ - "ars", - "zh_Hans" - ]) - - def test_default_blacklist(self): - expected_matches = set(EXAMPLE_FILE_STEMS) - expected_matches.remove("ars") - expected_matches.remove("zh_Hans") - self._check_filter(Filter.create_from_json({ - "blacklist": [ - "ars", - "zh_Hans" - ] - }), expected_matches) - - def test_language_whitelist(self): - self._check_filter(Filter.create_from_json({ - "filterType": "language", - "whitelist": [ - "af", - "bs" - ] - }), [ - "root", - "af_NA", - "af_ZA", - "af", - "bs_BA", - "bs_Cyrl_BA", - "bs_Cyrl", - "bs_Latn_BA", - "bs_Latn", - "bs" - ]) - - def test_language_blacklist(self): - expected_matches = set(EXAMPLE_FILE_STEMS) - expected_matches.remove("af_NA") - expected_matches.remove("af_ZA") - expected_matches.remove("af") - self._check_filter(Filter.create_from_json({ - "filterType": "language", - "blacklist": [ - "af" - ] - }), expected_matches) - - def test_regex_whitelist(self): - self._check_filter(Filter.create_from_json({ - "filterType": "regex", - "whitelist": [ - r"^ar.*$", - r"^zh$" - ] - }), [ - "ar", - "ar_SA", - "ars", - "zh" - ]) - - def test_regex_blacklist(self): - expected_matches = set(EXAMPLE_FILE_STEMS) - expected_matches.remove("ar") - expected_matches.remove("ar_SA") - expected_matches.remove("ars") - expected_matches.remove("zh") - self._check_filter(Filter.create_from_json({ - "filterType": "regex", - "blacklist": [ - r"^ar.*$", - r"^zh$" - ] - }), expected_matches) - - def test_locale_basic(self): - self._check_filter(Filter.create_from_json({ - "filterType": "locale", - "whitelist": [ - # Default scripts: - # sr => Cyrl - # vai => Vaii - # zh => Hans - "bs_BA", # is an alias to bs_Latn_BA - "en_DE", - "sr", # Language with no script - "vai_Latn", # Language with non-default script - "zh_Hans" # Language with default script - ] - }), [ - "root", - # bs: should include the full dependency tree of bs_BA - "bs_BA", - "bs_Latn_BA", - "bs_Latn", - "bs", - # en: should include the full dependency tree of en_DE - "en", - "en_DE", - "en_150", - "en_001", - # sr: include Cyrl, the default, but not Latn. - "sr", - "sr_BA", - "sr_CS", - "sr_Cyrl", - "sr_Cyrl_BA", - "sr_Cyrl_CS", - "sr_Cyrl_ME", - # vai: include Latn but NOT Vaii. - "vai_Latn", - "vai_Latn_LR", - # zh: include Hans but NOT Hant. - "zh", - "zh_CN", - "zh_SG", - "zh_Hans", - "zh_Hans_CN", - "zh_Hans_HK", - "zh_Hans_MO", - "zh_Hans_SG" - ]) - - def test_locale_no_children(self): - self._check_filter(Filter.create_from_json({ - "filterType": "locale", - "includeChildren": False, - "whitelist": [ - # See comments in test_locale_basic. - "bs_BA", - "en_DE", - "sr", - "vai_Latn", - "zh_Hans" - ] - }), [ - "root", - "bs_BA", - "bs_Latn_BA", - "bs_Latn", - "bs", - "en", - "en_DE", - "en_150", - "en_001", - "sr", - "vai_Latn", - "zh", - "zh_Hans", - ]) - - def test_locale_include_scripts(self): - self._check_filter(Filter.create_from_json({ - "filterType": "locale", - "includeScripts": True, - "whitelist": [ - # See comments in test_locale_basic. - "bs_BA", - "en_DE", - "sr", - "vai_Latn", - "zh_Hans" - ] - }), [ - "root", - # bs: includeScripts only works for language-only (without region) - "bs_BA", - "bs_Latn_BA", - "bs_Latn", - "bs", - # en: should include the full dependency tree of en_DE - "en", - "en_DE", - "en_150", - "en_001", - # sr: include Latn, since no particular script was requested. - "sr_BA", - "sr_CS", - "sr_Cyrl_BA", - "sr_Cyrl_CS", - "sr_Cyrl_ME", - "sr_Cyrl", - "sr_Latn_BA", - "sr_Latn_CS", - "sr_Latn_ME", - "sr_Latn", - "sr_ME", - "sr", - # vai: do NOT include Vaii; the script was explicitly requested. - "vai_Latn_LR", - "vai_Latn", - # zh: do NOT include Hant; the script was explicitly requested. - "zh_CN", - "zh_SG", - "zh_Hans_CN", - "zh_Hans_HK", - "zh_Hans_MO", - "zh_Hans_SG", - "zh_Hans", - "zh" - ]) - - def test_locale_no_children_include_scripts(self): - self._check_filter(Filter.create_from_json({ - "filterType": "locale", - "includeChildren": False, - "includeScripts": True, - "whitelist": [ - # See comments in test_locale_basic. - "bs_BA", - "en_DE", - "sr", - "vai_Latn", - "zh_Hans" - ] - }), [ - "root", - # bs: includeScripts only works for language-only (without region) - "bs_BA", - "bs_Latn_BA", - "bs_Latn", - "bs", - # en: should include the full dependency tree of en_DE - "en", - "en_DE", - "en_150", - "en_001", - # sr: include Cyrl and Latn but no other children - "sr", - "sr_Cyrl", - "sr_Latn", - # vai: include only the requested script - "vai_Latn", - # zh: include only the requested script - "zh", - "zh_Hans", - ]) - - def test_union(self): - self._check_filter(Filter.create_from_json({ - "filterType": "union", - "unionOf": [ - { - "whitelist": [ - "ars", - "zh_Hans" - ] - }, - { - "filterType": "regex", - "whitelist": [ - r"^bs.*$", - r"^zh$" - ] - } - ] - }), [ - "ars", - "zh_Hans", - "bs_BA", - "bs_Cyrl_BA", - "bs_Cyrl", - "bs_Latn_BA", - "bs_Latn", - "bs", - "zh" - ]) - - def _check_filter(self, filter, expected_matches): - for file_stem in EXAMPLE_FILE_STEMS: - is_match = filter.match(InFile("locales/%s.txt" % file_stem)) - expected_match = file_stem in expected_matches - self.assertEqual(is_match, expected_match, file_stem) - -# Export the test for the runner -suite = unittest.makeSuite(FiltrationTest) diff -Nru icu-64.2/source/data/buildtool/test/__init__.py icu-65.1/source/data/buildtool/test/__init__.py --- icu-64.2/source/data/buildtool/test/__init__.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/test/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html diff -Nru icu-64.2/source/data/buildtool/test/__main__.py icu-65.1/source/data/buildtool/test/__main__.py --- icu-64.2/source/data/buildtool/test/__main__.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/test/__main__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -import unittest - -from . import filtration_test - -def load_tests(loader, tests, pattern): - suite = unittest.TestSuite() - suite.addTest(filtration_test.suite) - return suite - -if __name__ == '__main__': - unittest.main() diff -Nru icu-64.2/source/data/buildtool/utils.py icu-65.1/source/data/buildtool/utils.py --- icu-64.2/source/data/buildtool/utils.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/buildtool/utils.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -# Copyright (C) 2018 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html - -# Python 2/3 Compatibility (ICU-20299) -# TODO(ICU-20301): Remove this. -from __future__ import print_function - -import sys - -from . import * - - -def dir_for(file): - if isinstance(file, LocalFile): - return file.dirname - if isinstance(file, SrcFile): - return "{SRC_DIR}" - if isinstance(file, InFile): - return "{IN_DIR}" - if isinstance(file, TmpFile): - return "{TMP_DIR}" - if isinstance(file, OutFile): - return "{OUT_DIR}" - if isinstance(file, PkgFile): - return "{PKG_DIR}" - assert False - - -def concat_dicts(*dicts): - # There is not a super great way to do this in Python: - new_dict = {} - for dict in dicts: - new_dict.update(dict) - return new_dict - - -def repeated_execution_request_looper(request): - # dictionary of lists to list of dictionaries: - ld = [ - dict(zip(request.repeat_with, t)) - for t in zip(*request.repeat_with.values()) - ] - if not ld: - # No special options given in repeat_with - ld = [{} for _ in range(len(request.input_files))] - return zip(ld, request.specific_dep_files, request.input_files, request.output_files) - - -def format_single_request_command(request, cmd_template, common_vars): - return cmd_template.format( - ARGS = request.args.format( - INPUT_FILES = [file.filename for file in request.input_files], - OUTPUT_FILES = [file.filename for file in request.output_files], - **concat_dicts(common_vars, request.format_with) - ) - ) - - -def format_repeated_request_command(request, cmd_template, loop_vars, common_vars): - (iter_vars, _, input_file, output_file) = loop_vars - return cmd_template.format( - ARGS = request.args.format( - INPUT_FILE = input_file.filename, - OUTPUT_FILE = output_file.filename, - **concat_dicts(common_vars, request.format_with, iter_vars) - ) - ) - - -def flatten_requests(requests, config, common_vars): - result = [] - for request in requests: - result += request.flatten(config, requests, common_vars) - return result - - -def get_all_output_files(requests, include_tmp=False): - files = [] - for request in requests: - files += request.all_output_files() - - # Filter out all files but those in OUT_DIR if necessary. - # It is also easy to filter for uniqueness; do it right now and return. - if not include_tmp: - files = (file for file in files if isinstance(file, OutFile)) - return list(set(files)) - - # Filter for unique values. NOTE: Cannot use set() because we need to accept same filename as - # OutFile and TmpFile as different, and by default they evaluate as equal. - return [f for _, f in set((type(f), f) for f in files)] - - -def compute_directories(requests): - dirs = set() - for file in get_all_output_files(requests, include_tmp=True): - path = "%s/%s" % (dir_for(file), file.filename) - dirs.add(path[:path.rfind("/")]) - return list(sorted(dirs)) - - -class SpaceSeparatedList(list): - """A list that joins itself with spaces when converted to a string.""" - def __str__(self): - return " ".join(self) diff -Nru icu-64.2/source/data/build.xml icu-65.1/source/data/build.xml --- icu-64.2/source/data/build.xml 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/build.xml 2019-10-03 11:16:41.000000000 +0000 @@ -43,13 +43,17 @@ - + + + + + @@ -60,11 +64,31 @@ + + + + + + + + + + + + + + + + + + + - + @@ -101,22 +125,23 @@ - + - + - + - + + @@ -154,11 +179,11 @@ - + - + @@ -169,11 +194,11 @@ - + - + @@ -184,12 +209,12 @@ - + - + @@ -200,119 +225,119 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -325,11 +350,11 @@ - + - + @@ -337,12 +362,12 @@ - + - + @@ -354,11 +379,11 @@ - + @@ -374,7 +399,7 @@ - + diff -Nru icu-64.2/source/data/cldr-icu-readme.txt icu-65.1/source/data/cldr-icu-readme.txt --- icu-64.2/source/data/cldr-icu-readme.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/cldr-icu-readme.txt 2019-10-03 11:16:41.000000000 +0000 @@ -35,21 +35,6 @@ # #---- # -# CLDR dtd caching -# -# Parts of the build process (notably building the new ICU data files in step 4) -# require http: access to files in the CLDR repository; for example, processing -# the files in icu4c/source/data/xml/ may require access to -# http://www.unicode.org/repos/cldr/trunk/common/dtd/ldml.dtd -# -# Unless you cache the dtds locally by -# 1. creating a temp directory e.g. ~/.cldrdtd -# 2. setting CLDR_DTD_CACHE to it e.g. -DCLDR_DTD_CACHE=~/.cldrdtd -# your system will make excessive network requests, which will result in the -# Unicode server blocking access. -# -#---- -# # There are several environment variables that need to be defined. # # a) Java- and ant-related variables @@ -62,9 +47,6 @@ # # -Xmx4096m, to give Java more memory; otherwise it may run out # of heap. -# -DCLDR_DTD_CACHE=~/.cldrdtd (or some other temp directory -# that already exists), to reduce frequent http: access to dtds -# and consequent blockage by Unicode server. # # b) CLDR-related variables # @@ -73,6 +55,16 @@ # CLDR_CLASSES: Path to the CLDR Tools classes directory. If not set, defaults # to $CLDR_DIR/tools/java/classes # +# CLDR_TMP_DIR: Parent of temporary CLDR production data. +# Defaults to $CLDR_DIR/../cldr-aux (sibling to CLDR_DIR). +# +# *** NOTE ***: In CLDR release-36-beta, the GenerateProductionData +# tool no longer generates data into $CLDR_TMP_DIR/production; instead +# it generates data into $CLDR_DIR/../cldr-staging/production. However +# the rest of the build still assumes that the generated data is in +# $CLDR_TMP_DIR/production. So CLDR_TMP_DIR must be defined to be +# $CLDR_DIR/../cldr-staging +# # c) ICU-related variables # These variables only need to be set if you're directly reusing the # commands below. @@ -140,38 +132,23 @@ # 1a. Java and ant variables, adjust for your system export JAVA_HOME=`/usr/libexec/java_home` -export ANT_OPTS="-Xmx4096m -DCLDR_DTD_CACHE=~/.cldrdtd" +export ANT_OPTS="-Xmx4096m # 1b. CLDR variables, adjust for your setup; with cygwin it might be e.g. # CLDR_DIR=`cygpath -wp /build/cldr` -export CLDR_DIR=$HOME/cldr/trunk +export CLDR_DIR=$HOME/cldr-myfork # 1c. ICU variables -export ICU4C_DIR=$HOME/icu/icu4c -export ICU4J_ROOT=$HOME/icu/icu4j - -# 1d. Pre-populate your CLDR DTD cache. You need to do this only once. - -mkdir ~/.cldrdtd -cd ~/.cldrdtd -curl http://www.unicode.org/repos/cldr/trunk/common/dtd/ldml.dtd \ - -o http___www.unicode.org_repos_cldr_trunk_common_dtd_ldml.dtd -# WAIT before hitting the server again; it WILL NOT give you a second chance! -sleep 5 -curl http://www.unicode.org/repos/cldr/trunk/common/dtd/ldmlICU.dtd \ - -o http___www.unicode.org_repos_cldr_trunk_common_dtd_ldmlICU.dtd -sleep 5 -curl http://www.unicode.org/repos/cldr/trunk/common/dtd/ldmlSupplemental.dtd \ - -o http___www.unicode.org_repos_cldr_trunk_common_dtd_ldmlSupplemental.dtd +export ICU4C_DIR=$HOME/icu-myfork/icu4c +export ICU4J_ROOT=$HOME/icu-myfork/icu4j -# 2. Build the CLDR Java tools -# Optionally build the jar, but ant will look inside the classes directory anyway +# 2. Build the CLDR Java tools and jar cd $CLDR_DIR/tools/java ant all -#ant jar +ant jar # 3. Configure ICU4C, build and test without new data first, to verify that # there are no pre-existing errors. Here is the runConfigureICU @@ -182,7 +159,7 @@ make all 2>&1 | tee /tmp/icu4c-oldData-makeAll.txt make check 2>&1 | tee /tmp/icu4c-oldData-makeCheck.txt -# 4. Build the new ICU4C data files; these include .txt files and .mk files. +# 4. Build the new ICU4C data files; these include .txt files and .py files. # These new files will replace whatever was already present in the ICU4C sources. # This process uses ant with ICU's data/build.xml and data/icu-config.xml to # operate (via CLDR's ant/CLDRConverterTool.java and ant/CLDRBuild.java) the @@ -193,22 +170,15 @@ # Running "ant setup" is not required, but it will print useful errors to # debug issues with your path when it fails. # -# If you see timeout errors when building the rbnf data, for example, then you are -# likely not using a CLDR dtd cache; see "CLDR dtd caching" above. If you are using -# a dtd cache and are still having timeout problems, the IP address of your system -# may have been blocked due to previous excessive access. In this case you may need -# to contact a Unicode sysadmin to restore access. -# -# Unfortunately, even if you have your DTD cache variable enabled, you may still -# get blocked and unable to populate your cache because of multiple successive -# requests to download the required DTD files. It is recommended that you -# pre-populate your cache as shown above in step 1d. cd $ICU4C_DIR/source/data ant setup ant clean ant all 2>&1 | tee /tmp/cldr-newData-buildLog.txt +# NOTE: if you change the CLDR data, please run "ant cleanprod" to clean out the +# temporary production data directory (usually $CLDR_DIR/../cldr-aux/production ) + # 5. Check which data files have modifications, which have been added or removed # (if there are no changes, you may not need to proceed further). Make sure the # list seems reasonable. @@ -291,6 +261,22 @@ # more failures in ICU4C or ICU4J (except failures that were present before you # began testing the new CLDR data). +# Note that certain data changes and related test failures may require the +# rebuilding of other kinds of data. For example: +# a) Changes to locale matching data may cause failures in e.g. the following: +# com.ibm.icu.dev.test.util.LocaleDistanceTest (testLoadedDataSameAsBuiltFromScratch) +# com.ibm.icu.dev.test.util.LocaleMatcherTest (testLikelySubtagsLoadedDataSameAsBuiltFromScratch) +# To address these requires building and running the tool +# icu4j/tools/misc/src/com/ibm/icu/dev/tool/locale/LocaleDistanceBuilder.java +# to regenerate the file icu4c/source/data/misc/langInfo.txt and then regenerating +# the ICU4J data jars. +# b) Changes to plurals data may cause failures in e.g. the following +# com.ibm.icu.dev.test.format.PluralRulesTest (TestLocales) +# To address these requires updating the LOCALE_SNAPSHOT data in +# icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRulesTest.java +# by modifying the TestLocales() test there to run generateLOCALE_SNAPSHOT() and then +# copying in the updated data. + # 15. Check the file changes; then git add or git rm as necessary, and # commit the changes. diff -Nru icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd --- icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,3146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd --- icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru icu-64.2/source/data/icu-config.xml icu-65.1/source/data/icu-config.xml --- icu-64.2/source/data/icu-config.xml 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/icu-config.xml 2019-10-03 11:16:41.000000000 +0000 @@ -370,6 +370,7 @@ + Binary files /tmp/tmp1eTomn/Up6jWaEcgn/icu-64.2/source/data/in/icudt64l.dat and /tmp/tmp1eTomn/1QfOdCdfdZ/icu-65.1/source/data/in/icudt64l.dat differ Binary files /tmp/tmp1eTomn/Up6jWaEcgn/icu-64.2/source/data/in/icudt65l.dat and /tmp/tmp1eTomn/1QfOdCdfdZ/icu-65.1/source/data/in/icudt65l.dat differ diff -Nru icu-64.2/source/data/makedata.mak icu-65.1/source/data/makedata.mak --- icu-64.2/source/data/makedata.mak 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/makedata.mak 2019-10-03 11:16:41.000000000 +0000 @@ -12,11 +12,11 @@ ############################################################################## # Keep the following in sync with the version - see common/unicode/uvernum.h -U_ICUDATA_NAME=icudt64 +U_ICUDATA_NAME=icudt65 ############################################################################## !IF "$(UWP)" == "UWP" # Optionally change the name of the data file for the UWP version. -U_ICUDATA_NAME=icudt64 +U_ICUDATA_NAME=icudt65 !ENDIF U_ICUDATA_ENDIAN_SUFFIX=l UNICODE_VERSION=12.1 @@ -71,6 +71,7 @@ # Timestamp files to keep track of current build state TOOLS_TS=$(ICUTMP)\tools.timestamp COREDATA_TS=$(ICUTMP)\coredata.timestamp +ARM_CROSSBUILD_TS= # ICUCOL # The directory that contains colfiles.mk files along with *.txt collation data files @@ -106,6 +107,8 @@ # !IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" DLL_OUTPUT=$(ICUP)\binARM$(UWP) +!ELSE IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +DLL_OUTPUT=$(ICUP)\binARM64$(UWP) !ELSE IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug" DLL_OUTPUT=$(ICUP)\bin64$(UWP) !ELSE IF "$(UWP)" == "UWP" @@ -113,6 +116,7 @@ !ELSE DLL_OUTPUT=$(ICUP)\bin$(UWP) !ENDIF +!MESSAGE ICU data DLL_OUTPUT path is $(DLL_OUTPUT) # # TESTDATA @@ -126,7 +130,7 @@ # # TESTDATABLD -# The build directory for test data intermidiate files +# The build directory for test data intermediate files # (Tests are NOT run from this makefile, # only the data is put in place.) TESTDATABLD=$(ICUP)\source\test\testdata\out\build @@ -138,20 +142,39 @@ ICUTOOLS=$(ICUP)\source\tools !MESSAGE ICU tools path is $(ICUTOOLS) +# ARM_CROSS_BUILD +# In order to support cross-compiling for ARM/ARM64 using the x64 tools +# we need to know if we're building the ARM/ARM64 data DLL, otherwise +# the existence of the x64 bits will cause us to think we are already done. +# Note: This is only for the "regular" builds, the UWP builds have a separate project file entirely. +ARM_CROSS_BUILD= +!IF "$(UWP)" == "" +!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" +ARM_CROSS_BUILD=ARM +ARM_CROSSBUILD_TS=$(ICUTMP)\$(ARM_CROSS_BUILD).timestamp +!ELSE IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +ARM_CROSS_BUILD=ARM64 +ARM_CROSSBUILD_TS=$(ICUTMP)\$(ARM_CROSS_BUILD).timestamp +!ENDIF +!ENDIF + # # TOOLS CFG PATH -# ARM needs to use one of the other tools, so make sure to get an usable cfg path +# Generally the tools want to run on the same architecture as is being built. +# Thus ARM and ARM64 need to use another build of the other tools, so make sure to get an usable cfg path. # Since tools, particularly pkggen, have architecture built-in, we made x64 on # Windows be machine-independent and use those tools. # +!IF "$(ARM_CROSS_BUILD)" == "" CFGTOOLS=$(CFG) -!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" +!ELSE CFGTOOLS=x64\Release !ENDIF !MESSAGE ICU tools CFG subpath is $(CFGTOOLS) + # The current ICU tools need to be in the path first. -# x86 uses x86, x64 and arm use x64 +# x86 uses x86; x64, arm, and arm64 use x64 !IF "$(CFG)" == "x86\Release" || "$(CFG)" == "x86\Debug" PATH = $(ICUP)\bin;$(PATH) ICUPBIN=$(ICUP)\bin @@ -190,9 +213,12 @@ COMMON_ICUDATA_ARGUMENTS=-f -e $(U_ICUDATA_NAME) -v $(ICU_PACKAGE_MODE) -c -p $(ICUPKG) -T "$(ICUTMP)" -L $(U_ICUDATA_NAME) -d "$(ICUBLD_PKG)" -s . !IF "$(UWP)" == "UWP" COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -u +!ENDIF !IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" -COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -a +COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -a ARM !ENDIF +!IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -a ARM64 !ENDIF ############################################################################# @@ -204,6 +230,7 @@ # Building the common dll in $(ICUBLD_PKG) unconditionally copies it to $(DLL_OUTPUT) too. # ############################################################################# +!IF "$(ARM_CROSS_BUILD)" == "" ALL : GODATA "$(ICU_LIB_TARGET)" "$(TESTDATAOUT)\testdata.dat" @echo All targets are up to date @@ -212,6 +239,11 @@ copy "$(ICUOUT)\$(U_ICUDATA_NAME)$(U_ICUDATA_ENDIAN_SUFFIX).dat" "$(ICUMAKE)\..\..\commondata\" !ENDIF +!ELSE +ALL : GODATA "$(ICU_LIB_TARGET)" "$(TESTDATAOUT)\testdata.dat" $(ARM_CROSSBUILD_TS) + @echo All targets are up to date + +!ENDIF # Three main targets: tools, core data, and test data. # Keep track of whether they are built via timestamp files. @@ -233,15 +265,16 @@ $(COREDATA_TS): @cd "$(ICUSRCDATA)" - py -3 -B -m buildtool \ + set PYTHONPATH=$(ICUP)\source\python;%PYTHONPATH% + py -3 -B -m icutools.databuilder \ --mode windows-exec \ --src_dir "$(ICUSRCDATA)" \ --tool_dir "$(ICUTOOLS)" \ --tool_cfg "$(CFG)" \ --out_dir "$(ICUBLD_PKG)" \ - --tmp_dir "$(ICUTMP)" + --tmp_dir "$(ICUTMP)" \ --filter_file "$(ICU_DATA_FILTER_FILE)" \ - $(ICU_DATA_BUILDTOOL_OPTS) \ + $(ICU_DATA_BUILDTOOL_OPTS) @echo "timestamp" > $(COREDATA_TS) @@ -378,6 +411,18 @@ -@erase "$(ICUTMP)\$(ICUPKG).dat" !ENDIF +"$(ARM_CROSSBUILD_TS)" : $(COMMON_ICUDATA_DEPENDENCIES) "$(ICU_LIB_TARGET)" + @echo Building ICU data for "$(ARM_CROSS_BUILD)" from x64 + cd "$(ICUBLD_PKG)" + "$(ICUPBIN)\pkgdata" $(COMMON_ICUDATA_ARGUMENTS) $(ICUTMP)\icudata.lst + -@erase "$(ICU_LIB_TARGET)" + @if not exist "$(DLL_OUTPUT)" mkdir "$(DLL_OUTPUT)" + copy "$(U_ICUDATA_NAME).dll" "$(ICU_LIB_TARGET)" + -@erase "$(U_ICUDATA_NAME).dll" + copy "$(ICUTMP)\$(ICUPKG).dat" "$(ICUOUT)\$(U_ICUDATA_NAME)$(U_ICUDATA_ENDIAN_SUFFIX).dat" + -@erase "$(ICUTMP)\$(ICUPKG).dat" + @echo "timestamp" > $(ARM_CROSSBUILD_TS) + # utility target to create missing directories # Most directories are made by Python, but still create ICUTMP # so it works in the source archive @@ -386,6 +431,7 @@ @if not exist "$(ICUTMP)\$(NULL)" mkdir "$(ICUTMP)" @if not exist "$(ICUOUT)\build\$(NULL)" mkdir "$(ICUOUT)\build" @if not exist "$(ICUBLD_PKG)\$(NULL)" mkdir "$(ICUBLD_PKG)" + @if not exist "$(TESTDATAOUT)" mkdir "$(TESTDATAOUT)" # utility target to send us to the right dir GODATA : CREATE_DIRS @@ -394,60 +440,11 @@ # This is to remove all the data files CLEAN : GODATA @echo Cleaning up the data files. - @cd "$(ICUBLD_PKG)" - -@erase "*.cnv" - -@erase "*.exp" - -@erase "*.icu" - -@erase "*.lib" - -@erase "*.nrm" - -@erase "*.res" - -@erase "*.spp" - -@erase "*.txt" - -@erase "*.cfu" - -@erase "curr\*.res" - -@erase "curr\*.txt" - -@erase "lang\*.res" - -@erase "lang\*.txt" - -@erase "region\*.res" - -@erase "region\*.txt" - -@erase "zone\*.res" - -@erase "zone\*.txt" - @cd "$(ICUBLD_PKG)\$(ICUBRK)" - -@erase "*.brk" - -@erase "*.res" - -@erase "*.txt" - -@erase "*.dict" - @cd "$(ICUBLD_PKG)\$(ICUCOL)" - -@erase "*.res" - -@erase "*.txt" - @cd "$(ICUBLD_PKG)\$(ICURBNF)" - -@erase "*.res" - -@erase "*.txt" - @cd "$(ICUBLD_PKG)\$(ICUTRNS)" - -@erase "*.res" @cd "$(ICUOUT)" - -@erase "*.dat" - @cd "$(ICUTMP)" - -@erase "*.html" - -@erase "*.lst" - -@erase "*.mak" - -@erase "*.obj" - -@erase "*.res" - -@erase "*.timestamp" - @cd "$(TESTDATABLD)" - -@erase "*.cnv" - -@erase "*.icu" - -@erase "*.mak" - -@erase "*.nrm" - -@erase "*.res" - -@erase "*.spp" - -@erase "*.txt" - @cd "$(TESTDATAOUT)" - -@erase "*.dat" - @cd "$(TESTDATAOUT)\testdata" - -@erase "*.typ" - @cd "$(ICUBLD_PKG)" - + -@erase "$(ICUOUT)\*.dat" + @rmdir $(ICUBLD) /s /q + @rmdir $(ICUTMP) /s /q + @rmdir $(TESTDATAOUT) /s /q # DLL version information # If you modify this, modify winmode.c in pkgdata. diff -Nru icu-64.2/source/data/makedata_uwp.vcxproj icu-65.1/source/data/makedata_uwp.vcxproj --- icu-64.2/source/data/makedata_uwp.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/makedata_uwp.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,10 @@ Debug ARM + + Debug + ARM64 + Release Win32 @@ -25,6 +29,10 @@ Release ARM + + Release + ARM64 + {B1D53358-37BD-48BC-B27C-68BAF1E78508} @@ -46,65 +54,20 @@ <_ProjectFileVersion>10.0.30319.1 - .\data\tmp\x86\ - .\data\tmp\x86\ - .\data\tmp\x64\ - .\data\tmp\x64\ - .\data\tmp\arm\ - .\data\tmp\arm\ - .\data\build\ - .\data\build\ - .\data\build\ - .\data\build\ - .\data\build\ - .\data\build\ - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release UWP=UWP - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release UWP=UWP clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release UWP=UWP clean - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug UWP=UWP - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug UWP=UWP clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug UWP=UWP clean - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release UWP=UWP - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release UWP=UWP clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release UWP=UWP clean - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug UWP=UWP - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug UWP=UWP clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug UWP=UWP clean - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Release UWP=UWP - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Release UWP=UWP clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Release UWP=UWP clean - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Debug UWP=UWP - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Debug UWP=UWP clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Debug UWP=UWP clean + .\data\tmp\$(Platform)\ + .\data\build\ + $(Platform)\$(Configuration) + + .\data\tmp\x86\ + x86\$(Configuration) + + NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) UWP=UWP + NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) UWP=UWP clean all + NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) UWP=UWP clean - - - .\out\tmp\x86\ReleaseUWPBuildLog.html - - - - - .\out\tmp\x86\DebugUWPBuildLog.html - - - - - .\out\tmp\x64\ReleaseUWPBuildLog.html - - - - - .\out\tmp\x64\DebugUWPBuildLog.html - - - - - .\out\tmp\arm\ReleaseUWPBuildLog.html - - - + - .\out\tmp\arm\DebugUWPBuildLog.html + $(OutDir)$(Configuration)UWPBuildLog.html @@ -116,7 +79,6 @@ - diff -Nru icu-64.2/source/data/makedata.vcxproj icu-65.1/source/data/makedata.vcxproj --- icu-64.2/source/data/makedata.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/makedata.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -19,69 +19,26 @@ <_ProjectFileVersion>10.0.30319.1 - .\data\tmp\x86\ - .\data\build\ - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release clean - - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - .\data\tmp\x86\ - .\data\build\ - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug clean - - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - .\data\tmp\x64\ - .\data\build\ - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release clean - - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - .\data\tmp\x64\ - .\data\build\ - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug clean all - NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug clean - - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) + .\data\tmp\$(Platform)\ + .\data\build\ + $(Platform)\$(Configuration) + + .\data\tmp\x86\ + x86\$(Configuration) + + NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) + NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) clean all + NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) clean + + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) - + - .\out\tmp\x86\ReleaseBuildLog.html - - - - - .\out\tmp\x86\DebugBuildLog.html - - - - - .\out\tmp\x64\ReleaseBuildLog.html - - - - - .\out\tmp\x64\DebugBuildLog.html + .\data\log\$(Platform)\$(Configuration)BuildLog.html @@ -93,7 +50,6 @@ - @@ -199,4 +155,4 @@ - \ No newline at end of file + diff -Nru icu-64.2/source/data/makedata.vcxproj.filters icu-65.1/source/data/makedata.vcxproj.filters --- icu-64.2/source/data/makedata.vcxproj.filters 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/makedata.vcxproj.filters 2019-10-03 11:16:41.000000000 +0000 @@ -35,9 +35,6 @@ Make Files - - Make Files - Make Files diff -Nru icu-64.2/source/data/Makefile.in icu-65.1/source/data/Makefile.in --- icu-64.2/source/data/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/data/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -136,7 +136,7 @@ $(RMV) $(LIBDIR)/*$(LIB_ICUDATA_NAME)*.$(SO)* $(LIBDIR)/$(LIB_STATIC_ICUDATA_NAME).$(A) check-local: - PYTHONPATH=$(srcdir) @PYTHON@ -m buildtool.test + PYTHONPATH=$(top_srcdir)/python @PYTHON@ -m icutools.databuilder.test # Find out if we have a source archive. # If we have that, then use that instead of building everything from scratch. @@ -266,7 +266,7 @@ TZDATA = $(firstword $(wildcard $(top_builddir)/tools/tzcode/tzdata*.tar.gz) $(wildcard $(top_srcdir)/tools/tzcode/tzdata*.tar.gz)) endif -# TODO(ICU-20466): Make the TZDATA override part of Python buildtool +# TODO(ICU-20466): Make the TZDATA override part of Python icutools.databuilder ifneq ($(TZDATA),) TZCODE_DIR=$(top_builddir)/tools/tzcode diff -Nru icu-64.2/source/extra/Makefile.in icu-65.1/source/extra/Makefile.in --- icu-64.2/source/extra/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/extra/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -23,7 +23,7 @@ ## Files to remove for 'make clean' CLEANFILES = *~ -SUBDIRS = uconv +SUBDIRS = scrptrun uconv ## List of phony targets .PHONY : all all-local all-recursive install install-local \ diff -Nru icu-64.2/source/extra/scrptrun/scrptrun.cpp icu-65.1/source/extra/scrptrun/scrptrun.cpp --- icu-64.2/source/extra/scrptrun/scrptrun.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/extra/scrptrun/scrptrun.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -19,6 +19,8 @@ #include "cmemory.h" #include "scrptrun.h" +U_NAMESPACE_BEGIN + const char ScriptRun::fgClassID=0; UChar32 ScriptRun::pairedChars[] = { @@ -201,3 +203,4 @@ return true; } +U_NAMESPACE_END diff -Nru icu-64.2/source/extra/scrptrun/scrptrun.h icu-65.1/source/extra/scrptrun/scrptrun.h --- icu-64.2/source/extra/scrptrun/scrptrun.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/extra/scrptrun/scrptrun.h 2019-10-03 11:16:41.000000000 +0000 @@ -20,6 +20,8 @@ #include "unicode/uobject.h" #include "unicode/uscript.h" +U_NAMESPACE_BEGIN + struct ScriptRecord { UChar32 startChar; @@ -152,5 +154,6 @@ reset(start, length); } +U_NAMESPACE_END #endif diff -Nru icu-64.2/source/extra/scrptrun/srtest.cpp icu-65.1/source/extra/scrptrun/srtest.cpp --- icu-64.2/source/extra/scrptrun/srtest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/extra/scrptrun/srtest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -27,9 +27,9 @@ int32_t testLength = UPRV_LENGTHOF(testChars); -void main() +int main() { - ScriptRun scriptRun(testChars, 0, testLength); + icu::ScriptRun scriptRun(testChars, 0, testLength); while (scriptRun.next()) { int32_t start = scriptRun.getScriptStart(); @@ -38,4 +38,5 @@ printf("Script '%s' from %d to %d.\n", uscript_getName(code), start, end); } + return 0; } diff -Nru icu-64.2/source/extra/uconv/makedata.mak icu-65.1/source/extra/uconv/makedata.mak --- icu-64.2/source/extra/uconv/makedata.mak 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/extra/uconv/makedata.mak 2019-10-03 11:16:41.000000000 +0000 @@ -17,7 +17,7 @@ !ENDIF #Here we test if a valid configuration is given -!IF "$(CFG)" != "Release" && "$(CFG)" != "release" && "$(CFG)" != "Debug" && "$(CFG)" != "debug" && "$(CFG)" != "x86\Release" && "$(CFG)" != "x86\Debug" && "$(CFG)" != "x64\Release" && "$(CFG)" != "x64\Debug" +!IF "$(CFG)" != "Release" && "$(CFG)" != "release" && "$(CFG)" != "Debug" && "$(CFG)" != "debug" && "$(CFG)" != "x86\Release" && "$(CFG)" != "x86\Debug" && "$(CFG)" != "x64\Release" && "$(CFG)" != "x64\Debug" && "$(CFG)" != "ARM\Release" && "$(CFG)" != "ARM\Debug" && "$(CFG)" != "ARM64\Release" && "$(CFG)" != "ARM64\Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: @@ -51,7 +51,9 @@ ICD=$(ICUDATA)^\ DATA_PATH=$(ICUP)\data^\ -!IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug" +# Use the x64 tools for building ARM and ARM64. +# Note: This is similar to the TOOLS CFG PATH in source\data\makedata.mak +!IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug" || "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" ICUTOOLS=$(ICUP)\bin64 PATH = $(ICUP)\bin64;$(PATH) !ELSE @@ -59,14 +61,29 @@ PATH = $(ICUP)\bin;$(PATH) !ENDIF +# If building ARM/ARM, then we need to pass the arch as an argument. +EXTRA_PKGDATA_ARGUMENTS= +!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" +EXTRA_PKGDATA_ARGUMENTS=-a ARM +!ENDIF +!IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +EXTRA_PKGDATA_ARGUMENTS=-a ARM64 +!ENDIF + # Make sure the necessary tools exist before continuing. (This is to prevent cryptic errors from NMAKE). !IF !EXISTS($(ICUTOOLS)\pkgdata.exe) !MESSAGE Unable to find "$(ICUTOOLS)\pkgdata.exe" !ERROR The tool 'pkgdata.exe' does not exist! (Have you built all of ICU yet?). +!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +!ERROR Note that the ARM and ARM64 builds require building x64 first. +!ENDIF !ENDIF !IF !EXISTS($(ICUTOOLS)\genrb.exe) !MESSAGE Unable to find "$(ICUTOOLS)\genrb.exe" !ERROR The tool 'genrb.exe' does not exist! (Have you built all of ICU yet?). +!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +!ERROR Note that the ARM and ARM64 builds require building x64 first. +!ENDIF !ENDIF # Suffixes for data files @@ -98,7 +115,7 @@ # invoke pkgdata - static "$(DLL_OUTPUT)\$(RESNAME).lib" : $(RB_FILES) $(RESFILES) @echo Building $(RESNAME).lib - @"$(ICUTOOLS)\pkgdata" -f -v -m static -c -p $(RESNAME) -d "$(DLL_OUTPUT)" -s "$(RESDIR)" < <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration) + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + x86\$(Configuration) + + true + false - + - - ..\..\..\include;..\..\common;%(AdditionalIncludeDirectories) - UCONVMSG_LINK;%(PreprocessorDefinitions) - true - Level3 - - - - - copy "$(TargetPath)" ..\..\..\bin - - $(ProjectDir)..\..\..\bin\$(TargetFileName);%(Outputs) - - .\x86\Release/uconv.tlb + $(OutDir)\uconv.tlb - MultiThreadedDLL - true - .\x86\Release/uconv.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ + Level3 Default + true + ..\..\..\include;..\..\common;%(AdditionalIncludeDirectories) + UCONVMSG_LINK;%(PreprocessorDefinitions) + $(OutDir)\uconv.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\uconv.pdb - uconvmsg.lib;icuuc.lib;icuin.lib;%(AdditionalDependencies) - .\x86\Release/uconv.exe - x86\Release;..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/uconv.pdb Console - false - - + $(OutDir)\uconv.exe + uconvmsg.lib;%(AdditionalDependencies) + $(OutDir);..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - $(ProjectDir)..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/uconv.tlb - + + + + true MultiThreadedDebugDLL - .\x86\Debug/uconv.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - EditAndContinue - Default - uconvmsg.lib;icuucd.lib;icuind.lib;%(AdditionalDependencies) - .\x86\Debug/uconv.exe - x86\Debug;..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/uconv.pdb - Console - false - - + icuucd.lib;icuind.lib;%(AdditionalDependencies) - - - copy "$(TargetPath)" ..\..\..\bin64 - - $(ProjectDir)..\..\..\bin64\$(TargetFileName);%(Outputs) - - - .\x64\Release/uconv.tlb - + + MultiThreadedDLL true - .\x64\Release/uconv.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default - uconvmsg.lib;icuuc.lib;icuin.lib;%(AdditionalDependencies) - .\x64\Release/uconv.exe - x64\Release;..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/uconv.pdb - Console - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - $(ProjectDir)..\..\..\bin64\$(TargetFileName);%(Outputs) - - - .\x64\Debug/uconv.tlb - - - MultiThreadedDebugDLL - .\x64\Debug/uconv.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - ProgramDatabase - Default - - - uconvmsg.lib;icuucd.lib;icuind.lib;%(AdditionalDependencies) - .\x64\Debug/uconv.exe - x64\Debug;..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/uconv.pdb - Console + icuuc.lib;icuin.lib;%(AdditionalDependencies) @@ -178,18 +102,8 @@ - nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x86\Debug - - x86\Debug/uconvmsg.lib;%(Outputs) - nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x64\Debug - - x64\Debug/uconvmsg.lib;%(Outputs) - nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x86\Release - - x86\Release/uconvmsg.lib;%(Outputs) - nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x64\Release - - x64\Release/uconvmsg.lib;%(Outputs) + nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=$(MakeCFG) + $(MakeCFG)\uconvmsg.lib;%(Outputs) diff -Nru icu-64.2/source/i18n/alphaindex.cpp icu-65.1/source/i18n/alphaindex.cpp --- icu-64.2/source/i18n/alphaindex.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/alphaindex.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -260,8 +260,7 @@ // but that would be worth it only if this method is called multiple times, // or called after using the old-style bucket iterator API. LocalPointer immutableBucketList(createBucketList(errorCode)); - LocalPointer coll( - static_cast(collatorPrimaryOnly_->clone())); + LocalPointer coll(collatorPrimaryOnly_->clone()); if (immutableBucketList.isNull() || coll.isNull()) { errorCode = U_MEMORY_ALLOCATION_ERROR; return NULL; @@ -907,7 +906,7 @@ return; } } - collatorPrimaryOnly_ = static_cast(collator_->clone()); + collatorPrimaryOnly_ = collator_->clone(); if (collatorPrimaryOnly_ == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; @@ -958,7 +957,7 @@ } if (leftString == NULL) { return 1; - }; + } if (rightString == NULL) { return -1; } diff -Nru icu-64.2/source/i18n/anytrans.cpp icu-65.1/source/i18n/anytrans.cpp --- icu-64.2/source/i18n/anytrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/anytrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -226,7 +226,7 @@ /** * Transliterator API. */ -Transliterator* AnyTransliterator::clone() const { +AnyTransliterator* AnyTransliterator::clone() const { return new AnyTransliterator(*this); } diff -Nru icu-64.2/source/i18n/anytrans.h icu-65.1/source/i18n/anytrans.h --- icu-64.2/source/i18n/anytrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/anytrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -66,7 +66,7 @@ /** * Transliterator API. */ - virtual Transliterator* clone() const; + virtual AnyTransliterator* clone() const; /** * Implements {@link Transliterator#handleTransliterate}. diff -Nru icu-64.2/source/i18n/astro.cpp icu-65.1/source/i18n/astro.cpp --- icu-64.2/source/i18n/astro.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/astro.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -65,10 +65,7 @@ return(uprv_isNaN(d)); } -static icu::UMutex *ccLock() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UMutex ccLock; U_CDECL_BEGIN static UBool calendar_astro_cleanup(void) { @@ -1552,12 +1549,12 @@ if(U_FAILURE(status)) { return 0; } - umtx_lock(ccLock()); + umtx_lock(&ccLock); if(*cache == NULL) { createCache(cache, status); if(U_FAILURE(status)) { - umtx_unlock(ccLock()); + umtx_unlock(&ccLock); return 0; } } @@ -1565,7 +1562,7 @@ res = uhash_igeti((*cache)->fTable, key); U_DEBUG_ASTRO_MSG(("%p: GET: [%d] == %d\n", (*cache)->fTable, key, res)); - umtx_unlock(ccLock()); + umtx_unlock(&ccLock); return res; } @@ -1573,12 +1570,12 @@ if(U_FAILURE(status)) { return; } - umtx_lock(ccLock()); + umtx_lock(&ccLock); if(*cache == NULL) { createCache(cache, status); if(U_FAILURE(status)) { - umtx_unlock(ccLock()); + umtx_unlock(&ccLock); return; } } @@ -1586,7 +1583,7 @@ uhash_iputi((*cache)->fTable, key, value, &status); U_DEBUG_ASTRO_MSG(("%p: PUT: [%d] := %d\n", (*cache)->fTable, key, value)); - umtx_unlock(ccLock()); + umtx_unlock(&ccLock); } CalendarCache::CalendarCache(int32_t size, UErrorCode &status) { diff -Nru icu-64.2/source/i18n/bocsu.h icu-65.1/source/i18n/bocsu.h --- icu-64.2/source/i18n/bocsu.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/bocsu.h 2019-10-03 11:16:41.000000000 +0000 @@ -144,14 +144,14 @@ * yields negative modulo results and quotients that are one more than * what we need here. */ -#define NEGDIVMOD(n, d, m) { \ +#define NEGDIVMOD(n, d, m) UPRV_BLOCK_MACRO_BEGIN { \ (m)=(n)%(d); \ (n)/=(d); \ if((m)<0) { \ --(n); \ (m)+=(d); \ } \ -} +} UPRV_BLOCK_MACRO_END U_CFUNC UChar32 u_writeIdenticalLevelRun(UChar32 prev, const UChar *s, int32_t length, icu::ByteSink &sink); diff -Nru icu-64.2/source/i18n/brktrans.cpp icu-65.1/source/i18n/brktrans.cpp --- icu-64.2/source/i18n/brktrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/brktrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -64,7 +64,7 @@ /** * Transliterator API. */ -Transliterator* BreakTransliterator::clone(void) const { +BreakTransliterator* BreakTransliterator::clone() const { return new BreakTransliterator(*this); } diff -Nru icu-64.2/source/i18n/brktrans.h icu-65.1/source/i18n/brktrans.h --- icu-64.2/source/i18n/brktrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/brktrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -54,7 +54,7 @@ * Transliterator API. * @return A copy of the object. */ - virtual Transliterator* clone(void) const; + virtual BreakTransliterator* clone() const; virtual const UnicodeString &getInsertion() const; diff -Nru icu-64.2/source/i18n/buddhcal.cpp icu-65.1/source/i18n/buddhcal.cpp --- icu-64.2/source/i18n/buddhcal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/buddhcal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -53,7 +53,7 @@ return *this; } -Calendar* BuddhistCalendar::clone(void) const +BuddhistCalendar* BuddhistCalendar::clone() const { return new BuddhistCalendar(*this); } @@ -133,7 +133,7 @@ */ static UDate gSystemDefaultCenturyStart = DBL_MIN; static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gBCInitOnce; +static icu::UInitOnce gBCInitOnce = U_INITONCE_INITIALIZER; UBool BuddhistCalendar::haveDefaultCentury() const diff -Nru icu-64.2/source/i18n/buddhcal.h icu-65.1/source/i18n/buddhcal.h --- icu-64.2/source/i18n/buddhcal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/buddhcal.h 2019-10-03 11:16:41.000000000 +0000 @@ -94,7 +94,7 @@ * @return return a polymorphic copy of this calendar. * @internal */ - virtual Calendar* clone(void) const; + virtual BuddhistCalendar* clone() const; public: /** diff -Nru icu-64.2/source/i18n/calendar.cpp icu-65.1/source/i18n/calendar.cpp --- icu-64.2/source/i18n/calendar.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/calendar.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -268,6 +268,8 @@ // canonicalize, so grandfathered variant will be transformed to keywords // e.g ja_JP_TRADITIONAL -> ja_JP@calendar=japanese + // NOTE: Since ICU-20187, ja_JP_TRADITIONAL no longer canonicalizes, and + // the Gregorian calendar is returned instead. int32_t canonicalLen = uloc_canonicalize(locid, canonicalName, sizeof(canonicalName) - 1, &status); if (U_FAILURE(status)) { return CALTYPE_GREGORIAN; @@ -748,6 +750,7 @@ validLocale[0] = 0; actualLocale[0] = 0; if (U_FAILURE(success)) { + delete zone; return; } if(zone == 0) { @@ -2592,7 +2595,7 @@ return FALSE; } // clone the calendar so we don't mess with the real one. - Calendar *work = (Calendar*)this->clone(); + Calendar *work = this->clone(); if (work == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return FALSE; @@ -2752,7 +2755,7 @@ // clone the calendar so we don't mess with the real one, and set it to // accept anything for the field values - Calendar *work = (Calendar*)this->clone(); + Calendar *work = this->clone(); if (work == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return 0; diff -Nru icu-64.2/source/i18n/casetrn.cpp icu-65.1/source/i18n/casetrn.cpp --- icu-64.2/source/i18n/casetrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/casetrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -125,7 +125,7 @@ /** * Transliterator API. */ -/*Transliterator* CaseMapTransliterator::clone(void) const { +/*CaseMapTransliterator* CaseMapTransliterator::clone() const { return new CaseMapTransliterator(*this); }*/ diff -Nru icu-64.2/source/i18n/casetrn.h icu-65.1/source/i18n/casetrn.h --- icu-64.2/source/i18n/casetrn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/casetrn.h 2019-10-03 11:16:41.000000000 +0000 @@ -58,7 +58,7 @@ * Transliterator API. * @return a copy of the object. */ - virtual Transliterator* clone(void) const = 0; + virtual CaseMapTransliterator* clone() const = 0; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/chnsecal.cpp icu-65.1/source/i18n/chnsecal.cpp --- icu-64.2/source/i18n/chnsecal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/chnsecal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -51,10 +51,7 @@ // --- The cache -- -static icu::UMutex *astroLock() { // Protects access to gChineseCalendarAstro. - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UMutex astroLock; static icu::CalendarAstronomer *gChineseCalendarAstro = NULL; // Lazy Creation & Access synchronized by class CalendarCache with a mutex. @@ -121,7 +118,7 @@ //------------------------------------------------------------------------- -Calendar* ChineseCalendar::clone() const { +ChineseCalendar* ChineseCalendar::clone() const { return new ChineseCalendar(*this); } @@ -538,14 +535,14 @@ // PST 1298 with a final result of Dec 14 10:31:59 PST 1299. double ms = daysToMillis(Grego::fieldsToDay(gyear, UCAL_DECEMBER, 1)); - umtx_lock(astroLock()); + umtx_lock(&astroLock); if(gChineseCalendarAstro == NULL) { gChineseCalendarAstro = new CalendarAstronomer(); ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup); } gChineseCalendarAstro->setTime(ms); UDate solarLong = gChineseCalendarAstro->getSunTime(CalendarAstronomer::WINTER_SOLSTICE(), TRUE); - umtx_unlock(astroLock()); + umtx_unlock(&astroLock); // Winter solstice is 270 degrees solar longitude aka Dongzhi cacheValue = (int32_t)millisToDays(solarLong); @@ -568,14 +565,14 @@ */ int32_t ChineseCalendar::newMoonNear(double days, UBool after) const { - umtx_lock(astroLock()); + umtx_lock(&astroLock); if(gChineseCalendarAstro == NULL) { gChineseCalendarAstro = new CalendarAstronomer(); ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup); } gChineseCalendarAstro->setTime(daysToMillis(days)); UDate newMoon = gChineseCalendarAstro->getMoonTime(CalendarAstronomer::NEW_MOON(), after); - umtx_unlock(astroLock()); + umtx_unlock(&astroLock); return (int32_t) millisToDays(newMoon); } @@ -600,14 +597,14 @@ */ int32_t ChineseCalendar::majorSolarTerm(int32_t days) const { - umtx_lock(astroLock()); + umtx_lock(&astroLock); if(gChineseCalendarAstro == NULL) { gChineseCalendarAstro = new CalendarAstronomer(); ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup); } gChineseCalendarAstro->setTime(daysToMillis(days)); UDate solarLongitude = gChineseCalendarAstro->getSunLongitude(); - umtx_unlock(astroLock()); + umtx_unlock(&astroLock); // Compute (floor(solarLongitude / (pi/6)) + 2) % 12 int32_t term = ( ((int32_t)(6 * solarLongitude / CalendarAstronomer::PI)) + 2 ) % 12; diff -Nru icu-64.2/source/i18n/chnsecal.h icu-65.1/source/i18n/chnsecal.h --- icu-64.2/source/i18n/chnsecal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/chnsecal.h 2019-10-03 11:16:41.000000000 +0000 @@ -144,7 +144,7 @@ virtual ~ChineseCalendar(); // clone - virtual Calendar* clone() const; + virtual ChineseCalendar* clone() const; private: diff -Nru icu-64.2/source/i18n/choicfmt.cpp icu-65.1/source/i18n/choicfmt.cpp --- icu-64.2/source/i18n/choicfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/choicfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -563,7 +563,7 @@ // ------------------------------------- -Format* +ChoiceFormat* ChoiceFormat::clone() const { ChoiceFormat *aCopy = new ChoiceFormat(*this); diff -Nru icu-64.2/source/i18n/collationiterator.cpp icu-65.1/source/i18n/collationiterator.cpp --- icu-64.2/source/i18n/collationiterator.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/collationiterator.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -872,7 +872,7 @@ // consistent with forward iteration. while(offsets.size() <= ceBuffer.length) { offsets.addElement(limitOffset, errorCode); - }; + } } return ceBuffer.get(--ceBuffer.length); } else { @@ -932,7 +932,7 @@ offset = getOffset(); while(offsets.size() < ceBuffer.length) { offsets.addElement(offset, errorCode); - }; + } } U_ASSERT(offsets.size() == ceBuffer.length); // End offset corresponding to just after the unsafe-backwards segment. diff -Nru icu-64.2/source/i18n/coll.cpp icu-65.1/source/i18n/coll.cpp --- icu-64.2/source/i18n/coll.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/coll.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -67,7 +67,7 @@ static icu::ICULocaleService* gService = NULL; static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; #endif -static icu::UInitOnce gAvailableLocaleListInitOnce; +static icu::UInitOnce gAvailableLocaleListInitOnce = U_INITONCE_INITIALIZER; /** * Release all static memory held by collator. diff -Nru icu-64.2/source/i18n/compactdecimalformat.cpp icu-65.1/source/i18n/compactdecimalformat.cpp --- icu-64.2/source/i18n/compactdecimalformat.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/compactdecimalformat.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -30,9 +30,9 @@ : DecimalFormat(new DecimalFormatSymbols(inLocale, status), status) { if (U_FAILURE(status)) return; // Minimal properties: let the non-shim code path do most of the logic for us. - fields->properties->compactStyle = style; - fields->properties->groupingSize = -2; // do not forward grouping information - fields->properties->minimumGroupingDigits = 2; + fields->properties.compactStyle = style; + fields->properties.groupingSize = -2; // do not forward grouping information + fields->properties.minimumGroupingDigits = 2; touch(status); } @@ -45,7 +45,7 @@ return *this; } -Format* CompactDecimalFormat::clone() const { +CompactDecimalFormat* CompactDecimalFormat::clone() const { return new CompactDecimalFormat(*this); } diff -Nru icu-64.2/source/i18n/coptccal.cpp icu-65.1/source/i18n/coptccal.cpp --- icu-64.2/source/i18n/coptccal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/coptccal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -40,7 +40,7 @@ { } -Calendar* +CopticCalendar* CopticCalendar::clone() const { return new CopticCalendar(*this); diff -Nru icu-64.2/source/i18n/coptccal.h icu-65.1/source/i18n/coptccal.h --- icu-64.2/source/i18n/coptccal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/coptccal.h 2019-10-03 11:16:41.000000000 +0000 @@ -145,7 +145,7 @@ * @return return a polymorphic copy of this calendar. * @internal */ - virtual Calendar* clone(void) const; + virtual CopticCalendar* clone() const; /** * return the calendar type, "coptic" diff -Nru icu-64.2/source/i18n/cpdtrans.cpp icu-65.1/source/i18n/cpdtrans.cpp --- icu-64.2/source/i18n/cpdtrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/cpdtrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -323,7 +323,7 @@ /** * Transliterator API. */ -Transliterator* CompoundTransliterator::clone(void) const { +CompoundTransliterator* CompoundTransliterator::clone() const { return new CompoundTransliterator(*this); } diff -Nru icu-64.2/source/i18n/cpdtrans.h icu-65.1/source/i18n/cpdtrans.h --- icu-64.2/source/i18n/cpdtrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/cpdtrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -98,7 +98,7 @@ /** * Transliterator API. */ - virtual Transliterator* clone(void) const; + virtual CompoundTransliterator* clone() const; /** * Returns the number of transliterators in this chain. diff -Nru icu-64.2/source/i18n/csdetect.cpp icu-65.1/source/i18n/csdetect.cpp --- icu-64.2/source/i18n/csdetect.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/csdetect.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -47,7 +47,7 @@ U_NAMESPACE_END static icu::CSRecognizerInfo **fCSRecognizers = NULL; -static icu::UInitOnce gCSRecognizersInitOnce; +static icu::UInitOnce gCSRecognizersInitOnce = U_INITONCE_INITIALIZER; static int32_t fCSRecognizers_size = 0; U_CDECL_BEGIN diff -Nru icu-64.2/source/i18n/curramt.cpp icu-65.1/source/i18n/curramt.cpp --- icu-64.2/source/i18n/curramt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/curramt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -38,7 +38,7 @@ return *this; } -UObject* CurrencyAmount::clone() const { +CurrencyAmount* CurrencyAmount::clone() const { return new CurrencyAmount(*this); } diff -Nru icu-64.2/source/i18n/currfmt.cpp icu-65.1/source/i18n/currfmt.cpp --- icu-64.2/source/i18n/currfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/currfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -33,7 +33,7 @@ CurrencyFormat::~CurrencyFormat() { } -Format* CurrencyFormat::clone() const { +CurrencyFormat* CurrencyFormat::clone() const { return new CurrencyFormat(*this); } diff -Nru icu-64.2/source/i18n/currfmt.h icu-65.1/source/i18n/currfmt.h --- icu-64.2/source/i18n/currfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/currfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -57,7 +57,7 @@ /** * Override Format API. */ - virtual Format* clone() const; + virtual CurrencyFormat* clone() const; using MeasureFormat::format; diff -Nru icu-64.2/source/i18n/currunit.cpp icu-65.1/source/i18n/currunit.cpp --- icu-64.2/source/i18n/currunit.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/currunit.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -109,7 +109,7 @@ return *this; } -UObject* CurrencyUnit::clone() const { +CurrencyUnit* CurrencyUnit::clone() const { return new CurrencyUnit(*this); } diff -Nru icu-64.2/source/i18n/dangical.cpp icu-65.1/source/i18n/dangical.cpp --- icu-64.2/source/i18n/dangical.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dangical.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -65,7 +65,7 @@ { } -Calendar* +DangiCalendar* DangiCalendar::clone() const { return new DangiCalendar(*this); diff -Nru icu-64.2/source/i18n/dangical.h icu-65.1/source/i18n/dangical.h --- icu-64.2/source/i18n/dangical.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dangical.h 2019-10-03 11:16:41.000000000 +0000 @@ -66,7 +66,7 @@ * Clone. * @internal */ - virtual Calendar* clone() const; + virtual DangiCalendar* clone() const; //---------------------------------------------------------------------- // Internal methods & astronomical calculations diff -Nru icu-64.2/source/i18n/datefmt.cpp icu-65.1/source/i18n/datefmt.cpp --- icu-64.2/source/i18n/datefmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/datefmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -154,7 +154,7 @@ fCalendar = NULL; } if(other.fNumberFormat) { - fNumberFormat = (NumberFormat*)other.fNumberFormat->clone(); + fNumberFormat = other.fNumberFormat->clone(); } else { fNumberFormat = NULL; } @@ -598,7 +598,7 @@ void DateFormat::setNumberFormat(const NumberFormat& newNumberFormat) { - NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone(); + NumberFormat* newNumFmtClone = newNumberFormat.clone(); if (newNumFmtClone != NULL) { adoptNumberFormat(newNumFmtClone); } diff -Nru icu-64.2/source/i18n/decimfmt.cpp icu-65.1/source/i18n/decimfmt.cpp --- icu-64.2/source/i18n/decimfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/decimfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -95,7 +95,7 @@ new CurrencyPluralInfo(fields->symbols->getLocale(), status), status); if (U_FAILURE(status)) { return; } - fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan()); + fields->properties.currencyPluralInfo.fPtr.adoptInstead(cpi.orphan()); } touch(status); } @@ -111,21 +111,14 @@ status = U_MEMORY_ALLOCATION_ERROR; return; } - fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status); - fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status); - fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status); if (adoptedSymbols.isNull()) { fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status); } else { fields->symbols.adoptInsteadAndCheckErrorCode(adoptedSymbols.orphan(), status); } - // In order to simplify error handling logic in the various getters/setters/etc, we do not allow - // any partially populated DecimalFormatFields object. We must have a fully complete fields object - // or else we set it to nullptr. - if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) { + if (U_FAILURE(status)) { delete fields; fields = nullptr; - status = U_MEMORY_ALLOCATION_ERROR; } } @@ -133,8 +126,8 @@ void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { if (fields == nullptr) { return; } - if (value == fields->properties->parseAllInput) { return; } - fields->properties->parseAllInput = value; + if (value == fields->properties.parseAllInput) { return; } + fields->properties.parseAllInput = value; } #endif @@ -379,9 +372,9 @@ if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(enabled) == fields->properties->groupingUsed) { return; } + if (UBOOL_TO_BOOL(enabled) == fields->properties.groupingUsed) { return; } NumberFormat::setGroupingUsed(enabled); // to set field for compatibility - fields->properties->groupingUsed = enabled; + fields->properties.groupingUsed = enabled; touchNoError(); } @@ -389,9 +382,9 @@ if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(value) == fields->properties->parseIntegerOnly) { return; } + if (UBOOL_TO_BOOL(value) == fields->properties.parseIntegerOnly) { return; } NumberFormat::setParseIntegerOnly(value); // to set field for compatibility - fields->properties->parseIntegerOnly = value; + fields->properties.parseIntegerOnly = value; touchNoError(); } @@ -400,9 +393,9 @@ return; } ParseMode mode = enable ? PARSE_MODE_LENIENT : PARSE_MODE_STRICT; - if (!fields->properties->parseMode.isNull() && mode == fields->properties->parseMode.getNoError()) { return; } + if (!fields->properties.parseMode.isNull() && mode == fields->properties.parseMode.getNoError()) { return; } NumberFormat::setLenient(enable); // to set field for compatibility - fields->properties->parseMode = mode; + fields->properties.parseMode = mode; touchNoError(); } @@ -441,19 +434,16 @@ // Note: it is not safe to copy fields->formatter or fWarehouse directly because fields->formatter might have // dangling pointers to fields inside fWarehouse. The safe thing is to re-construct fields->formatter from // the property bag, despite being somewhat slower. - fields = new DecimalFormatFields(); + fields = new DecimalFormatFields(source.fields->properties); if (fields == nullptr) { return; // no way to report an error. } UErrorCode status = U_ZERO_ERROR; - fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status); - fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(*source.fields->properties), status); fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(*source.fields->symbols), status); - fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status); // In order to simplify error handling logic in the various getters/setters/etc, we do not allow // any partially populated DecimalFormatFields object. We must have a fully complete fields object // or else we set it to nullptr. - if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) { + if (U_FAILURE(status)) { delete fields; fields = nullptr; return; @@ -470,8 +460,8 @@ if (fields == nullptr || rhs.fields == nullptr) { return *this; // unfortunately, no way to report an error. } - *fields->properties = *rhs.fields->properties; - fields->exportedProperties->clear(); + fields->properties = rhs.fields->properties; + fields->exportedProperties.clear(); UErrorCode status = U_ZERO_ERROR; LocalPointer dfs(new DecimalFormatSymbols(*rhs.fields->symbols), status); if (U_FAILURE(status)) { @@ -495,7 +485,7 @@ delete fields; } -Format* DecimalFormat::clone() const { +DecimalFormat* DecimalFormat::clone() const { // can only clone valid objects. if (fields == nullptr) { return nullptr; @@ -517,7 +507,7 @@ if (fields == nullptr || otherDF->fields == nullptr) { return false; } - return *fields->properties == *otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols; + return fields->properties == otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols; } UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const { @@ -529,7 +519,7 @@ return appendTo; } UErrorCode localStatus = U_ZERO_ERROR; - FormattedNumber output = fields->formatter->formatDouble(number, localStatus); + FormattedNumber output = fields->formatter.formatDouble(number, localStatus); fieldPositionHelper(output, pos, appendTo.length(), localStatus); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, localStatus); @@ -550,7 +540,7 @@ if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter->formatDouble(number, status); + FormattedNumber output = fields->formatter.formatDouble(number, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -572,7 +562,7 @@ if (posIter == nullptr && fastFormatDouble(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter->formatDouble(number, status); + FormattedNumber output = fields->formatter.formatDouble(number, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -603,7 +593,7 @@ return appendTo; } UErrorCode localStatus = U_ZERO_ERROR; - FormattedNumber output = fields->formatter->formatInt(number, localStatus); + FormattedNumber output = fields->formatter.formatInt(number, localStatus); fieldPositionHelper(output, pos, appendTo.length(), localStatus); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, localStatus); @@ -624,7 +614,7 @@ if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter->formatInt(number, status); + FormattedNumber output = fields->formatter.formatInt(number, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -646,7 +636,7 @@ if (posIter == nullptr && fastFormatInt64(number, appendTo)) { return appendTo; } - FormattedNumber output = fields->formatter->formatInt(number, status); + FormattedNumber output = fields->formatter.formatInt(number, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -665,7 +655,7 @@ appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter->formatDecimal(number, status); + FormattedNumber output = fields->formatter.formatDecimal(number, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -683,7 +673,7 @@ appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status); + FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status); fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -702,7 +692,7 @@ appendTo.setToBogus(); return appendTo; } - FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status); + FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status); fieldPositionHelper(output, pos, appendTo.length(), status); auto appendable = UnicodeStringAppendable(appendTo); output.appendTo(appendable, status); @@ -823,7 +813,7 @@ if (fields == nullptr) { return nullptr; } - return fields->properties->currencyPluralInfo.fPtr.getAlias(); + return fields->properties.currencyPluralInfo.fPtr.getAlias(); } void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) { @@ -833,7 +823,7 @@ if (fields == nullptr) { return; } - fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan()); + fields->properties.currencyPluralInfo.fPtr.adoptInstead(cpi.orphan()); touchNoError(); } @@ -841,11 +831,11 @@ if (fields == nullptr) { return; } - if (fields->properties->currencyPluralInfo.fPtr.isNull()) { + if (fields->properties.currencyPluralInfo.fPtr.isNull()) { // Note: clone() can fail with OOM error, but we have no way to report it. :( - fields->properties->currencyPluralInfo.fPtr.adoptInstead(info.clone()); + fields->properties.currencyPluralInfo.fPtr.adoptInstead(info.clone()); } else { - *fields->properties->currencyPluralInfo.fPtr = info; // copy-assignment operator + *fields->properties.currencyPluralInfo.fPtr = info; // copy-assignment operator } touchNoError(); } @@ -856,7 +846,7 @@ return result; } UErrorCode status = U_ZERO_ERROR; - fields->formatter->getAffixImpl(true, false, result, status); + fields->formatter.getAffixImpl(true, false, result, status); if (U_FAILURE(status)) { result.setToBogus(); } return result; } @@ -865,8 +855,8 @@ if (fields == nullptr) { return; } - if (newValue == fields->properties->positivePrefix) { return; } - fields->properties->positivePrefix = newValue; + if (newValue == fields->properties.positivePrefix) { return; } + fields->properties.positivePrefix = newValue; touchNoError(); } @@ -876,7 +866,7 @@ return result; } UErrorCode status = U_ZERO_ERROR; - fields->formatter->getAffixImpl(true, true, result, status); + fields->formatter.getAffixImpl(true, true, result, status); if (U_FAILURE(status)) { result.setToBogus(); } return result; } @@ -885,8 +875,8 @@ if (fields == nullptr) { return; } - if (newValue == fields->properties->negativePrefix) { return; } - fields->properties->negativePrefix = newValue; + if (newValue == fields->properties.negativePrefix) { return; } + fields->properties.negativePrefix = newValue; touchNoError(); } @@ -896,7 +886,7 @@ return result; } UErrorCode status = U_ZERO_ERROR; - fields->formatter->getAffixImpl(false, false, result, status); + fields->formatter.getAffixImpl(false, false, result, status); if (U_FAILURE(status)) { result.setToBogus(); } return result; } @@ -905,8 +895,8 @@ if (fields == nullptr) { return; } - if (newValue == fields->properties->positiveSuffix) { return; } - fields->properties->positiveSuffix = newValue; + if (newValue == fields->properties.positiveSuffix) { return; } + fields->properties.positiveSuffix = newValue; touchNoError(); } @@ -916,7 +906,7 @@ return result; } UErrorCode status = U_ZERO_ERROR; - fields->formatter->getAffixImpl(false, true, result, status); + fields->formatter.getAffixImpl(false, true, result, status); if (U_FAILURE(status)) { result.setToBogus(); } return result; } @@ -925,8 +915,8 @@ if (fields == nullptr) { return; } - if (newValue == fields->properties->negativeSuffix) { return; } - fields->properties->negativeSuffix = newValue; + if (newValue == fields->properties.negativeSuffix) { return; } + fields->properties.negativeSuffix = newValue; touchNoError(); } @@ -935,13 +925,13 @@ if (fields == nullptr) { return DecimalFormatProperties::getDefault().signAlwaysShown; } - return fields->properties->signAlwaysShown; + return fields->properties.signAlwaysShown; } void DecimalFormat::setSignAlwaysShown(UBool value) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(value) == fields->properties->signAlwaysShown) { return; } - fields->properties->signAlwaysShown = value; + if (UBOOL_TO_BOOL(value) == fields->properties.signAlwaysShown) { return; } + fields->properties.signAlwaysShown = value; touchNoError(); } @@ -952,7 +942,7 @@ // Fallback to using the default instance of DecimalFormatProperties. dfp = &(DecimalFormatProperties::getDefault()); } else { - dfp = fields->properties.getAlias(); + dfp = &fields->properties; } if (dfp->multiplier != 1) { return dfp->multiplier; @@ -984,11 +974,11 @@ value = temp; } if (delta != -1) { - fields->properties->magnitudeMultiplier = delta; - fields->properties->multiplier = 1; + fields->properties.magnitudeMultiplier = delta; + fields->properties.multiplier = 1; } else { - fields->properties->magnitudeMultiplier = 0; - fields->properties->multiplier = multiplier; + fields->properties.magnitudeMultiplier = 0; + fields->properties.multiplier = multiplier; } touchNoError(); } @@ -999,13 +989,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().multiplierScale; } - return fields->properties->multiplierScale; + return fields->properties.multiplierScale; } void DecimalFormat::setMultiplierScale(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->multiplierScale) { return; } - fields->properties->multiplierScale = newValue; + if (newValue == fields->properties.multiplierScale) { return; } + fields->properties.multiplierScale = newValue; touchNoError(); } @@ -1015,13 +1005,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().roundingIncrement; } - return fields->exportedProperties->roundingIncrement; + return fields->exportedProperties.roundingIncrement; } void DecimalFormat::setRoundingIncrement(double newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->roundingIncrement) { return; } - fields->properties->roundingIncrement = newValue; + if (newValue == fields->properties.roundingIncrement) { return; } + fields->properties.roundingIncrement = newValue; touchNoError(); } @@ -1032,17 +1022,17 @@ return static_cast(DecimalFormatProperties::getDefault().roundingMode.getNoError()); } // UNumberFormatRoundingMode and ERoundingMode have the same values. - return static_cast(fields->exportedProperties->roundingMode.getNoError()); + return static_cast(fields->exportedProperties.roundingMode.getNoError()); } void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) { if (fields == nullptr) { return; } auto uRoundingMode = static_cast(roundingMode); - if (!fields->properties->roundingMode.isNull() && uRoundingMode == fields->properties->roundingMode.getNoError()) { + if (!fields->properties.roundingMode.isNull() && uRoundingMode == fields->properties.roundingMode.getNoError()) { return; } NumberFormat::setMaximumIntegerDigits(roundingMode); // to set field for compatibility - fields->properties->roundingMode = uRoundingMode; + fields->properties.roundingMode = uRoundingMode; touchNoError(); } @@ -1052,52 +1042,52 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().formatWidth; } - return fields->properties->formatWidth; + return fields->properties.formatWidth; } void DecimalFormat::setFormatWidth(int32_t width) { if (fields == nullptr) { return; } - if (width == fields->properties->formatWidth) { return; } - fields->properties->formatWidth = width; + if (width == fields->properties.formatWidth) { return; } + fields->properties.formatWidth = width; touchNoError(); } UnicodeString DecimalFormat::getPadCharacterString() const { - if (fields == nullptr || fields->properties->padString.isBogus()) { + if (fields == nullptr || fields->properties.padString.isBogus()) { // Readonly-alias the static string kFallbackPaddingString return {TRUE, kFallbackPaddingString, -1}; } else { - return fields->properties->padString; + return fields->properties.padString; } } void DecimalFormat::setPadCharacter(const UnicodeString& padChar) { if (fields == nullptr) { return; } - if (padChar == fields->properties->padString) { return; } + if (padChar == fields->properties.padString) { return; } if (padChar.length() > 0) { - fields->properties->padString = UnicodeString(padChar.char32At(0)); + fields->properties.padString = UnicodeString(padChar.char32At(0)); } else { - fields->properties->padString.setToBogus(); + fields->properties.padString.setToBogus(); } touchNoError(); } EPadPosition DecimalFormat::getPadPosition(void) const { - if (fields == nullptr || fields->properties->padPosition.isNull()) { + if (fields == nullptr || fields->properties.padPosition.isNull()) { return EPadPosition::kPadBeforePrefix; } else { // UNumberFormatPadPosition and EPadPosition have the same values. - return static_cast(fields->properties->padPosition.getNoError()); + return static_cast(fields->properties.padPosition.getNoError()); } } void DecimalFormat::setPadPosition(EPadPosition padPos) { if (fields == nullptr) { return; } auto uPadPos = static_cast(padPos); - if (!fields->properties->padPosition.isNull() && uPadPos == fields->properties->padPosition.getNoError()) { + if (!fields->properties.padPosition.isNull() && uPadPos == fields->properties.padPosition.getNoError()) { return; } - fields->properties->padPosition = uPadPos; + fields->properties.padPosition = uPadPos; touchNoError(); } @@ -1107,17 +1097,17 @@ // Fallback to using the default instance of DecimalFormatProperties. return (DecimalFormatProperties::getDefault().minimumExponentDigits != -1); } - return (fields->properties->minimumExponentDigits != -1); + return (fields->properties.minimumExponentDigits != -1); } void DecimalFormat::setScientificNotation(UBool useScientific) { if (fields == nullptr) { return; } int32_t minExp = useScientific ? 1 : -1; - if (fields->properties->minimumExponentDigits == minExp) { return; } + if (fields->properties.minimumExponentDigits == minExp) { return; } if (useScientific) { - fields->properties->minimumExponentDigits = 1; + fields->properties.minimumExponentDigits = 1; } else { - fields->properties->minimumExponentDigits = -1; + fields->properties.minimumExponentDigits = -1; } touchNoError(); } @@ -1128,13 +1118,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return static_cast(DecimalFormatProperties::getDefault().minimumExponentDigits); } - return static_cast(fields->properties->minimumExponentDigits); + return static_cast(fields->properties.minimumExponentDigits); } void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) { if (fields == nullptr) { return; } - if (minExpDig == fields->properties->minimumExponentDigits) { return; } - fields->properties->minimumExponentDigits = minExpDig; + if (minExpDig == fields->properties.minimumExponentDigits) { return; } + fields->properties.minimumExponentDigits = minExpDig; touchNoError(); } @@ -1144,13 +1134,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().exponentSignAlwaysShown; } - return fields->properties->exponentSignAlwaysShown; + return fields->properties.exponentSignAlwaysShown; } void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(expSignAlways) == fields->properties->exponentSignAlwaysShown) { return; } - fields->properties->exponentSignAlwaysShown = expSignAlways; + if (UBOOL_TO_BOOL(expSignAlways) == fields->properties.exponentSignAlwaysShown) { return; } + fields->properties.exponentSignAlwaysShown = expSignAlways; touchNoError(); } @@ -1161,7 +1151,7 @@ // Fallback to using the default instance of DecimalFormatProperties. groupingSize = DecimalFormatProperties::getDefault().groupingSize; } else { - groupingSize = fields->properties->groupingSize; + groupingSize = fields->properties.groupingSize; } if (groupingSize < 0) { return 0; @@ -1171,8 +1161,8 @@ void DecimalFormat::setGroupingSize(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->groupingSize) { return; } - fields->properties->groupingSize = newValue; + if (newValue == fields->properties.groupingSize) { return; } + fields->properties.groupingSize = newValue; touchNoError(); } @@ -1183,7 +1173,7 @@ // Fallback to using the default instance of DecimalFormatProperties. grouping2 = DecimalFormatProperties::getDefault().secondaryGroupingSize; } else { - grouping2 = fields->properties->secondaryGroupingSize; + grouping2 = fields->properties.secondaryGroupingSize; } if (grouping2 < 0) { return 0; @@ -1193,8 +1183,8 @@ void DecimalFormat::setSecondaryGroupingSize(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->secondaryGroupingSize) { return; } - fields->properties->secondaryGroupingSize = newValue; + if (newValue == fields->properties.secondaryGroupingSize) { return; } + fields->properties.secondaryGroupingSize = newValue; touchNoError(); } @@ -1204,13 +1194,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().minimumGroupingDigits; } - return fields->properties->minimumGroupingDigits; + return fields->properties.minimumGroupingDigits; } void DecimalFormat::setMinimumGroupingDigits(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->minimumGroupingDigits) { return; } - fields->properties->minimumGroupingDigits = newValue; + if (newValue == fields->properties.minimumGroupingDigits) { return; } + fields->properties.minimumGroupingDigits = newValue; touchNoError(); } @@ -1220,13 +1210,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().decimalSeparatorAlwaysShown; } - return fields->properties->decimalSeparatorAlwaysShown; + return fields->properties.decimalSeparatorAlwaysShown; } void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalSeparatorAlwaysShown) { return; } - fields->properties->decimalSeparatorAlwaysShown = newValue; + if (UBOOL_TO_BOOL(newValue) == fields->properties.decimalSeparatorAlwaysShown) { return; } + fields->properties.decimalSeparatorAlwaysShown = newValue; touchNoError(); } @@ -1236,13 +1226,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().decimalPatternMatchRequired; } - return fields->properties->decimalPatternMatchRequired; + return fields->properties.decimalPatternMatchRequired; } void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalPatternMatchRequired) { return; } - fields->properties->decimalPatternMatchRequired = newValue; + if (UBOOL_TO_BOOL(newValue) == fields->properties.decimalPatternMatchRequired) { return; } + fields->properties.decimalPatternMatchRequired = newValue; touchNoError(); } @@ -1252,13 +1242,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().parseNoExponent; } - return fields->properties->parseNoExponent; + return fields->properties.parseNoExponent; } void DecimalFormat::setParseNoExponent(UBool value) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(value) == fields->properties->parseNoExponent) { return; } - fields->properties->parseNoExponent = value; + if (UBOOL_TO_BOOL(value) == fields->properties.parseNoExponent) { return; } + fields->properties.parseNoExponent = value; touchNoError(); } @@ -1268,13 +1258,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().parseCaseSensitive; } - return fields->properties->parseCaseSensitive; + return fields->properties.parseCaseSensitive; } void DecimalFormat::setParseCaseSensitive(UBool value) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(value) == fields->properties->parseCaseSensitive) { return; } - fields->properties->parseCaseSensitive = value; + if (UBOOL_TO_BOOL(value) == fields->properties.parseCaseSensitive) { return; } + fields->properties.parseCaseSensitive = value; touchNoError(); } @@ -1284,13 +1274,13 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().formatFailIfMoreThanMaxDigits; } - return fields->properties->formatFailIfMoreThanMaxDigits; + return fields->properties.formatFailIfMoreThanMaxDigits; } void DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool value) { if (fields == nullptr) { return; } - if (UBOOL_TO_BOOL(value) == fields->properties->formatFailIfMoreThanMaxDigits) { return; } - fields->properties->formatFailIfMoreThanMaxDigits = value; + if (UBOOL_TO_BOOL(value) == fields->properties.formatFailIfMoreThanMaxDigits) { return; } + fields->properties.formatFailIfMoreThanMaxDigits = value; touchNoError(); } @@ -1305,7 +1295,7 @@ // so that CurrencyUsage is reflected properly. // TODO: Consider putting this logic in number_patternstring.cpp instead. ErrorCode localStatus; - DecimalFormatProperties tprops(*fields->properties); + DecimalFormatProperties tprops(fields->properties); bool useCurrency = ( !tprops.currency.isNull() || !tprops.currencyPluralInfo.fPtr.isNull() || @@ -1315,9 +1305,9 @@ AffixUtils::hasCurrencySymbols(tprops.negativePrefixPattern, localStatus) || AffixUtils::hasCurrencySymbols(tprops.negativeSuffixPattern, localStatus)); if (useCurrency) { - tprops.minimumFractionDigits = fields->exportedProperties->minimumFractionDigits; - tprops.maximumFractionDigits = fields->exportedProperties->maximumFractionDigits; - tprops.roundingIncrement = fields->exportedProperties->roundingIncrement; + tprops.minimumFractionDigits = fields->exportedProperties.minimumFractionDigits; + tprops.maximumFractionDigits = fields->exportedProperties.maximumFractionDigits; + tprops.roundingIncrement = fields->exportedProperties.roundingIncrement; } result = PatternStringUtils::propertiesToPatternString(tprops, localStatus); return result; @@ -1373,49 +1363,53 @@ void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->maximumIntegerDigits) { return; } + if (newValue == fields->properties.maximumIntegerDigits) { return; } // For backwards compatibility, conflicting min/max need to keep the most recent setting. - int32_t min = fields->properties->minimumIntegerDigits; + int32_t min = fields->properties.minimumIntegerDigits; if (min >= 0 && min > newValue) { - fields->properties->minimumIntegerDigits = newValue; + fields->properties.minimumIntegerDigits = newValue; } - fields->properties->maximumIntegerDigits = newValue; + fields->properties.maximumIntegerDigits = newValue; touchNoError(); } void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->minimumIntegerDigits) { return; } + if (newValue == fields->properties.minimumIntegerDigits) { return; } // For backwards compatibility, conflicting min/max need to keep the most recent setting. - int32_t max = fields->properties->maximumIntegerDigits; + int32_t max = fields->properties.maximumIntegerDigits; if (max >= 0 && max < newValue) { - fields->properties->maximumIntegerDigits = newValue; + fields->properties.maximumIntegerDigits = newValue; } - fields->properties->minimumIntegerDigits = newValue; + fields->properties.minimumIntegerDigits = newValue; touchNoError(); } void DecimalFormat::setMaximumFractionDigits(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->maximumFractionDigits) { return; } + if (newValue == fields->properties.maximumFractionDigits) { return; } + // cap for backward compatibility, formerly 340, now 999 + if (newValue > kMaxIntFracSig) { + newValue = kMaxIntFracSig; + } // For backwards compatibility, conflicting min/max need to keep the most recent setting. - int32_t min = fields->properties->minimumFractionDigits; + int32_t min = fields->properties.minimumFractionDigits; if (min >= 0 && min > newValue) { - fields->properties->minimumFractionDigits = newValue; + fields->properties.minimumFractionDigits = newValue; } - fields->properties->maximumFractionDigits = newValue; + fields->properties.maximumFractionDigits = newValue; touchNoError(); } void DecimalFormat::setMinimumFractionDigits(int32_t newValue) { if (fields == nullptr) { return; } - if (newValue == fields->properties->minimumFractionDigits) { return; } + if (newValue == fields->properties.minimumFractionDigits) { return; } // For backwards compatibility, conflicting min/max need to keep the most recent setting. - int32_t max = fields->properties->maximumFractionDigits; + int32_t max = fields->properties.maximumFractionDigits; if (max >= 0 && max < newValue) { - fields->properties->maximumFractionDigits = newValue; + fields->properties.maximumFractionDigits = newValue; } - fields->properties->minimumFractionDigits = newValue; + fields->properties.minimumFractionDigits = newValue; touchNoError(); } @@ -1425,7 +1419,7 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().minimumSignificantDigits; } - return fields->exportedProperties->minimumSignificantDigits; + return fields->exportedProperties.minimumSignificantDigits; } int32_t DecimalFormat::getMaximumSignificantDigits() const { @@ -1434,28 +1428,28 @@ // Fallback to using the default instance of DecimalFormatProperties. return DecimalFormatProperties::getDefault().maximumSignificantDigits; } - return fields->exportedProperties->maximumSignificantDigits; + return fields->exportedProperties.maximumSignificantDigits; } void DecimalFormat::setMinimumSignificantDigits(int32_t value) { if (fields == nullptr) { return; } - if (value == fields->properties->minimumSignificantDigits) { return; } - int32_t max = fields->properties->maximumSignificantDigits; + if (value == fields->properties.minimumSignificantDigits) { return; } + int32_t max = fields->properties.maximumSignificantDigits; if (max >= 0 && max < value) { - fields->properties->maximumSignificantDigits = value; + fields->properties.maximumSignificantDigits = value; } - fields->properties->minimumSignificantDigits = value; + fields->properties.minimumSignificantDigits = value; touchNoError(); } void DecimalFormat::setMaximumSignificantDigits(int32_t value) { if (fields == nullptr) { return; } - if (value == fields->properties->maximumSignificantDigits) { return; } - int32_t min = fields->properties->minimumSignificantDigits; + if (value == fields->properties.maximumSignificantDigits) { return; } + int32_t min = fields->properties.minimumSignificantDigits; if (min >= 0 && min > value) { - fields->properties->minimumSignificantDigits = value; + fields->properties.minimumSignificantDigits = value; } - fields->properties->maximumSignificantDigits = value; + fields->properties.maximumSignificantDigits = value; touchNoError(); } @@ -1466,7 +1460,7 @@ // Fallback to using the default instance of DecimalFormatProperties. dfp = &(DecimalFormatProperties::getDefault()); } else { - dfp = fields->properties.getAlias(); + dfp = &fields->properties; } return dfp->minimumSignificantDigits != -1 || dfp->maximumSignificantDigits != -1; } @@ -1476,20 +1470,20 @@ // These are the default values from the old implementation. if (useSignificantDigits) { - if (fields->properties->minimumSignificantDigits != -1 || - fields->properties->maximumSignificantDigits != -1) { + if (fields->properties.minimumSignificantDigits != -1 || + fields->properties.maximumSignificantDigits != -1) { return; } } else { - if (fields->properties->minimumSignificantDigits == -1 && - fields->properties->maximumSignificantDigits == -1) { + if (fields->properties.minimumSignificantDigits == -1 && + fields->properties.maximumSignificantDigits == -1) { return; } } int32_t minSig = useSignificantDigits ? 1 : -1; int32_t maxSig = useSignificantDigits ? 6 : -1; - fields->properties->minimumSignificantDigits = minSig; - fields->properties->maximumSignificantDigits = maxSig; + fields->properties.minimumSignificantDigits = minSig; + fields->properties.maximumSignificantDigits = maxSig; touchNoError(); } @@ -1503,11 +1497,11 @@ } CurrencyUnit currencyUnit(theCurrency, ec); if (U_FAILURE(ec)) { return; } - if (!fields->properties->currency.isNull() && fields->properties->currency.getNoError() == currencyUnit) { + if (!fields->properties.currency.isNull() && fields->properties.currency.getNoError() == currencyUnit) { return; } NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility - fields->properties->currency = currencyUnit; + fields->properties.currency = currencyUnit; // TODO: Set values in fields->symbols, too? touchNoError(); } @@ -1525,20 +1519,20 @@ *ec = U_MEMORY_ALLOCATION_ERROR; return; } - if (!fields->properties->currencyUsage.isNull() && newUsage == fields->properties->currencyUsage.getNoError()) { + if (!fields->properties.currencyUsage.isNull() && newUsage == fields->properties.currencyUsage.getNoError()) { return; } - fields->properties->currencyUsage = newUsage; + fields->properties.currencyUsage = newUsage; touch(*ec); } UCurrencyUsage DecimalFormat::getCurrencyUsage() const { // CurrencyUsage is not exported, so we have to get it from the input property bag. // TODO: Should we export CurrencyUsage instead? - if (fields == nullptr || fields->properties->currencyUsage.isNull()) { + if (fields == nullptr || fields->properties.currencyUsage.isNull()) { return UCURR_USAGE_STANDARD; } - return fields->properties->currencyUsage.getNoError(); + return fields->properties.currencyUsage.getNoError(); } void @@ -1550,7 +1544,7 @@ status = U_MEMORY_ALLOCATION_ERROR; return; } - fields->formatter->formatDouble(number, status).getDecimalQuantity(output, status); + fields->formatter.formatDouble(number, status).getDecimalQuantity(output, status); } void DecimalFormat::formatToDecimalQuantity(const Formattable& number, DecimalQuantity& output, @@ -1564,7 +1558,7 @@ } UFormattedNumberData obj; number.populateDecimalQuantity(obj.quantity, status); - fields->formatter->formatImpl(&obj, status); + fields->formatter.formatImpl(&obj, status); output = std::move(obj.quantity); } @@ -1576,12 +1570,7 @@ status = U_MEMORY_ALLOCATION_ERROR; return nullptr; } - return &*fields->formatter; -} - -const number::LocalizedNumberFormatter& DecimalFormat::toNumberFormatter() const { - UErrorCode localStatus = U_ZERO_ERROR; - return *toNumberFormatter(localStatus); + return &fields->formatter; } /** Rebuilds the formatter object from the property bag. */ @@ -1608,9 +1597,9 @@ // Since memory has already been allocated for the formatter, we can move assign a stack-allocated object // and don't need to call new. (Which is slower and could possibly fail). - *fields->formatter = NumberPropertyMapper::create( - *fields->properties, *fields->symbols, fields->warehouse, *fields->exportedProperties, status).locale( - locale); + fields->formatter = NumberPropertyMapper::create( + fields->properties, *fields->symbols, fields->warehouse, fields->exportedProperties, status + ).locale(locale); // Do this after fields->exportedProperties are set up setupFastFormat(); @@ -1620,13 +1609,13 @@ delete fields->atomicCurrencyParser.exchange(nullptr); // In order for the getters to work, we need to populate some fields in NumberFormat. - NumberFormat::setCurrency(fields->exportedProperties->currency.get(status).getISOCurrency(), status); - NumberFormat::setMaximumIntegerDigits(fields->exportedProperties->maximumIntegerDigits); - NumberFormat::setMinimumIntegerDigits(fields->exportedProperties->minimumIntegerDigits); - NumberFormat::setMaximumFractionDigits(fields->exportedProperties->maximumFractionDigits); - NumberFormat::setMinimumFractionDigits(fields->exportedProperties->minimumFractionDigits); + NumberFormat::setCurrency(fields->exportedProperties.currency.get(status).getISOCurrency(), status); + NumberFormat::setMaximumIntegerDigits(fields->exportedProperties.maximumIntegerDigits); + NumberFormat::setMinimumIntegerDigits(fields->exportedProperties.minimumIntegerDigits); + NumberFormat::setMaximumFractionDigits(fields->exportedProperties.maximumFractionDigits); + NumberFormat::setMinimumFractionDigits(fields->exportedProperties.minimumFractionDigits); // fImpl->properties, not fields->exportedProperties, since this information comes from the pattern: - NumberFormat::setGroupingUsed(fields->properties->groupingUsed); + NumberFormat::setGroupingUsed(fields->properties.groupingUsed); } void DecimalFormat::touchNoError() { @@ -1639,7 +1628,7 @@ if (U_SUCCESS(status)) { // Cast workaround to get around putting the enum in the public header file auto actualIgnoreRounding = static_cast(ignoreRounding); - PatternParser::parseToExistingProperties(pattern, *fields->properties, actualIgnoreRounding, status); + PatternParser::parseToExistingProperties(pattern, fields->properties, actualIgnoreRounding, status); } } @@ -1658,7 +1647,7 @@ } // Try computing the parser on our own - auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, false, status); + auto* temp = NumberParserImpl::createParserFromProperties(fields->properties, *fields->symbols, false, status); if (U_FAILURE(status)) { return nullptr; } @@ -1691,7 +1680,7 @@ } // Try computing the parser on our own - auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, true, status); + auto* temp = NumberParserImpl::createParserFromProperties(fields->properties, *fields->symbols, true, status); if (temp == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; // although we may still dereference, call sites should be guarded @@ -1739,7 +1728,7 @@ void DecimalFormat::setupFastFormat() { // Check the majority of properties: - if (!fields->properties->equalsDefaultExceptFastFormat()) { + if (!fields->properties.equalsDefaultExceptFastFormat()) { trace("no fast format: equality\n"); fields->canUseFastFormat = false; return; @@ -1747,12 +1736,12 @@ // Now check the remaining properties. // Nontrivial affixes: - UBool trivialPP = fields->properties->positivePrefixPattern.isEmpty(); - UBool trivialPS = fields->properties->positiveSuffixPattern.isEmpty(); - UBool trivialNP = fields->properties->negativePrefixPattern.isBogus() || ( - fields->properties->negativePrefixPattern.length() == 1 && - fields->properties->negativePrefixPattern.charAt(0) == u'-'); - UBool trivialNS = fields->properties->negativeSuffixPattern.isEmpty(); + UBool trivialPP = fields->properties.positivePrefixPattern.isEmpty(); + UBool trivialPS = fields->properties.positiveSuffixPattern.isEmpty(); + UBool trivialNP = fields->properties.negativePrefixPattern.isBogus() || ( + fields->properties.negativePrefixPattern.length() == 1 && + fields->properties.negativePrefixPattern.charAt(0) == u'-'); + UBool trivialNS = fields->properties.negativeSuffixPattern.isEmpty(); if (!trivialPP || !trivialPS || !trivialNP || !trivialNS) { trace("no fast format: affixes\n"); fields->canUseFastFormat = false; @@ -1760,8 +1749,8 @@ } // Grouping (secondary grouping is forbidden in equalsDefaultExceptFastFormat): - bool groupingUsed = fields->properties->groupingUsed; - int32_t groupingSize = fields->properties->groupingSize; + bool groupingUsed = fields->properties.groupingUsed; + int32_t groupingSize = fields->properties.groupingSize; bool unusualGroupingSize = groupingSize > 0 && groupingSize != 3; const UnicodeString& groupingString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); if (groupingUsed && (unusualGroupingSize || groupingString.length() != 1)) { @@ -1771,8 +1760,8 @@ } // Integer length: - int32_t minInt = fields->exportedProperties->minimumIntegerDigits; - int32_t maxInt = fields->exportedProperties->maximumIntegerDigits; + int32_t minInt = fields->exportedProperties.minimumIntegerDigits; + int32_t maxInt = fields->exportedProperties.maximumIntegerDigits; // Fastpath supports up to only 10 digits (length of INT32_MIN) if (minInt > 10) { trace("no fast format: integer\n"); @@ -1781,7 +1770,7 @@ } // Fraction length (no fraction part allowed in fast path): - int32_t minFrac = fields->exportedProperties->minimumFractionDigits; + int32_t minFrac = fields->exportedProperties.minimumFractionDigits; if (minFrac > 0) { trace("no fast format: fraction\n"); fields->canUseFastFormat = false; diff -Nru icu-64.2/source/i18n/decNumberLocal.h icu-65.1/source/i18n/decNumberLocal.h --- icu-64.2/source/i18n/decNumberLocal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/decNumberLocal.h 2019-10-03 11:16:41.000000000 +0000 @@ -259,7 +259,7 @@ /* 2,000,000,000 (as is needed for negative exponents of */ /* subnormals). The unsigned integer pow is used as a temporary */ /* variable. */ - #define TODIGIT(u, cut, c, pow) { \ + #define TODIGIT(u, cut, c, pow) UPRV_BLOCK_MACRO_BEGIN { \ *(c)='0'; \ pow=DECPOWERS[cut]*2; \ if ((u)>pow) { \ @@ -272,7 +272,7 @@ if ((u)>=pow) {(u)-=pow; *(c)+=2;} \ pow/=2; \ if ((u)>=pow) {(u)-=pow; *(c)+=1;} \ - } + } UPRV_BLOCK_MACRO_END /* ---------------------------------------------------------------- */ /* Definitions for fixed-precision modules (only valid after */ diff -Nru icu-64.2/source/i18n/double-conversion-bignum.cpp icu-65.1/source/i18n/double-conversion-bignum.cpp --- icu-64.2/source/i18n/double-conversion-bignum.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-bignum.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -34,6 +34,9 @@ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING +#include +#include + // ICU PATCH: Customize header file paths for ICU. #include "double-conversion-bignum.h" @@ -44,136 +47,129 @@ namespace double_conversion { -Bignum::Bignum() - : bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { - for (int i = 0; i < kBigitCapacity; ++i) { - bigits_[i] = 0; - } +Bignum::Chunk& Bignum::RawBigit(const int index) { + DOUBLE_CONVERSION_ASSERT(static_cast(index) < kBigitCapacity); + return bigits_buffer_[index]; +} + + +const Bignum::Chunk& Bignum::RawBigit(const int index) const { + DOUBLE_CONVERSION_ASSERT(static_cast(index) < kBigitCapacity); + return bigits_buffer_[index]; } template -static int BitSize(S value) { +static int BitSize(const S value) { (void) value; // Mark variable as used. return 8 * sizeof(value); } // Guaranteed to lie in one Bigit. -void Bignum::AssignUInt16(uint16_t value) { - ASSERT(kBigitSize >= BitSize(value)); +void Bignum::AssignUInt16(const uint16_t value) { + DOUBLE_CONVERSION_ASSERT(kBigitSize >= BitSize(value)); Zero(); - if (value == 0) return; - - EnsureCapacity(1); - bigits_[0] = value; - used_digits_ = 1; + if (value > 0) { + RawBigit(0) = value; + used_bigits_ = 1; + } } void Bignum::AssignUInt64(uint64_t value) { - const int kUInt64Size = 64; - Zero(); - if (value == 0) return; - - int needed_bigits = kUInt64Size / kBigitSize + 1; - EnsureCapacity(needed_bigits); - for (int i = 0; i < needed_bigits; ++i) { - bigits_[i] = value & kBigitMask; - value = value >> kBigitSize; + for(int i = 0; value > 0; ++i) { + RawBigit(i) = value & kBigitMask; + value >>= kBigitSize; + ++used_bigits_; } - used_digits_ = needed_bigits; - Clamp(); } void Bignum::AssignBignum(const Bignum& other) { exponent_ = other.exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - bigits_[i] = other.bigits_[i]; + for (int i = 0; i < other.used_bigits_; ++i) { + RawBigit(i) = other.RawBigit(i); } - // Clear the excess digits (if there were any). - for (int i = other.used_digits_; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = other.used_digits_; + used_bigits_ = other.used_bigits_; } -static uint64_t ReadUInt64(Vector buffer, - int from, - int digits_to_read) { +static uint64_t ReadUInt64(const Vector buffer, + const int from, + const int digits_to_read) { uint64_t result = 0; for (int i = from; i < from + digits_to_read; ++i) { - int digit = buffer[i] - '0'; - ASSERT(0 <= digit && digit <= 9); + const int digit = buffer[i] - '0'; + DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9); result = result * 10 + digit; } return result; } -void Bignum::AssignDecimalString(Vector value) { +void Bignum::AssignDecimalString(const Vector value) { // 2^64 = 18446744073709551616 > 10^19 - const int kMaxUint64DecimalDigits = 19; + static const int kMaxUint64DecimalDigits = 19; Zero(); int length = value.length(); - unsigned int pos = 0; + unsigned pos = 0; // Let's just say that each digit needs 4 bits. while (length >= kMaxUint64DecimalDigits) { - uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); + const uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); pos += kMaxUint64DecimalDigits; length -= kMaxUint64DecimalDigits; MultiplyByPowerOfTen(kMaxUint64DecimalDigits); AddUInt64(digits); } - uint64_t digits = ReadUInt64(value, pos, length); + const uint64_t digits = ReadUInt64(value, pos, length); MultiplyByPowerOfTen(length); AddUInt64(digits); Clamp(); } -static int HexCharValue(char c) { - if ('0' <= c && c <= '9') return c - '0'; - if ('a' <= c && c <= 'f') return 10 + c - 'a'; - ASSERT('A' <= c && c <= 'F'); +static uint64_t HexCharValue(const int c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } + if ('a' <= c && c <= 'f') { + return 10 + c - 'a'; + } + DOUBLE_CONVERSION_ASSERT('A' <= c && c <= 'F'); return 10 + c - 'A'; } +// Unlike AssignDecimalString(), this function is "only" used +// for unit-tests and therefore not performance critical. void Bignum::AssignHexString(Vector value) { Zero(); - int length = value.length(); - - int needed_bigits = length * 4 / kBigitSize + 1; - EnsureCapacity(needed_bigits); - int string_index = length - 1; - for (int i = 0; i < needed_bigits - 1; ++i) { - // These bigits are guaranteed to be "full". - Chunk current_bigit = 0; - for (int j = 0; j < kBigitSize / 4; j++) { - current_bigit += HexCharValue(value[string_index--]) << (j * 4); - } - bigits_[i] = current_bigit; - } - used_digits_ = needed_bigits - 1; - - Chunk most_significant_bigit = 0; // Could be = 0; - for (int j = 0; j <= string_index; ++j) { - most_significant_bigit <<= 4; - most_significant_bigit += HexCharValue(value[j]); - } - if (most_significant_bigit != 0) { - bigits_[used_digits_] = most_significant_bigit; - used_digits_++; + // Required capacity could be reduced by ignoring leading zeros. + EnsureCapacity(((value.length() * 4) + kBigitSize - 1) / kBigitSize); + DOUBLE_CONVERSION_ASSERT(sizeof(uint64_t) * 8 >= kBigitSize + 4); // TODO: static_assert + // Accumulates converted hex digits until at least kBigitSize bits. + // Works with non-factor-of-four kBigitSizes. + uint64_t tmp = 0; // Accumulates converted hex digits until at least + for (int cnt = 0; !value.is_empty(); value.pop_back()) { + tmp |= (HexCharValue(value.last()) << cnt); + if ((cnt += 4) >= kBigitSize) { + RawBigit(used_bigits_++) = (tmp & kBigitMask); + cnt -= kBigitSize; + tmp >>= kBigitSize; + } + } + if (tmp > 0) { + RawBigit(used_bigits_++) = tmp; } Clamp(); } -void Bignum::AddUInt64(uint64_t operand) { - if (operand == 0) return; +void Bignum::AddUInt64(const uint64_t operand) { + if (operand == 0) { + return; + } Bignum other; other.AssignUInt64(operand); AddBignum(other); @@ -181,8 +177,8 @@ void Bignum::AddBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); + DOUBLE_CONVERSION_ASSERT(IsClamped()); + DOUBLE_CONVERSION_ASSERT(other.IsClamped()); // If this has a greater exponent than other append zero-bigits to this. // After this call exponent_ <= other.exponent_. @@ -200,48 +196,52 @@ // cccccccccccc 0000 // In both cases we might need a carry bigit. - EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); + EnsureCapacity(1 + (std::max)(BigitLength(), other.BigitLength()) - exponent_); Chunk carry = 0; int bigit_pos = other.exponent_ - exponent_; - ASSERT(bigit_pos >= 0); - for (int i = 0; i < other.used_digits_; ++i) { - Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; - bigits_[bigit_pos] = sum & kBigitMask; + DOUBLE_CONVERSION_ASSERT(bigit_pos >= 0); + for (int i = used_bigits_; i < bigit_pos; ++i) { + RawBigit(i) = 0; + } + for (int i = 0; i < other.used_bigits_; ++i) { + const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0; + const Chunk sum = my + other.RawBigit(i) + carry; + RawBigit(bigit_pos) = sum & kBigitMask; carry = sum >> kBigitSize; - bigit_pos++; + ++bigit_pos; } - while (carry != 0) { - Chunk sum = bigits_[bigit_pos] + carry; - bigits_[bigit_pos] = sum & kBigitMask; + const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0; + const Chunk sum = my + carry; + RawBigit(bigit_pos) = sum & kBigitMask; carry = sum >> kBigitSize; - bigit_pos++; + ++bigit_pos; } - used_digits_ = Max(bigit_pos, used_digits_); - ASSERT(IsClamped()); + used_bigits_ = (std::max)(bigit_pos, static_cast(used_bigits_)); + DOUBLE_CONVERSION_ASSERT(IsClamped()); } void Bignum::SubtractBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); + DOUBLE_CONVERSION_ASSERT(IsClamped()); + DOUBLE_CONVERSION_ASSERT(other.IsClamped()); // We require this to be bigger than other. - ASSERT(LessEqual(other, *this)); + DOUBLE_CONVERSION_ASSERT(LessEqual(other, *this)); Align(other); - int offset = other.exponent_ - exponent_; + const int offset = other.exponent_ - exponent_; Chunk borrow = 0; int i; - for (i = 0; i < other.used_digits_; ++i) { - ASSERT((borrow == 0) || (borrow == 1)); - Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; - bigits_[i + offset] = difference & kBigitMask; + for (i = 0; i < other.used_bigits_; ++i) { + DOUBLE_CONVERSION_ASSERT((borrow == 0) || (borrow == 1)); + const Chunk difference = RawBigit(i + offset) - other.RawBigit(i) - borrow; + RawBigit(i + offset) = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); } while (borrow != 0) { - Chunk difference = bigits_[i + offset] - borrow; - bigits_[i + offset] = difference & kBigitMask; + const Chunk difference = RawBigit(i + offset) - borrow; + RawBigit(i + offset) = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); ++i; } @@ -249,91 +249,105 @@ } -void Bignum::ShiftLeft(int shift_amount) { - if (used_digits_ == 0) return; - exponent_ += shift_amount / kBigitSize; - int local_shift = shift_amount % kBigitSize; - EnsureCapacity(used_digits_ + 1); +void Bignum::ShiftLeft(const int shift_amount) { + if (used_bigits_ == 0) { + return; + } + exponent_ += (shift_amount / kBigitSize); + const int local_shift = shift_amount % kBigitSize; + EnsureCapacity(used_bigits_ + 1); BigitsShiftLeft(local_shift); } -void Bignum::MultiplyByUInt32(uint32_t factor) { - if (factor == 1) return; +void Bignum::MultiplyByUInt32(const uint32_t factor) { + if (factor == 1) { + return; + } if (factor == 0) { Zero(); return; } - if (used_digits_ == 0) return; - + if (used_bigits_ == 0) { + return; + } // The product of a bigit with the factor is of size kBigitSize + 32. // Assert that this number + 1 (for the carry) fits into double chunk. - ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); + DOUBLE_CONVERSION_ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); DoubleChunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - DoubleChunk product = static_cast(factor) * bigits_[i] + carry; - bigits_[i] = static_cast(product & kBigitMask); + for (int i = 0; i < used_bigits_; ++i) { + const DoubleChunk product = static_cast(factor) * RawBigit(i) + carry; + RawBigit(i) = static_cast(product & kBigitMask); carry = (product >> kBigitSize); } while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = carry & kBigitMask; - used_digits_++; + EnsureCapacity(used_bigits_ + 1); + RawBigit(used_bigits_) = carry & kBigitMask; + used_bigits_++; carry >>= kBigitSize; } } -void Bignum::MultiplyByUInt64(uint64_t factor) { - if (factor == 1) return; +void Bignum::MultiplyByUInt64(const uint64_t factor) { + if (factor == 1) { + return; + } if (factor == 0) { Zero(); return; } - ASSERT(kBigitSize < 32); + if (used_bigits_ == 0) { + return; + } + DOUBLE_CONVERSION_ASSERT(kBigitSize < 32); uint64_t carry = 0; - uint64_t low = factor & 0xFFFFFFFF; - uint64_t high = factor >> 32; - for (int i = 0; i < used_digits_; ++i) { - uint64_t product_low = low * bigits_[i]; - uint64_t product_high = high * bigits_[i]; - uint64_t tmp = (carry & kBigitMask) + product_low; - bigits_[i] = tmp & kBigitMask; + const uint64_t low = factor & 0xFFFFFFFF; + const uint64_t high = factor >> 32; + for (int i = 0; i < used_bigits_; ++i) { + const uint64_t product_low = low * RawBigit(i); + const uint64_t product_high = high * RawBigit(i); + const uint64_t tmp = (carry & kBigitMask) + product_low; + RawBigit(i) = tmp & kBigitMask; carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + (product_high << (32 - kBigitSize)); } while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = carry & kBigitMask; - used_digits_++; + EnsureCapacity(used_bigits_ + 1); + RawBigit(used_bigits_) = carry & kBigitMask; + used_bigits_++; carry >>= kBigitSize; } } -void Bignum::MultiplyByPowerOfTen(int exponent) { - const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d); - const uint16_t kFive1 = 5; - const uint16_t kFive2 = kFive1 * 5; - const uint16_t kFive3 = kFive2 * 5; - const uint16_t kFive4 = kFive3 * 5; - const uint16_t kFive5 = kFive4 * 5; - const uint16_t kFive6 = kFive5 * 5; - const uint32_t kFive7 = kFive6 * 5; - const uint32_t kFive8 = kFive7 * 5; - const uint32_t kFive9 = kFive8 * 5; - const uint32_t kFive10 = kFive9 * 5; - const uint32_t kFive11 = kFive10 * 5; - const uint32_t kFive12 = kFive11 * 5; - const uint32_t kFive13 = kFive12 * 5; - const uint32_t kFive1_to_12[] = +void Bignum::MultiplyByPowerOfTen(const int exponent) { + static const uint64_t kFive27 = DOUBLE_CONVERSION_UINT64_2PART_C(0x6765c793, fa10079d); + static const uint16_t kFive1 = 5; + static const uint16_t kFive2 = kFive1 * 5; + static const uint16_t kFive3 = kFive2 * 5; + static const uint16_t kFive4 = kFive3 * 5; + static const uint16_t kFive5 = kFive4 * 5; + static const uint16_t kFive6 = kFive5 * 5; + static const uint32_t kFive7 = kFive6 * 5; + static const uint32_t kFive8 = kFive7 * 5; + static const uint32_t kFive9 = kFive8 * 5; + static const uint32_t kFive10 = kFive9 * 5; + static const uint32_t kFive11 = kFive10 * 5; + static const uint32_t kFive12 = kFive11 * 5; + static const uint32_t kFive13 = kFive12 * 5; + static const uint32_t kFive1_to_12[] = { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; - ASSERT(exponent >= 0); - if (exponent == 0) return; - if (used_digits_ == 0) return; + DOUBLE_CONVERSION_ASSERT(exponent >= 0); + if (exponent == 0) { + return; + } + if (used_bigits_ == 0) { + return; + } // We shift by exponent at the end just before returning. int remaining_exponent = exponent; while (remaining_exponent >= 27) { @@ -352,8 +366,8 @@ void Bignum::Square() { - ASSERT(IsClamped()); - int product_length = 2 * used_digits_; + DOUBLE_CONVERSION_ASSERT(IsClamped()); + const int product_length = 2 * used_bigits_; EnsureCapacity(product_length); // Comba multiplication: compute each column separately. @@ -368,64 +382,64 @@ // // Assert that the additional number of bits in a DoubleChunk are enough to // sum up used_digits of Bigit*Bigit. - if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { - UNIMPLEMENTED(); + if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_bigits_) { + DOUBLE_CONVERSION_UNIMPLEMENTED(); } DoubleChunk accumulator = 0; // First shift the digits so we don't overwrite them. - int copy_offset = used_digits_; - for (int i = 0; i < used_digits_; ++i) { - bigits_[copy_offset + i] = bigits_[i]; + const int copy_offset = used_bigits_; + for (int i = 0; i < used_bigits_; ++i) { + RawBigit(copy_offset + i) = RawBigit(i); } // We have two loops to avoid some 'if's in the loop. - for (int i = 0; i < used_digits_; ++i) { + for (int i = 0; i < used_bigits_; ++i) { // Process temporary digit i with power i. // The sum of the two indices must be equal to i. int bigit_index1 = i; int bigit_index2 = 0; // Sum all of the sub-products. while (bigit_index1 >= 0) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; + const Chunk chunk1 = RawBigit(copy_offset + bigit_index1); + const Chunk chunk2 = RawBigit(copy_offset + bigit_index2); accumulator += static_cast(chunk1) * chunk2; bigit_index1--; bigit_index2++; } - bigits_[i] = static_cast(accumulator) & kBigitMask; + RawBigit(i) = static_cast(accumulator) & kBigitMask; accumulator >>= kBigitSize; } - for (int i = used_digits_; i < product_length; ++i) { - int bigit_index1 = used_digits_ - 1; + for (int i = used_bigits_; i < product_length; ++i) { + int bigit_index1 = used_bigits_ - 1; int bigit_index2 = i - bigit_index1; // Invariant: sum of both indices is again equal to i. // Inner loop runs 0 times on last iteration, emptying accumulator. - while (bigit_index2 < used_digits_) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; + while (bigit_index2 < used_bigits_) { + const Chunk chunk1 = RawBigit(copy_offset + bigit_index1); + const Chunk chunk2 = RawBigit(copy_offset + bigit_index2); accumulator += static_cast(chunk1) * chunk2; bigit_index1--; bigit_index2++; } - // The overwritten bigits_[i] will never be read in further loop iterations, + // The overwritten RawBigit(i) will never be read in further loop iterations, // because bigit_index1 and bigit_index2 are always greater - // than i - used_digits_. - bigits_[i] = static_cast(accumulator) & kBigitMask; + // than i - used_bigits_. + RawBigit(i) = static_cast(accumulator) & kBigitMask; accumulator >>= kBigitSize; } // Since the result was guaranteed to lie inside the number the // accumulator must be 0 now. - ASSERT(accumulator == 0); + DOUBLE_CONVERSION_ASSERT(accumulator == 0); // Don't forget to update the used_digits and the exponent. - used_digits_ = product_length; + used_bigits_ = product_length; exponent_ *= 2; Clamp(); } -void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { - ASSERT(base != 0); - ASSERT(power_exponent >= 0); +void Bignum::AssignPowerUInt16(uint16_t base, const int power_exponent) { + DOUBLE_CONVERSION_ASSERT(base != 0); + DOUBLE_CONVERSION_ASSERT(power_exponent >= 0); if (power_exponent == 0) { AssignUInt16(1); return; @@ -445,7 +459,7 @@ tmp_base >>= 1; bit_size++; } - int final_size = bit_size * power_exponent; + const int final_size = bit_size * power_exponent; // 1 extra bigit for the shifting, and one for rounded final_size. EnsureCapacity(final_size / kBigitSize + 2); @@ -466,10 +480,10 @@ // Verify that there is enough space in this_value to perform the // multiplication. The first bit_size bits must be 0. if ((power_exponent & mask) != 0) { - ASSERT(bit_size > 0); - uint64_t base_bits_mask = - ~((static_cast(1) << (64 - bit_size)) - 1); - bool high_bits_zero = (this_value & base_bits_mask) == 0; + DOUBLE_CONVERSION_ASSERT(bit_size > 0); + const uint64_t base_bits_mask = + ~((static_cast(1) << (64 - bit_size)) - 1); + const bool high_bits_zero = (this_value & base_bits_mask) == 0; if (high_bits_zero) { this_value *= base; } else { @@ -499,9 +513,9 @@ // Precondition: this/other < 16bit. uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - ASSERT(other.used_digits_ > 0); + DOUBLE_CONVERSION_ASSERT(IsClamped()); + DOUBLE_CONVERSION_ASSERT(other.IsClamped()); + DOUBLE_CONVERSION_ASSERT(other.used_bigits_ > 0); // Easy case: if we have less digits than the divisor than the result is 0. // Note: this handles the case where this == 0, too. @@ -519,34 +533,34 @@ // This naive approach is extremely inefficient if `this` divided by other // is big. This function is implemented for doubleToString where // the result should be small (less than 10). - ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); - ASSERT(bigits_[used_digits_ - 1] < 0x10000); + DOUBLE_CONVERSION_ASSERT(other.RawBigit(other.used_bigits_ - 1) >= ((1 << kBigitSize) / 16)); + DOUBLE_CONVERSION_ASSERT(RawBigit(used_bigits_ - 1) < 0x10000); // Remove the multiples of the first digit. // Example this = 23 and other equals 9. -> Remove 2 multiples. - result += static_cast(bigits_[used_digits_ - 1]); - SubtractTimes(other, bigits_[used_digits_ - 1]); + result += static_cast(RawBigit(used_bigits_ - 1)); + SubtractTimes(other, RawBigit(used_bigits_ - 1)); } - ASSERT(BigitLength() == other.BigitLength()); + DOUBLE_CONVERSION_ASSERT(BigitLength() == other.BigitLength()); // Both bignums are at the same length now. // Since other has more than 0 digits we know that the access to - // bigits_[used_digits_ - 1] is safe. - Chunk this_bigit = bigits_[used_digits_ - 1]; - Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; + // RawBigit(used_bigits_ - 1) is safe. + const Chunk this_bigit = RawBigit(used_bigits_ - 1); + const Chunk other_bigit = other.RawBigit(other.used_bigits_ - 1); - if (other.used_digits_ == 1) { + if (other.used_bigits_ == 1) { // Shortcut for easy (and common) case. int quotient = this_bigit / other_bigit; - bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; - ASSERT(quotient < 0x10000); + RawBigit(used_bigits_ - 1) = this_bigit - other_bigit * quotient; + DOUBLE_CONVERSION_ASSERT(quotient < 0x10000); result += static_cast(quotient); Clamp(); return result; } - int division_estimate = this_bigit / (other_bigit + 1); - ASSERT(division_estimate < 0x10000); + const int division_estimate = this_bigit / (other_bigit + 1); + DOUBLE_CONVERSION_ASSERT(division_estimate < 0x10000); result += static_cast(division_estimate); SubtractTimes(other, division_estimate); @@ -566,7 +580,7 @@ template static int SizeInHexChars(S number) { - ASSERT(number > 0); + DOUBLE_CONVERSION_ASSERT(number > 0); int result = 0; while (number != 0) { number >>= 4; @@ -576,29 +590,35 @@ } -static char HexCharOfValue(int value) { - ASSERT(0 <= value && value <= 16); - if (value < 10) return static_cast(value + '0'); +static char HexCharOfValue(const int value) { + DOUBLE_CONVERSION_ASSERT(0 <= value && value <= 16); + if (value < 10) { + return static_cast(value + '0'); + } return static_cast(value - 10 + 'A'); } -bool Bignum::ToHexString(char* buffer, int buffer_size) const { - ASSERT(IsClamped()); +bool Bignum::ToHexString(char* buffer, const int buffer_size) const { + DOUBLE_CONVERSION_ASSERT(IsClamped()); // Each bigit must be printable as separate hex-character. - ASSERT(kBigitSize % 4 == 0); - const int kHexCharsPerBigit = kBigitSize / 4; + DOUBLE_CONVERSION_ASSERT(kBigitSize % 4 == 0); + static const int kHexCharsPerBigit = kBigitSize / 4; - if (used_digits_ == 0) { - if (buffer_size < 2) return false; + if (used_bigits_ == 0) { + if (buffer_size < 2) { + return false; + } buffer[0] = '0'; buffer[1] = '\0'; return true; } // We add 1 for the terminating '\0' character. - int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + - SizeInHexChars(bigits_[used_digits_ - 1]) + 1; - if (needed_chars > buffer_size) return false; + const int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + + SizeInHexChars(RawBigit(used_bigits_ - 1)) + 1; + if (needed_chars > buffer_size) { + return false; + } int string_index = needed_chars - 1; buffer[string_index--] = '\0'; for (int i = 0; i < exponent_; ++i) { @@ -606,15 +626,15 @@ buffer[string_index--] = '0'; } } - for (int i = 0; i < used_digits_ - 1; ++i) { - Chunk current_bigit = bigits_[i]; + for (int i = 0; i < used_bigits_ - 1; ++i) { + Chunk current_bigit = RawBigit(i); for (int j = 0; j < kHexCharsPerBigit; ++j) { buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); current_bigit >>= 4; } } // And finally the last bigit. - Chunk most_significant_bigit = bigits_[used_digits_ - 1]; + Chunk most_significant_bigit = RawBigit(used_bigits_ - 1); while (most_significant_bigit != 0) { buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); most_significant_bigit >>= 4; @@ -623,25 +643,37 @@ } -Bignum::Chunk Bignum::BigitAt(int index) const { - if (index >= BigitLength()) return 0; - if (index < exponent_) return 0; - return bigits_[index - exponent_]; +Bignum::Chunk Bignum::BigitOrZero(const int index) const { + if (index >= BigitLength()) { + return 0; + } + if (index < exponent_) { + return 0; + } + return RawBigit(index - exponent_); } int Bignum::Compare(const Bignum& a, const Bignum& b) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - int bigit_length_a = a.BigitLength(); - int bigit_length_b = b.BigitLength(); - if (bigit_length_a < bigit_length_b) return -1; - if (bigit_length_a > bigit_length_b) return +1; - for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { - Chunk bigit_a = a.BigitAt(i); - Chunk bigit_b = b.BigitAt(i); - if (bigit_a < bigit_b) return -1; - if (bigit_a > bigit_b) return +1; + DOUBLE_CONVERSION_ASSERT(a.IsClamped()); + DOUBLE_CONVERSION_ASSERT(b.IsClamped()); + const int bigit_length_a = a.BigitLength(); + const int bigit_length_b = b.BigitLength(); + if (bigit_length_a < bigit_length_b) { + return -1; + } + if (bigit_length_a > bigit_length_b) { + return +1; + } + for (int i = bigit_length_a - 1; i >= (std::min)(a.exponent_, b.exponent_); --i) { + const Chunk bigit_a = a.BigitOrZero(i); + const Chunk bigit_b = b.BigitOrZero(i); + if (bigit_a < bigit_b) { + return -1; + } + if (bigit_a > bigit_b) { + return +1; + } // Otherwise they are equal up to this digit. Try the next digit. } return 0; @@ -649,14 +681,18 @@ int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - ASSERT(c.IsClamped()); + DOUBLE_CONVERSION_ASSERT(a.IsClamped()); + DOUBLE_CONVERSION_ASSERT(b.IsClamped()); + DOUBLE_CONVERSION_ASSERT(c.IsClamped()); if (a.BigitLength() < b.BigitLength()) { return PlusCompare(b, a, c); } - if (a.BigitLength() + 1 < c.BigitLength()) return -1; - if (a.BigitLength() > c.BigitLength()) return +1; + if (a.BigitLength() + 1 < c.BigitLength()) { + return -1; + } + if (a.BigitLength() > c.BigitLength()) { + return +1; + } // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one // of 'a'. @@ -666,92 +702,83 @@ Chunk borrow = 0; // Starting at min_exponent all digits are == 0. So no need to compare them. - int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); + const int min_exponent = (std::min)((std::min)(a.exponent_, b.exponent_), c.exponent_); for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { - Chunk chunk_a = a.BigitAt(i); - Chunk chunk_b = b.BigitAt(i); - Chunk chunk_c = c.BigitAt(i); - Chunk sum = chunk_a + chunk_b; + const Chunk chunk_a = a.BigitOrZero(i); + const Chunk chunk_b = b.BigitOrZero(i); + const Chunk chunk_c = c.BigitOrZero(i); + const Chunk sum = chunk_a + chunk_b; if (sum > chunk_c + borrow) { return +1; } else { borrow = chunk_c + borrow - sum; - if (borrow > 1) return -1; + if (borrow > 1) { + return -1; + } borrow <<= kBigitSize; } } - if (borrow == 0) return 0; + if (borrow == 0) { + return 0; + } return -1; } void Bignum::Clamp() { - while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { - used_digits_--; + while (used_bigits_ > 0 && RawBigit(used_bigits_ - 1) == 0) { + used_bigits_--; } - if (used_digits_ == 0) { + if (used_bigits_ == 0) { // Zero. exponent_ = 0; } } -bool Bignum::IsClamped() const { - return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; -} - - -void Bignum::Zero() { - for (int i = 0; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = 0; - exponent_ = 0; -} - - void Bignum::Align(const Bignum& other) { if (exponent_ > other.exponent_) { - // If "X" represents a "hidden" digit (by the exponent) then we are in the + // If "X" represents a "hidden" bigit (by the exponent) then we are in the // following case (a == this, b == other): // a: aaaaaaXXXX or a: aaaaaXXX // b: bbbbbbX b: bbbbbbbbXX // We replace some of the hidden digits (X) of a with 0 digits. // a: aaaaaa000X or a: aaaaa0XX - int zero_digits = exponent_ - other.exponent_; - EnsureCapacity(used_digits_ + zero_digits); - for (int i = used_digits_ - 1; i >= 0; --i) { - bigits_[i + zero_digits] = bigits_[i]; + const int zero_bigits = exponent_ - other.exponent_; + EnsureCapacity(used_bigits_ + zero_bigits); + for (int i = used_bigits_ - 1; i >= 0; --i) { + RawBigit(i + zero_bigits) = RawBigit(i); } - for (int i = 0; i < zero_digits; ++i) { - bigits_[i] = 0; + for (int i = 0; i < zero_bigits; ++i) { + RawBigit(i) = 0; } - used_digits_ += zero_digits; - exponent_ -= zero_digits; - ASSERT(used_digits_ >= 0); - ASSERT(exponent_ >= 0); + used_bigits_ += zero_bigits; + exponent_ -= zero_bigits; + + DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0); + DOUBLE_CONVERSION_ASSERT(exponent_ >= 0); } } -void Bignum::BigitsShiftLeft(int shift_amount) { - ASSERT(shift_amount < kBigitSize); - ASSERT(shift_amount >= 0); +void Bignum::BigitsShiftLeft(const int shift_amount) { + DOUBLE_CONVERSION_ASSERT(shift_amount < kBigitSize); + DOUBLE_CONVERSION_ASSERT(shift_amount >= 0); Chunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); - bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; + for (int i = 0; i < used_bigits_; ++i) { + const Chunk new_carry = RawBigit(i) >> (kBigitSize - shift_amount); + RawBigit(i) = ((RawBigit(i) << shift_amount) + carry) & kBigitMask; carry = new_carry; } if (carry != 0) { - bigits_[used_digits_] = carry; - used_digits_++; + RawBigit(used_bigits_) = carry; + used_bigits_++; } } -void Bignum::SubtractTimes(const Bignum& other, int factor) { - ASSERT(exponent_ <= other.exponent_); +void Bignum::SubtractTimes(const Bignum& other, const int factor) { + DOUBLE_CONVERSION_ASSERT(exponent_ <= other.exponent_); if (factor < 3) { for (int i = 0; i < factor; ++i) { SubtractBignum(other); @@ -759,19 +786,21 @@ return; } Chunk borrow = 0; - int exponent_diff = other.exponent_ - exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - DoubleChunk product = static_cast(factor) * other.bigits_[i]; - DoubleChunk remove = borrow + product; - Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask); - bigits_[i + exponent_diff] = difference & kBigitMask; + const int exponent_diff = other.exponent_ - exponent_; + for (int i = 0; i < other.used_bigits_; ++i) { + const DoubleChunk product = static_cast(factor) * other.RawBigit(i); + const DoubleChunk remove = borrow + product; + const Chunk difference = RawBigit(i + exponent_diff) - (remove & kBigitMask); + RawBigit(i + exponent_diff) = difference & kBigitMask; borrow = static_cast((difference >> (kChunkSize - 1)) + (remove >> kBigitSize)); } - for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { - if (borrow == 0) return; - Chunk difference = bigits_[i] - borrow; - bigits_[i] = difference & kBigitMask; + for (int i = other.used_bigits_ + exponent_diff; i < used_bigits_; ++i) { + if (borrow == 0) { + return; + } + const Chunk difference = RawBigit(i) - borrow; + RawBigit(i) = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); } Clamp(); diff -Nru icu-64.2/source/i18n/double-conversion-bignum-dtoa.cpp icu-65.1/source/i18n/double-conversion-bignum-dtoa.cpp --- icu-64.2/source/i18n/double-conversion-bignum-dtoa.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-bignum-dtoa.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -49,7 +49,7 @@ namespace double_conversion { static int NormalizedExponent(uint64_t significand, int exponent) { - ASSERT(significand != 0); + DOUBLE_CONVERSION_ASSERT(significand != 0); while ((significand & Double::kHiddenBit) == 0) { significand = significand << 1; exponent = exponent - 1; @@ -90,26 +90,26 @@ // Generates 'requested_digits' after the decimal point. static void BignumToFixed(int requested_digits, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector(buffer), int* length); + Vector buffer, int* length); // Generates 'count' digits of numerator/denominator. // Once 'count' digits have been produced rounds the result depending on the // remainder (remainders of exactly .5 round upwards). Might update the // decimal_point when rounding up (for example for 0.9999). static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector(buffer), int* length); + Vector buffer, int* length); void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, Vector buffer, int* length, int* decimal_point) { - ASSERT(v > 0); - ASSERT(!Double(v).IsSpecial()); + DOUBLE_CONVERSION_ASSERT(v > 0); + DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial()); uint64_t significand; int exponent; bool lower_boundary_is_closer; if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) { float f = static_cast(v); - ASSERT(f == v); + DOUBLE_CONVERSION_ASSERT(f == v); significand = Single(f).Significand(); exponent = Single(f).Exponent(); lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser(); @@ -148,7 +148,7 @@ // 4e-324. In this case the denominator needs fewer than 324*4 binary digits. // The maximum double is 1.7976931348623157e308 which needs fewer than // 308*4 binary digits. - ASSERT(Bignum::kMaxSignificantBits >= 324*4); + DOUBLE_CONVERSION_ASSERT(Bignum::kMaxSignificantBits >= 324*4); InitialScaledStartValues(significand, exponent, lower_boundary_is_closer, estimated_power, need_boundary_deltas, &numerator, &denominator, @@ -177,7 +177,7 @@ buffer, length); break; default: - UNREACHABLE(); + DOUBLE_CONVERSION_UNREACHABLE(); } buffer[*length] = '\0'; } @@ -209,7 +209,7 @@ for (;;) { uint16_t digit; digit = numerator->DivideModuloIntBignum(*denominator); - ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. + DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator. buffer[(*length)++] = static_cast(digit + '0'); @@ -255,7 +255,7 @@ // loop would have stopped earlier. // We still have an assert here in case the preconditions were not // satisfied. - ASSERT(buffer[(*length) - 1] != '9'); + DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9'); buffer[(*length) - 1]++; } else { // Halfway case. @@ -266,7 +266,7 @@ if ((buffer[(*length) - 1] - '0') % 2 == 0) { // Round down => Do nothing. } else { - ASSERT(buffer[(*length) - 1] != '9'); + DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9'); buffer[(*length) - 1]++; } } @@ -278,9 +278,9 @@ // Round up. // Note again that the last digit could not be '9' since this would have // stopped the loop earlier. - // We still have an ASSERT here, in case the preconditions were not + // We still have an DOUBLE_CONVERSION_ASSERT here, in case the preconditions were not // satisfied. - ASSERT(buffer[(*length) -1] != '9'); + DOUBLE_CONVERSION_ASSERT(buffer[(*length) -1] != '9'); buffer[(*length) - 1]++; return; } @@ -297,11 +297,11 @@ static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator, Vector buffer, int* length) { - ASSERT(count >= 0); + DOUBLE_CONVERSION_ASSERT(count >= 0); for (int i = 0; i < count - 1; ++i) { uint16_t digit; digit = numerator->DivideModuloIntBignum(*denominator); - ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. + DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator. buffer[i] = static_cast(digit + '0'); @@ -314,7 +314,7 @@ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { digit++; } - ASSERT(digit <= 10); + DOUBLE_CONVERSION_ASSERT(digit <= 10); buffer[count - 1] = static_cast(digit + '0'); // Correct bad digits (in case we had a sequence of '9's). Propagate the // carry until we hat a non-'9' or til we reach the first digit. @@ -339,7 +339,7 @@ // Input verifies: 1 <= (numerator + delta) / denominator < 10. static void BignumToFixed(int requested_digits, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector(buffer), int* length) { + Vector buffer, int* length) { // Note that we have to look at more than just the requested_digits, since // a number could be rounded up. Example: v=0.5 with requested_digits=0. // Even though the power of v equals 0 we can't just stop here. @@ -355,7 +355,7 @@ } else if (-(*decimal_point) == requested_digits) { // We only need to verify if the number rounds down or up. // Ex: 0.04 and 0.06 with requested_digits == 1. - ASSERT(*decimal_point == -requested_digits); + DOUBLE_CONVERSION_ASSERT(*decimal_point == -requested_digits); // Initially the fraction lies in range (1, 10]. Multiply the denominator // by 10 so that we can compare more easily. denominator->Times10(); @@ -434,7 +434,7 @@ Bignum* numerator, Bignum* denominator, Bignum* delta_minus, Bignum* delta_plus) { // A positive exponent implies a positive power. - ASSERT(estimated_power >= 0); + DOUBLE_CONVERSION_ASSERT(estimated_power >= 0); // Since the estimated_power is positive we simply multiply the denominator // by 10^estimated_power. @@ -520,7 +520,7 @@ // numerator = v * 10^-estimated_power * 2 * 2^-exponent. // Remember: numerator has been abused as power_ten. So no need to assign it // to itself. - ASSERT(numerator == power_ten); + DOUBLE_CONVERSION_ASSERT(numerator == power_ten); numerator->MultiplyByUInt64(significand); // denominator = 2 * 2^-exponent with exponent < 0. diff -Nru icu-64.2/source/i18n/double-conversion-bignum.h icu-65.1/source/i18n/double-conversion-bignum.h --- icu-64.2/source/i18n/double-conversion-bignum.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-bignum.h 2019-10-03 11:16:41.000000000 +0000 @@ -53,26 +53,27 @@ // exponent. static const int kMaxSignificantBits = 3584; - Bignum(); - void AssignUInt16(uint16_t value); + Bignum() : used_bigits_(0), exponent_(0) {} + + void AssignUInt16(const uint16_t value); void AssignUInt64(uint64_t value); void AssignBignum(const Bignum& other); - void AssignDecimalString(Vector value); - void AssignHexString(Vector value); + void AssignDecimalString(const Vector value); + void AssignHexString(const Vector value); - void AssignPowerUInt16(uint16_t base, int exponent); + void AssignPowerUInt16(uint16_t base, const int exponent); - void AddUInt64(uint64_t operand); + void AddUInt64(const uint64_t operand); void AddBignum(const Bignum& other); // Precondition: this >= other. void SubtractBignum(const Bignum& other); void Square(); - void ShiftLeft(int shift_amount); - void MultiplyByUInt32(uint32_t factor); - void MultiplyByUInt64(uint64_t factor); - void MultiplyByPowerOfTen(int exponent); + void ShiftLeft(const int shift_amount); + void MultiplyByUInt32(const uint32_t factor); + void MultiplyByUInt64(const uint64_t factor); + void MultiplyByPowerOfTen(const int exponent); void Times10() { return MultiplyByUInt32(10); } // Pseudocode: // int result = this / other; @@ -80,7 +81,7 @@ // In the worst case this function is in O(this/other). uint16_t DivideModuloIntBignum(const Bignum& other); - bool ToHexString(char* buffer, int buffer_size) const; + bool ToHexString(char* buffer, const int buffer_size) const; // Returns // -1 if a < b, @@ -124,33 +125,40 @@ // grow. There are no checks if the stack-allocated space is sufficient. static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; - void EnsureCapacity(int size) { + static void EnsureCapacity(const int size) { if (size > kBigitCapacity) { - UNREACHABLE(); + DOUBLE_CONVERSION_UNREACHABLE(); } } void Align(const Bignum& other); void Clamp(); - bool IsClamped() const; - void Zero(); + bool IsClamped() const { + return used_bigits_ == 0 || RawBigit(used_bigits_ - 1) != 0; + } + void Zero() { + used_bigits_ = 0; + exponent_ = 0; + } // Requires this to have enough capacity (no tests done). - // Updates used_digits_ if necessary. + // Updates used_bigits_ if necessary. // shift_amount must be < kBigitSize. - void BigitsShiftLeft(int shift_amount); - // BigitLength includes the "hidden" digits encoded in the exponent. - int BigitLength() const { return used_digits_ + exponent_; } - Chunk BigitAt(int index) const; - void SubtractTimes(const Bignum& other, int factor); - + void BigitsShiftLeft(const int shift_amount); + // BigitLength includes the "hidden" bigits encoded in the exponent. + int BigitLength() const { return used_bigits_ + exponent_; } + Chunk& RawBigit(const int index); + const Chunk& RawBigit(const int index) const; + Chunk BigitOrZero(const int index) const; + void SubtractTimes(const Bignum& other, const int factor); + + // The Bignum's value is value(bigits_buffer_) * 2^(exponent_ * kBigitSize), + // where the value of the buffer consists of the lower kBigitSize bits of + // the first used_bigits_ Chunks in bigits_buffer_, first chunk has lowest + // significant bits. + int16_t used_bigits_; + int16_t exponent_; Chunk bigits_buffer_[kBigitCapacity]; - // A vector backed by bigits_buffer_. This way accesses to the array are - // checked for out-of-bounds errors. - Vector bigits_; - int used_digits_; - // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). - int exponent_; - DC_DISALLOW_COPY_AND_ASSIGN(Bignum); + DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Bignum); }; } // namespace double_conversion diff -Nru icu-64.2/source/i18n/double-conversion-cached-powers.cpp icu-65.1/source/i18n/double-conversion-cached-powers.cpp --- icu-64.2/source/i18n/double-conversion-cached-powers.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-cached-powers.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -49,6 +49,8 @@ namespace double_conversion { +namespace PowersOfTenCache { + struct CachedPower { uint64_t significand; int16_t binary_exponent; @@ -56,103 +58,99 @@ }; static const CachedPower kCachedPowers[] = { - {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, - {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, - {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, - {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, - {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, - {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, - {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, - {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, - {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, - {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, - {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, - {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, - {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, - {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, - {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, - {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, - {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, - {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, - {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, - {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, - {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, - {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, - {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, - {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, - {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, - {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, - {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, - {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, - {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, - {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, - {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, - {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, - {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, - {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, - {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, - {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, - {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, - {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, - {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, - {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, - {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, - {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, - {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, - {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, - {UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, - {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, - {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, - {UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, - {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, - {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, - {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, - {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, - {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, - {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, - {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, - {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, - {UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, - {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, - {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, - {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, - {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, - {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, - {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, - {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, - {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, - {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, - {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, - {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, - {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, - {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, - {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, - {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, - {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, - {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, - {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, - {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, - {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, - {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, - {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, - {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, - {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, - {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, - {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, - {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, - {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, - {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, - {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, + {DOUBLE_CONVERSION_UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, }; static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent. static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10) -// Difference between the decimal exponents in the table above. -const int PowersOfTenCache::kDecimalExponentDistance = 8; -const int PowersOfTenCache::kMinDecimalExponent = -348; -const int PowersOfTenCache::kMaxDecimalExponent = 340; -void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( +void GetCachedPowerForBinaryExponentRange( int min_exponent, int max_exponent, DiyFp* power, @@ -162,30 +160,32 @@ int foo = kCachedPowersOffset; int index = (foo + static_cast(k) - 1) / kDecimalExponentDistance + 1; - ASSERT(0 <= index && index < static_cast(ARRAY_SIZE(kCachedPowers))); + DOUBLE_CONVERSION_ASSERT(0 <= index && index < static_cast(DOUBLE_CONVERSION_ARRAY_SIZE(kCachedPowers))); CachedPower cached_power = kCachedPowers[index]; - ASSERT(min_exponent <= cached_power.binary_exponent); + DOUBLE_CONVERSION_ASSERT(min_exponent <= cached_power.binary_exponent); (void) max_exponent; // Mark variable as used. - ASSERT(cached_power.binary_exponent <= max_exponent); + DOUBLE_CONVERSION_ASSERT(cached_power.binary_exponent <= max_exponent); *decimal_exponent = cached_power.decimal_exponent; *power = DiyFp(cached_power.significand, cached_power.binary_exponent); } -void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent, - DiyFp* power, - int* found_exponent) { - ASSERT(kMinDecimalExponent <= requested_exponent); - ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); +void GetCachedPowerForDecimalExponent(int requested_exponent, + DiyFp* power, + int* found_exponent) { + DOUBLE_CONVERSION_ASSERT(kMinDecimalExponent <= requested_exponent); + DOUBLE_CONVERSION_ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); int index = (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance; CachedPower cached_power = kCachedPowers[index]; *power = DiyFp(cached_power.significand, cached_power.binary_exponent); *found_exponent = cached_power.decimal_exponent; - ASSERT(*found_exponent <= requested_exponent); - ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance); + DOUBLE_CONVERSION_ASSERT(*found_exponent <= requested_exponent); + DOUBLE_CONVERSION_ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance); } +} // namespace PowersOfTenCache + } // namespace double_conversion // ICU PATCH: Close ICU namespace diff -Nru icu-64.2/source/i18n/double-conversion-cached-powers.h icu-65.1/source/i18n/double-conversion-cached-powers.h --- icu-64.2/source/i18n/double-conversion-cached-powers.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-cached-powers.h 2019-10-03 11:16:41.000000000 +0000 @@ -46,32 +46,32 @@ namespace double_conversion { -class PowersOfTenCache { - public: +namespace PowersOfTenCache { // Not all powers of ten are cached. The decimal exponent of two neighboring // cached numbers will differ by kDecimalExponentDistance. - static const int kDecimalExponentDistance; + static const int kDecimalExponentDistance = 8; - static const int kMinDecimalExponent; - static const int kMaxDecimalExponent; + static const int kMinDecimalExponent = -348; + static const int kMaxDecimalExponent = 340; // Returns a cached power-of-ten with a binary exponent in the range // [min_exponent; max_exponent] (boundaries included). - static void GetCachedPowerForBinaryExponentRange(int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent); + void GetCachedPowerForBinaryExponentRange(int min_exponent, + int max_exponent, + DiyFp* power, + int* decimal_exponent); // Returns a cached power of ten x ~= 10^k such that // k <= decimal_exponent < k + kCachedPowersDecimalDistance. // The given decimal_exponent must satisfy // kMinDecimalExponent <= requested_exponent, and // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance. - static void GetCachedPowerForDecimalExponent(int requested_exponent, - DiyFp* power, - int* found_exponent); -}; + void GetCachedPowerForDecimalExponent(int requested_exponent, + DiyFp* power, + int* found_exponent); + +} // namespace PowersOfTenCache } // namespace double_conversion diff -Nru icu-64.2/source/i18n/double-conversion.cpp icu-65.1/source/i18n/double-conversion.cpp --- icu-64.2/source/i18n/double-conversion.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1168 +0,0 @@ -// © 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -// -// From the double-conversion library. Original license: -// -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING -#include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING - -// ICU PATCH: Do not include std::locale. - -#include -//#include -#include - -// ICU PATCH: Customize header file paths for ICU. -// The file fixed-dtoa.h is not needed. - -#include "double-conversion.h" - -#include "double-conversion-bignum-dtoa.h" -#include "double-conversion-fast-dtoa.h" -#include "double-conversion-ieee.h" -#include "double-conversion-strtod.h" -#include "double-conversion-utils.h" - -// ICU PATCH: Wrap in ICU namespace -U_NAMESPACE_BEGIN - -namespace double_conversion { - -#if 0 // not needed for ICU -const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() { - int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; - static DoubleToStringConverter converter(flags, - "Infinity", - "NaN", - 'e', - -6, 21, - 6, 0); - return converter; -} - - -bool DoubleToStringConverter::HandleSpecialValues( - double value, - StringBuilder* result_builder) const { - Double double_inspect(value); - if (double_inspect.IsInfinite()) { - if (infinity_symbol_ == NULL) return false; - if (value < 0) { - result_builder->AddCharacter('-'); - } - result_builder->AddString(infinity_symbol_); - return true; - } - if (double_inspect.IsNan()) { - if (nan_symbol_ == NULL) return false; - result_builder->AddString(nan_symbol_); - return true; - } - return false; -} - - -void DoubleToStringConverter::CreateExponentialRepresentation( - const char* decimal_digits, - int length, - int exponent, - StringBuilder* result_builder) const { - ASSERT(length != 0); - result_builder->AddCharacter(decimal_digits[0]); - if (length != 1) { - result_builder->AddCharacter('.'); - result_builder->AddSubstring(&decimal_digits[1], length-1); - } - result_builder->AddCharacter(exponent_character_); - if (exponent < 0) { - result_builder->AddCharacter('-'); - exponent = -exponent; - } else { - if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) { - result_builder->AddCharacter('+'); - } - } - if (exponent == 0) { - result_builder->AddCharacter('0'); - return; - } - ASSERT(exponent < 1e4); - const int kMaxExponentLength = 5; - char buffer[kMaxExponentLength + 1]; - buffer[kMaxExponentLength] = '\0'; - int first_char_pos = kMaxExponentLength; - while (exponent > 0) { - buffer[--first_char_pos] = '0' + (exponent % 10); - exponent /= 10; - } - result_builder->AddSubstring(&buffer[first_char_pos], - kMaxExponentLength - first_char_pos); -} - - -void DoubleToStringConverter::CreateDecimalRepresentation( - const char* decimal_digits, - int length, - int decimal_point, - int digits_after_point, - StringBuilder* result_builder) const { - // Create a representation that is padded with zeros if needed. - if (decimal_point <= 0) { - // "0.00000decimal_rep" or "0.000decimal_rep00". - result_builder->AddCharacter('0'); - if (digits_after_point > 0) { - result_builder->AddCharacter('.'); - result_builder->AddPadding('0', -decimal_point); - ASSERT(length <= digits_after_point - (-decimal_point)); - result_builder->AddSubstring(decimal_digits, length); - int remaining_digits = digits_after_point - (-decimal_point) - length; - result_builder->AddPadding('0', remaining_digits); - } - } else if (decimal_point >= length) { - // "decimal_rep0000.00000" or "decimal_rep.0000". - result_builder->AddSubstring(decimal_digits, length); - result_builder->AddPadding('0', decimal_point - length); - if (digits_after_point > 0) { - result_builder->AddCharacter('.'); - result_builder->AddPadding('0', digits_after_point); - } - } else { - // "decima.l_rep000". - ASSERT(digits_after_point > 0); - result_builder->AddSubstring(decimal_digits, decimal_point); - result_builder->AddCharacter('.'); - ASSERT(length - decimal_point <= digits_after_point); - result_builder->AddSubstring(&decimal_digits[decimal_point], - length - decimal_point); - int remaining_digits = digits_after_point - (length - decimal_point); - result_builder->AddPadding('0', remaining_digits); - } - if (digits_after_point == 0) { - if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { - result_builder->AddCharacter('.'); - } - if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { - result_builder->AddCharacter('0'); - } - } -} - - -bool DoubleToStringConverter::ToShortestIeeeNumber( - double value, - StringBuilder* result_builder, - DoubleToStringConverter::DtoaMode mode) const { - ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE); - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - int decimal_point; - bool sign; - const int kDecimalRepCapacity = kBase10MaximalLength + 1; - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - - DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - - bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - int exponent = decimal_point - 1; - if ((decimal_in_shortest_low_ <= exponent) && - (exponent < decimal_in_shortest_high_)) { - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, - decimal_point, - Max(0, decimal_rep_length - decimal_point), - result_builder); - } else { - CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, - result_builder); - } - return true; -} - - -bool DoubleToStringConverter::ToFixed(double value, - int requested_digits, - StringBuilder* result_builder) const { - ASSERT(kMaxFixedDigitsBeforePoint == 60); - const double kFirstNonFixed = 1e60; - - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - if (requested_digits > kMaxFixedDigitsAfterPoint) return false; - if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; - - // Find a sufficiently precise decimal representation of n. - int decimal_point; - bool sign; - // Add space for the '\0' byte. - const int kDecimalRepCapacity = - kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - DoubleToAscii(value, FIXED, requested_digits, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - - bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, - requested_digits, result_builder); - return true; -} - - -bool DoubleToStringConverter::ToExponential( - double value, - int requested_digits, - StringBuilder* result_builder) const { - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - if (requested_digits < -1) return false; - if (requested_digits > kMaxExponentialDigits) return false; - - int decimal_point; - bool sign; - // Add space for digit before the decimal point and the '\0' character. - const int kDecimalRepCapacity = kMaxExponentialDigits + 2; - ASSERT(kDecimalRepCapacity > kBase10MaximalLength); - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - - if (requested_digits == -1) { - DoubleToAscii(value, SHORTEST, 0, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - } else { - DoubleToAscii(value, PRECISION, requested_digits + 1, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - ASSERT(decimal_rep_length <= requested_digits + 1); - - for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { - decimal_rep[i] = '0'; - } - decimal_rep_length = requested_digits + 1; - } - - bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - int exponent = decimal_point - 1; - CreateExponentialRepresentation(decimal_rep, - decimal_rep_length, - exponent, - result_builder); - return true; -} - - -bool DoubleToStringConverter::ToPrecision(double value, - int precision, - StringBuilder* result_builder) const { - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) { - return false; - } - - // Find a sufficiently precise decimal representation of n. - int decimal_point; - bool sign; - // Add one for the terminating null character. - const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - - DoubleToAscii(value, PRECISION, precision, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - ASSERT(decimal_rep_length <= precision); - - bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - // The exponent if we print the number as x.xxeyyy. That is with the - // decimal point after the first digit. - int exponent = decimal_point - 1; - - int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0; - if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) || - (decimal_point - precision + extra_zero > - max_trailing_padding_zeroes_in_precision_mode_)) { - // Fill buffer to contain 'precision' digits. - // Usually the buffer is already at the correct length, but 'DoubleToAscii' - // is allowed to return less characters. - for (int i = decimal_rep_length; i < precision; ++i) { - decimal_rep[i] = '0'; - } - - CreateExponentialRepresentation(decimal_rep, - precision, - exponent, - result_builder); - } else { - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, - Max(0, precision - decimal_point), - result_builder); - } - return true; -} -#endif // not needed for ICU - - -static BignumDtoaMode DtoaToBignumDtoaMode( - DoubleToStringConverter::DtoaMode dtoa_mode) { - switch (dtoa_mode) { - case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST; - case DoubleToStringConverter::SHORTEST_SINGLE: - return BIGNUM_DTOA_SHORTEST_SINGLE; - case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; - case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; - default: - UNREACHABLE(); - } -} - - -void DoubleToStringConverter::DoubleToAscii(double v, - DtoaMode mode, - int requested_digits, - char* buffer, - int buffer_length, - bool* sign, - int* length, - int* point) { - Vector vector(buffer, buffer_length); - ASSERT(!Double(v).IsSpecial()); - ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0); - - if (Double(v).Sign() < 0) { - *sign = true; - v = -v; - } else { - *sign = false; - } - - if (mode == PRECISION && requested_digits == 0) { - vector[0] = '\0'; - *length = 0; - return; - } - - if (v == 0) { - vector[0] = '0'; - vector[1] = '\0'; - *length = 1; - *point = 1; - return; - } - - bool fast_worked; - switch (mode) { - case SHORTEST: - fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point); - break; -#if 0 // not needed for ICU - case SHORTEST_SINGLE: - fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, - vector, length, point); - break; - case FIXED: - fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point); - break; - case PRECISION: - fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, - vector, length, point); - break; -#endif // not needed for ICU - default: - fast_worked = false; - UNREACHABLE(); - } - if (fast_worked) return; - - // If the fast dtoa didn't succeed use the slower bignum version. - BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode); - BignumDtoa(v, bignum_mode, requested_digits, vector, length, point); - vector[*length] = '\0'; -} - - -namespace { - -inline char ToLower(char ch) { -#if 0 // do not include std::locale in ICU - static const std::ctype& cType = - std::use_facet >(std::locale::classic()); - return cType.tolower(ch); -#else - (void)ch; - UNREACHABLE(); -#endif -} - -inline char Pass(char ch) { - return ch; -} - -template -static inline bool ConsumeSubStringImpl(Iterator* current, - Iterator end, - const char* substring, - Converter converter) { - ASSERT(converter(**current) == *substring); - for (substring++; *substring != '\0'; substring++) { - ++*current; - if (*current == end || converter(**current) != *substring) { - return false; - } - } - ++*current; - return true; -} - -// Consumes the given substring from the iterator. -// Returns false, if the substring does not match. -template -static bool ConsumeSubString(Iterator* current, - Iterator end, - const char* substring, - bool allow_case_insensibility) { - if (allow_case_insensibility) { - return ConsumeSubStringImpl(current, end, substring, ToLower); - } else { - return ConsumeSubStringImpl(current, end, substring, Pass); - } -} - -// Consumes first character of the str is equal to ch -inline bool ConsumeFirstCharacter(char ch, - const char* str, - bool case_insensibility) { - return case_insensibility ? ToLower(ch) == str[0] : ch == str[0]; -} -} // namespace - -// Maximum number of significant digits in decimal representation. -// The longest possible double in decimal representation is -// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 -// (768 digits). If we parse a number whose first digits are equal to a -// mean of 2 adjacent doubles (that could have up to 769 digits) the result -// must be rounded to the bigger one unless the tail consists of zeros, so -// we don't need to preserve all the digits. -const int kMaxSignificantDigits = 772; - - -static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; -static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7); - - -static const uc16 kWhitespaceTable16[] = { - 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195, - 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279 -}; -static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16); - - - -static bool isWhitespace(int x) { - if (x < 128) { - for (int i = 0; i < kWhitespaceTable7Length; i++) { - if (kWhitespaceTable7[i] == x) return true; - } - } else { - for (int i = 0; i < kWhitespaceTable16Length; i++) { - if (kWhitespaceTable16[i] == x) return true; - } - } - return false; -} - - -// Returns true if a nonspace found and false if the end has reached. -template -static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { - while (*current != end) { - if (!isWhitespace(**current)) return true; - ++*current; - } - return false; -} - - -static bool isDigit(int x, int radix) { - return (x >= '0' && x <= '9' && x < '0' + radix) - || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) - || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); -} - - -static double SignedZero(bool sign) { - return sign ? -0.0 : 0.0; -} - - -// Returns true if 'c' is a decimal digit that is valid for the given radix. -// -// The function is small and could be inlined, but VS2012 emitted a warning -// because it constant-propagated the radix and concluded that the last -// condition was always true. By moving it into a separate function the -// compiler wouldn't warn anymore. -#ifdef _MSC_VER -#pragma optimize("",off) -static bool IsDecimalDigitForRadix(int c, int radix) { - return '0' <= c && c <= '9' && (c - '0') < radix; -} -#pragma optimize("",on) -#else -static bool inline IsDecimalDigitForRadix(int c, int radix) { - return '0' <= c && c <= '9' && (c - '0') < radix; -} -#endif -// Returns true if 'c' is a character digit that is valid for the given radix. -// The 'a_character' should be 'a' or 'A'. -// -// The function is small and could be inlined, but VS2012 emitted a warning -// because it constant-propagated the radix and concluded that the first -// condition was always false. By moving it into a separate function the -// compiler wouldn't warn anymore. -static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { - return radix > 10 && c >= a_character && c < a_character + radix - 10; -} - -// Returns true, when the iterator is equal to end. -template -static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) { - if (separator == StringToDoubleConverter::kNoSeparator) { - ++(*it); - return *it == end; - } - if (!isDigit(**it, base)) { - ++(*it); - return *it == end; - } - ++(*it); - if (*it == end) return true; - if (*it + 1 == end) return false; - if (**it == separator && isDigit(*(*it + 1), base)) { - ++(*it); - } - return *it == end; -} - -// Checks whether the string in the range start-end is a hex-float string. -// This function assumes that the leading '0x'/'0X' is already consumed. -// -// Hex float strings are of one of the following forms: -// - hex_digits+ 'p' ('+'|'-')? exponent_digits+ -// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+ -// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+ -template -static bool IsHexFloatString(Iterator start, - Iterator end, - uc16 separator, - bool allow_trailing_junk) { - ASSERT(start != end); - - Iterator current = start; - - bool saw_digit = false; - while (isDigit(*current, 16)) { - saw_digit = true; - if (Advance(¤t, separator, 16, end)) return false; - } - if (*current == '.') { - if (Advance(¤t, separator, 16, end)) return false; - while (isDigit(*current, 16)) { - saw_digit = true; - if (Advance(¤t, separator, 16, end)) return false; - } - if (!saw_digit) return false; // Only the '.', but no digits. - } - if (*current != 'p' && *current != 'P') return false; - if (Advance(¤t, separator, 16, end)) return false; - if (*current == '+' || *current == '-') { - if (Advance(¤t, separator, 16, end)) return false; - } - if (!isDigit(*current, 10)) return false; - if (Advance(¤t, separator, 16, end)) return true; - while (isDigit(*current, 10)) { - if (Advance(¤t, separator, 16, end)) return true; - } - return allow_trailing_junk || !AdvanceToNonspace(¤t, end); -} - - -// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. -// -// If parse_as_hex_float is true, then the string must be a valid -// hex-float. -template -static double RadixStringToIeee(Iterator* current, - Iterator end, - bool sign, - uc16 separator, - bool parse_as_hex_float, - bool allow_trailing_junk, - double junk_string_value, - bool read_as_double, - bool* result_is_junk) { - ASSERT(*current != end); - ASSERT(!parse_as_hex_float || - IsHexFloatString(*current, end, separator, allow_trailing_junk)); - - const int kDoubleSize = Double::kSignificandSize; - const int kSingleSize = Single::kSignificandSize; - const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; - - *result_is_junk = true; - - int64_t number = 0; - int exponent = 0; - const int radix = (1 << radix_log_2); - // Whether we have encountered a '.' and are parsing the decimal digits. - // Only relevant if parse_as_hex_float is true. - bool post_decimal = false; - - // Skip leading 0s. - while (**current == '0') { - if (Advance(current, separator, radix, end)) { - *result_is_junk = false; - return SignedZero(sign); - } - } - - while (true) { - int digit; - if (IsDecimalDigitForRadix(**current, radix)) { - digit = static_cast(**current) - '0'; - if (post_decimal) exponent -= radix_log_2; - } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { - digit = static_cast(**current) - 'a' + 10; - if (post_decimal) exponent -= radix_log_2; - } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { - digit = static_cast(**current) - 'A' + 10; - if (post_decimal) exponent -= radix_log_2; - } else if (parse_as_hex_float && **current == '.') { - post_decimal = true; - Advance(current, separator, radix, end); - ASSERT(*current != end); - continue; - } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { - break; - } else { - if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { - break; - } else { - return junk_string_value; - } - } - - number = number * radix + digit; - int overflow = static_cast(number >> kSignificandSize); - if (overflow != 0) { - // Overflow occurred. Need to determine which direction to round the - // result. - int overflow_bits_count = 1; - while (overflow > 1) { - overflow_bits_count++; - overflow >>= 1; - } - - int dropped_bits_mask = ((1 << overflow_bits_count) - 1); - int dropped_bits = static_cast(number) & dropped_bits_mask; - number >>= overflow_bits_count; - exponent += overflow_bits_count; - - bool zero_tail = true; - for (;;) { - if (Advance(current, separator, radix, end)) break; - if (parse_as_hex_float && **current == '.') { - // Just run over the '.'. We are just trying to see whether there is - // a non-zero digit somewhere. - Advance(current, separator, radix, end); - ASSERT(*current != end); - post_decimal = true; - } - if (!isDigit(**current, radix)) break; - zero_tail = zero_tail && **current == '0'; - if (!post_decimal) exponent += radix_log_2; - } - - if (!parse_as_hex_float && - !allow_trailing_junk && - AdvanceToNonspace(current, end)) { - return junk_string_value; - } - - int middle_value = (1 << (overflow_bits_count - 1)); - if (dropped_bits > middle_value) { - number++; // Rounding up. - } else if (dropped_bits == middle_value) { - // Rounding to even to consistency with decimals: half-way case rounds - // up if significant part is odd and down otherwise. - if ((number & 1) != 0 || !zero_tail) { - number++; // Rounding up. - } - } - - // Rounding up may cause overflow. - if ((number & ((int64_t)1 << kSignificandSize)) != 0) { - exponent++; - number >>= 1; - } - break; - } - if (Advance(current, separator, radix, end)) break; - } - - ASSERT(number < ((int64_t)1 << kSignificandSize)); - ASSERT(static_cast(static_cast(number)) == number); - - *result_is_junk = false; - - if (parse_as_hex_float) { - ASSERT(**current == 'p' || **current == 'P'); - Advance(current, separator, radix, end); - ASSERT(*current != end); - bool is_negative = false; - if (**current == '+') { - Advance(current, separator, radix, end); - ASSERT(*current != end); - } else if (**current == '-') { - is_negative = true; - Advance(current, separator, radix, end); - ASSERT(*current != end); - } - int written_exponent = 0; - while (IsDecimalDigitForRadix(**current, 10)) { - written_exponent = 10 * written_exponent + **current - '0'; - if (Advance(current, separator, radix, end)) break; - } - if (is_negative) written_exponent = -written_exponent; - exponent += written_exponent; - } - - if (exponent == 0 || number == 0) { - if (sign) { - if (number == 0) return -0.0; - number = -number; - } - return static_cast(number); - } - - ASSERT(number != 0); - double result = Double(DiyFp(number, exponent)).value(); - return sign ? -result : result; -} - -template -double StringToDoubleConverter::StringToIeee( - Iterator input, - int length, - bool read_as_double, - int* processed_characters_count) const { - Iterator current = input; - Iterator end = input + length; - - *processed_characters_count = 0; - - const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; - const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; - const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; - const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; - const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0; - - // To make sure that iterator dereferencing is valid the following - // convention is used: - // 1. Each '++current' statement is followed by check for equality to 'end'. - // 2. If AdvanceToNonspace returned false then current == end. - // 3. If 'current' becomes equal to 'end' the function returns or goes to - // 'parsing_done'. - // 4. 'current' is not dereferenced after the 'parsing_done' label. - // 5. Code before 'parsing_done' may rely on 'current != end'. - if (current == end) return empty_string_value_; - - if (allow_leading_spaces || allow_trailing_spaces) { - if (!AdvanceToNonspace(¤t, end)) { - *processed_characters_count = static_cast(current - input); - return empty_string_value_; - } - if (!allow_leading_spaces && (input != current)) { - // No leading spaces allowed, but AdvanceToNonspace moved forward. - return junk_string_value_; - } - } - - // The longest form of simplified number is: "-.1eXXX\0". - const int kBufferSize = kMaxSignificantDigits + 10; - char buffer[kBufferSize]; // NOLINT: size is known at compile time. - int buffer_pos = 0; - - // Exponent will be adjusted if insignificant digits of the integer part - // or insignificant leading zeros of the fractional part are dropped. - int exponent = 0; - int significant_digits = 0; - int insignificant_digits = 0; - bool nonzero_digit_dropped = false; - - bool sign = false; - - if (*current == '+' || *current == '-') { - sign = (*current == '-'); - ++current; - Iterator next_non_space = current; - // Skip following spaces (if allowed). - if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; - if (!allow_spaces_after_sign && (current != next_non_space)) { - return junk_string_value_; - } - current = next_non_space; - } - - if (infinity_symbol_ != NULL) { - if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) { - if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensibility)) { - return junk_string_value_; - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - - ASSERT(buffer_pos == 0); - *processed_characters_count = static_cast(current - input); - return sign ? -Double::Infinity() : Double::Infinity(); - } - } - - if (nan_symbol_ != NULL) { - if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) { - if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensibility)) { - return junk_string_value_; - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - - ASSERT(buffer_pos == 0); - *processed_characters_count = static_cast(current - input); - return sign ? -Double::NaN() : Double::NaN(); - } - } - - bool leading_zero = false; - if (*current == '0') { - if (Advance(¤t, separator_, 10, end)) { - *processed_characters_count = static_cast(current - input); - return SignedZero(sign); - } - - leading_zero = true; - - // It could be hexadecimal value. - if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) && - (*current == 'x' || *current == 'X')) { - ++current; - - bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) && - IsHexFloatString(current, end, separator_, allow_trailing_junk); - - if (current == end) return junk_string_value_; // "0x" - if (!parse_as_hex_float && !isDigit(*current, 16)) { - return junk_string_value_; - } - - bool result_is_junk; - double result = RadixStringToIeee<4>(¤t, - end, - sign, - separator_, - parse_as_hex_float, - allow_trailing_junk, - junk_string_value_, - read_as_double, - &result_is_junk); - if (!result_is_junk) { - if (allow_trailing_spaces) AdvanceToNonspace(¤t, end); - *processed_characters_count = static_cast(current - input); - } - return result; - } - - // Ignore leading zeros in the integer part. - while (*current == '0') { - if (Advance(¤t, separator_, 10, end)) { - *processed_characters_count = static_cast(current - input); - return SignedZero(sign); - } - } - } - - bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; - - // Copy significant digits of the integer part (if any) to the buffer. - while (*current >= '0' && *current <= '9') { - if (significant_digits < kMaxSignificantDigits) { - ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos++] = static_cast(*current); - significant_digits++; - // Will later check if it's an octal in the buffer. - } else { - insignificant_digits++; // Move the digit into the exponential part. - nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; - } - octal = octal && *current < '8'; - if (Advance(¤t, separator_, 10, end)) goto parsing_done; - } - - if (significant_digits == 0) { - octal = false; - } - - if (*current == '.') { - if (octal && !allow_trailing_junk) return junk_string_value_; - if (octal) goto parsing_done; - - if (Advance(¤t, separator_, 10, end)) { - if (significant_digits == 0 && !leading_zero) { - return junk_string_value_; - } else { - goto parsing_done; - } - } - - if (significant_digits == 0) { - // octal = false; - // Integer part consists of 0 or is absent. Significant digits start after - // leading zeros (if any). - while (*current == '0') { - if (Advance(¤t, separator_, 10, end)) { - *processed_characters_count = static_cast(current - input); - return SignedZero(sign); - } - exponent--; // Move this 0 into the exponent. - } - } - - // There is a fractional part. - // We don't emit a '.', but adjust the exponent instead. - while (*current >= '0' && *current <= '9') { - if (significant_digits < kMaxSignificantDigits) { - ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos++] = static_cast(*current); - significant_digits++; - exponent--; - } else { - // Ignore insignificant digits in the fractional part. - nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; - } - if (Advance(¤t, separator_, 10, end)) goto parsing_done; - } - } - - if (!leading_zero && exponent == 0 && significant_digits == 0) { - // If leading_zeros is true then the string contains zeros. - // If exponent < 0 then string was [+-]\.0*... - // If significant_digits != 0 the string is not equal to 0. - // Otherwise there are no digits in the string. - return junk_string_value_; - } - - // Parse exponential part. - if (*current == 'e' || *current == 'E') { - if (octal && !allow_trailing_junk) return junk_string_value_; - if (octal) goto parsing_done; - Iterator junk_begin = current; - ++current; - if (current == end) { - if (allow_trailing_junk) { - current = junk_begin; - goto parsing_done; - } else { - return junk_string_value_; - } - } - char exponen_sign = '+'; - if (*current == '+' || *current == '-') { - exponen_sign = static_cast(*current); - ++current; - if (current == end) { - if (allow_trailing_junk) { - current = junk_begin; - goto parsing_done; - } else { - return junk_string_value_; - } - } - } - - if (current == end || *current < '0' || *current > '9') { - if (allow_trailing_junk) { - current = junk_begin; - goto parsing_done; - } else { - return junk_string_value_; - } - } - - const int max_exponent = INT_MAX / 2; - ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); - int num = 0; - do { - // Check overflow. - int digit = *current - '0'; - if (num >= max_exponent / 10 - && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { - num = max_exponent; - } else { - num = num * 10 + digit; - } - ++current; - } while (current != end && *current >= '0' && *current <= '9'); - - exponent += (exponen_sign == '-' ? -num : num); - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - if (allow_trailing_spaces) { - AdvanceToNonspace(¤t, end); - } - - parsing_done: - exponent += insignificant_digits; - - if (octal) { - double result; - bool result_is_junk; - char* start = buffer; - result = RadixStringToIeee<3>(&start, - buffer + buffer_pos, - sign, - separator_, - false, // Don't parse as hex_float. - allow_trailing_junk, - junk_string_value_, - read_as_double, - &result_is_junk); - ASSERT(!result_is_junk); - *processed_characters_count = static_cast(current - input); - return result; - } - - if (nonzero_digit_dropped) { - buffer[buffer_pos++] = '1'; - exponent--; - } - - ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos] = '\0'; - - double converted; - if (read_as_double) { - converted = Strtod(Vector(buffer, buffer_pos), exponent); - } else { - converted = Strtof(Vector(buffer, buffer_pos), exponent); - } - *processed_characters_count = static_cast(current - input); - return sign? -converted: converted; -} - - -double StringToDoubleConverter::StringToDouble( - const char* buffer, - int length, - int* processed_characters_count) const { - return StringToIeee(buffer, length, true, processed_characters_count); -} - - -double StringToDoubleConverter::StringToDouble( - const uc16* buffer, - int length, - int* processed_characters_count) const { - return StringToIeee(buffer, length, true, processed_characters_count); -} - - -float StringToDoubleConverter::StringToFloat( - const char* buffer, - int length, - int* processed_characters_count) const { - return static_cast(StringToIeee(buffer, length, false, - processed_characters_count)); -} - - -float StringToDoubleConverter::StringToFloat( - const uc16* buffer, - int length, - int* processed_characters_count) const { - return static_cast(StringToIeee(buffer, length, false, - processed_characters_count)); -} - -} // namespace double_conversion - -// ICU PATCH: Close ICU namespace -U_NAMESPACE_END -#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-diy-fp.cpp icu-65.1/source/i18n/double-conversion-diy-fp.cpp --- icu-64.2/source/i18n/double-conversion-diy-fp.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-diy-fp.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -// © 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -// -// From the double-conversion library. Original license: -// -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING -#include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING - -// ICU PATCH: Customize header file paths for ICU. - -#include "double-conversion-diy-fp.h" -#include "double-conversion-utils.h" - -// ICU PATCH: Wrap in ICU namespace -U_NAMESPACE_BEGIN - -namespace double_conversion { - -void DiyFp::Multiply(const DiyFp& other) { - // Simply "emulates" a 128 bit multiplication. - // However: the resulting number only contains 64 bits. The least - // significant 64 bits are only used for rounding the most significant 64 - // bits. - const uint64_t kM32 = 0xFFFFFFFFU; - uint64_t a = f_ >> 32; - uint64_t b = f_ & kM32; - uint64_t c = other.f_ >> 32; - uint64_t d = other.f_ & kM32; - uint64_t ac = a * c; - uint64_t bc = b * c; - uint64_t ad = a * d; - uint64_t bd = b * d; - uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32); - // By adding 1U << 31 to tmp we round the final result. - // Halfway cases will be round up. - tmp += 1U << 31; - uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); - e_ += other.e_ + 64; - f_ = result_f; -} - -} // namespace double_conversion - -// ICU PATCH: Close ICU namespace -U_NAMESPACE_END -#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-diy-fp.h icu-65.1/source/i18n/double-conversion-diy-fp.h --- icu-64.2/source/i18n/double-conversion-diy-fp.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-diy-fp.h 2019-10-03 11:16:41.000000000 +0000 @@ -50,36 +50,55 @@ // with a uint64 significand and an int exponent. Normalized DiyFp numbers will // have the most significant bit of the significand set. // Multiplication and Subtraction do not normalize their results. -// DiyFp are not designed to contain special doubles (NaN and Infinity). +// DiyFp store only non-negative numbers and are not designed to contain special +// doubles (NaN and Infinity). class DiyFp { public: static const int kSignificandSize = 64; DiyFp() : f_(0), e_(0) {} - DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {} + DiyFp(const uint64_t significand, const int32_t exponent) : f_(significand), e_(exponent) {} - // this = this - other. + // this -= other. // The exponents of both numbers must be the same and the significand of this - // must be bigger than the significand of other. + // must be greater or equal than the significand of other. // The result will not be normalized. void Subtract(const DiyFp& other) { - ASSERT(e_ == other.e_); - ASSERT(f_ >= other.f_); + DOUBLE_CONVERSION_ASSERT(e_ == other.e_); + DOUBLE_CONVERSION_ASSERT(f_ >= other.f_); f_ -= other.f_; } // Returns a - b. - // The exponents of both numbers must be the same and this must be bigger - // than other. The result will not be normalized. + // The exponents of both numbers must be the same and a must be greater + // or equal than b. The result will not be normalized. static DiyFp Minus(const DiyFp& a, const DiyFp& b) { DiyFp result = a; result.Subtract(b); return result; } - - // this = this * other. - void Multiply(const DiyFp& other); + // this *= other. + void Multiply(const DiyFp& other) { + // Simply "emulates" a 128 bit multiplication. + // However: the resulting number only contains 64 bits. The least + // significant 64 bits are only used for rounding the most significant 64 + // bits. + const uint64_t kM32 = 0xFFFFFFFFU; + const uint64_t a = f_ >> 32; + const uint64_t b = f_ & kM32; + const uint64_t c = other.f_ >> 32; + const uint64_t d = other.f_ & kM32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + // By adding 1U << 31 to tmp we round the final result. + // Halfway cases will be rounded up. + const uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32) + (1U << 31); + e_ += other.e_ + 64; + f_ = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); + } // returns a * b; static DiyFp Times(const DiyFp& a, const DiyFp& b) { @@ -89,13 +108,13 @@ } void Normalize() { - ASSERT(f_ != 0); + DOUBLE_CONVERSION_ASSERT(f_ != 0); uint64_t significand = f_; - int exponent = e_; + int32_t exponent = e_; - // This method is mainly called for normalizing boundaries. In general - // boundaries need to be shifted by 10 bits. We thus optimize for this case. - const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); + // This method is mainly called for normalizing boundaries. In general, + // boundaries need to be shifted by 10 bits, and we optimize for this case. + const uint64_t k10MSBits = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFC00000, 00000000); while ((significand & k10MSBits) == 0) { significand <<= 10; exponent -= 10; @@ -115,16 +134,16 @@ } uint64_t f() const { return f_; } - int e() const { return e_; } + int32_t e() const { return e_; } void set_f(uint64_t new_value) { f_ = new_value; } - void set_e(int new_value) { e_ = new_value; } + void set_e(int32_t new_value) { e_ = new_value; } private: - static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000); + static const uint64_t kUint64MSB = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000); uint64_t f_; - int e_; + int32_t e_; }; } // namespace double_conversion diff -Nru icu-64.2/source/i18n/double-conversion-double-to-string.cpp icu-65.1/source/i18n/double-conversion-double-to-string.cpp --- icu-64.2/source/i18n/double-conversion-double-to-string.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-double-to-string.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,450 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +#include +#include +#include + +// ICU PATCH: Customize header file paths for ICU. +// The file fixed-dtoa.h is not needed. + +#include "double-conversion-double-to-string.h" + +#include "double-conversion-bignum-dtoa.h" +#include "double-conversion-fast-dtoa.h" +#include "double-conversion-ieee.h" +#include "double-conversion-utils.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +#if 0 // not needed for ICU +const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() { + int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; + static DoubleToStringConverter converter(flags, + "Infinity", + "NaN", + 'e', + -6, 21, + 6, 0); + return converter; +} + + +bool DoubleToStringConverter::HandleSpecialValues( + double value, + StringBuilder* result_builder) const { + Double double_inspect(value); + if (double_inspect.IsInfinite()) { + if (infinity_symbol_ == NULL) return false; + if (value < 0) { + result_builder->AddCharacter('-'); + } + result_builder->AddString(infinity_symbol_); + return true; + } + if (double_inspect.IsNan()) { + if (nan_symbol_ == NULL) return false; + result_builder->AddString(nan_symbol_); + return true; + } + return false; +} + + +void DoubleToStringConverter::CreateExponentialRepresentation( + const char* decimal_digits, + int length, + int exponent, + StringBuilder* result_builder) const { + DOUBLE_CONVERSION_ASSERT(length != 0); + result_builder->AddCharacter(decimal_digits[0]); + if (length != 1) { + result_builder->AddCharacter('.'); + result_builder->AddSubstring(&decimal_digits[1], length-1); + } + result_builder->AddCharacter(exponent_character_); + if (exponent < 0) { + result_builder->AddCharacter('-'); + exponent = -exponent; + } else { + if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) { + result_builder->AddCharacter('+'); + } + } + if (exponent == 0) { + result_builder->AddCharacter('0'); + return; + } + DOUBLE_CONVERSION_ASSERT(exponent < 1e4); + // Changing this constant requires updating the comment of DoubleToStringConverter constructor + const int kMaxExponentLength = 5; + char buffer[kMaxExponentLength + 1]; + buffer[kMaxExponentLength] = '\0'; + int first_char_pos = kMaxExponentLength; + while (exponent > 0) { + buffer[--first_char_pos] = '0' + (exponent % 10); + exponent /= 10; + } + // Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength) + // For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2 + while(kMaxExponentLength - first_char_pos < std::min(min_exponent_width_, kMaxExponentLength)) { + buffer[--first_char_pos] = '0'; + } + result_builder->AddSubstring(&buffer[first_char_pos], + kMaxExponentLength - first_char_pos); +} + + +void DoubleToStringConverter::CreateDecimalRepresentation( + const char* decimal_digits, + int length, + int decimal_point, + int digits_after_point, + StringBuilder* result_builder) const { + // Create a representation that is padded with zeros if needed. + if (decimal_point <= 0) { + // "0.00000decimal_rep" or "0.000decimal_rep00". + result_builder->AddCharacter('0'); + if (digits_after_point > 0) { + result_builder->AddCharacter('.'); + result_builder->AddPadding('0', -decimal_point); + DOUBLE_CONVERSION_ASSERT(length <= digits_after_point - (-decimal_point)); + result_builder->AddSubstring(decimal_digits, length); + int remaining_digits = digits_after_point - (-decimal_point) - length; + result_builder->AddPadding('0', remaining_digits); + } + } else if (decimal_point >= length) { + // "decimal_rep0000.00000" or "decimal_rep.0000". + result_builder->AddSubstring(decimal_digits, length); + result_builder->AddPadding('0', decimal_point - length); + if (digits_after_point > 0) { + result_builder->AddCharacter('.'); + result_builder->AddPadding('0', digits_after_point); + } + } else { + // "decima.l_rep000". + DOUBLE_CONVERSION_ASSERT(digits_after_point > 0); + result_builder->AddSubstring(decimal_digits, decimal_point); + result_builder->AddCharacter('.'); + DOUBLE_CONVERSION_ASSERT(length - decimal_point <= digits_after_point); + result_builder->AddSubstring(&decimal_digits[decimal_point], + length - decimal_point); + int remaining_digits = digits_after_point - (length - decimal_point); + result_builder->AddPadding('0', remaining_digits); + } + if (digits_after_point == 0) { + if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { + result_builder->AddCharacter('.'); + } + if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { + result_builder->AddCharacter('0'); + } + } +} + + +bool DoubleToStringConverter::ToShortestIeeeNumber( + double value, + StringBuilder* result_builder, + DoubleToStringConverter::DtoaMode mode) const { + DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE); + if (Double(value).IsSpecial()) { + return HandleSpecialValues(value, result_builder); + } + + int decimal_point; + bool sign; + const int kDecimalRepCapacity = kBase10MaximalLength + 1; + char decimal_rep[kDecimalRepCapacity]; + int decimal_rep_length; + + DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity, + &sign, &decimal_rep_length, &decimal_point); + + bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; + if (sign && (value != 0.0 || !unique_zero)) { + result_builder->AddCharacter('-'); + } + + int exponent = decimal_point - 1; + if ((decimal_in_shortest_low_ <= exponent) && + (exponent < decimal_in_shortest_high_)) { + CreateDecimalRepresentation(decimal_rep, decimal_rep_length, + decimal_point, + (std::max)(0, decimal_rep_length - decimal_point), + result_builder); + } else { + CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, + result_builder); + } + return true; +} + + +bool DoubleToStringConverter::ToFixed(double value, + int requested_digits, + StringBuilder* result_builder) const { + DOUBLE_CONVERSION_ASSERT(kMaxFixedDigitsBeforePoint == 60); + const double kFirstNonFixed = 1e60; + + if (Double(value).IsSpecial()) { + return HandleSpecialValues(value, result_builder); + } + + if (requested_digits > kMaxFixedDigitsAfterPoint) return false; + if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; + + // Find a sufficiently precise decimal representation of n. + int decimal_point; + bool sign; + // Add space for the '\0' byte. + const int kDecimalRepCapacity = + kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; + char decimal_rep[kDecimalRepCapacity]; + int decimal_rep_length; + DoubleToAscii(value, FIXED, requested_digits, + decimal_rep, kDecimalRepCapacity, + &sign, &decimal_rep_length, &decimal_point); + + bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); + if (sign && (value != 0.0 || !unique_zero)) { + result_builder->AddCharacter('-'); + } + + CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, + requested_digits, result_builder); + return true; +} + + +bool DoubleToStringConverter::ToExponential( + double value, + int requested_digits, + StringBuilder* result_builder) const { + if (Double(value).IsSpecial()) { + return HandleSpecialValues(value, result_builder); + } + + if (requested_digits < -1) return false; + if (requested_digits > kMaxExponentialDigits) return false; + + int decimal_point; + bool sign; + // Add space for digit before the decimal point and the '\0' character. + const int kDecimalRepCapacity = kMaxExponentialDigits + 2; + DOUBLE_CONVERSION_ASSERT(kDecimalRepCapacity > kBase10MaximalLength); + char decimal_rep[kDecimalRepCapacity]; +#ifndef NDEBUG + // Problem: there is an assert in StringBuilder::AddSubstring() that + // will pass this buffer to strlen(), and this buffer is not generally + // null-terminated. + memset(decimal_rep, 0, sizeof(decimal_rep)); +#endif + int decimal_rep_length; + + if (requested_digits == -1) { + DoubleToAscii(value, SHORTEST, 0, + decimal_rep, kDecimalRepCapacity, + &sign, &decimal_rep_length, &decimal_point); + } else { + DoubleToAscii(value, PRECISION, requested_digits + 1, + decimal_rep, kDecimalRepCapacity, + &sign, &decimal_rep_length, &decimal_point); + DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= requested_digits + 1); + + for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { + decimal_rep[i] = '0'; + } + decimal_rep_length = requested_digits + 1; + } + + bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); + if (sign && (value != 0.0 || !unique_zero)) { + result_builder->AddCharacter('-'); + } + + int exponent = decimal_point - 1; + CreateExponentialRepresentation(decimal_rep, + decimal_rep_length, + exponent, + result_builder); + return true; +} + + +bool DoubleToStringConverter::ToPrecision(double value, + int precision, + StringBuilder* result_builder) const { + if (Double(value).IsSpecial()) { + return HandleSpecialValues(value, result_builder); + } + + if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) { + return false; + } + + // Find a sufficiently precise decimal representation of n. + int decimal_point; + bool sign; + // Add one for the terminating null character. + const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; + char decimal_rep[kDecimalRepCapacity]; + int decimal_rep_length; + + DoubleToAscii(value, PRECISION, precision, + decimal_rep, kDecimalRepCapacity, + &sign, &decimal_rep_length, &decimal_point); + DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= precision); + + bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); + if (sign && (value != 0.0 || !unique_zero)) { + result_builder->AddCharacter('-'); + } + + // The exponent if we print the number as x.xxeyyy. That is with the + // decimal point after the first digit. + int exponent = decimal_point - 1; + + int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0; + if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) || + (decimal_point - precision + extra_zero > + max_trailing_padding_zeroes_in_precision_mode_)) { + // Fill buffer to contain 'precision' digits. + // Usually the buffer is already at the correct length, but 'DoubleToAscii' + // is allowed to return less characters. + for (int i = decimal_rep_length; i < precision; ++i) { + decimal_rep[i] = '0'; + } + + CreateExponentialRepresentation(decimal_rep, + precision, + exponent, + result_builder); + } else { + CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, + (std::max)(0, precision - decimal_point), + result_builder); + } + return true; +} +#endif // not needed for ICU + + +static BignumDtoaMode DtoaToBignumDtoaMode( + DoubleToStringConverter::DtoaMode dtoa_mode) { + switch (dtoa_mode) { + case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST; + case DoubleToStringConverter::SHORTEST_SINGLE: + return BIGNUM_DTOA_SHORTEST_SINGLE; + case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; + case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; + default: + DOUBLE_CONVERSION_UNREACHABLE(); + } +} + + +void DoubleToStringConverter::DoubleToAscii(double v, + DtoaMode mode, + int requested_digits, + char* buffer, + int buffer_length, + bool* sign, + int* length, + int* point) { + Vector vector(buffer, buffer_length); + DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial()); + DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0); + + if (Double(v).Sign() < 0) { + *sign = true; + v = -v; + } else { + *sign = false; + } + + if (mode == PRECISION && requested_digits == 0) { + vector[0] = '\0'; + *length = 0; + return; + } + + if (v == 0) { + vector[0] = '0'; + vector[1] = '\0'; + *length = 1; + *point = 1; + return; + } + + bool fast_worked; + switch (mode) { + case SHORTEST: + fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point); + break; +#if 0 // not needed for ICU + case SHORTEST_SINGLE: + fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, + vector, length, point); + break; + case FIXED: + fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point); + break; + case PRECISION: + fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, + vector, length, point); + break; +#endif // not needed for ICU + default: + fast_worked = false; + DOUBLE_CONVERSION_UNREACHABLE(); + } + if (fast_worked) return; + + // If the fast dtoa didn't succeed use the slower bignum version. + BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode); + BignumDtoa(v, bignum_mode, requested_digits, vector, length, point); + vector[*length] = '\0'; +} + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-double-to-string.h icu-65.1/source/i18n/double-conversion-double-to-string.h --- icu-64.2/source/i18n/double-conversion-double-to-string.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-double-to-string.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,419 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +#ifndef DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_ +#define DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_ + +// ICU PATCH: Customize header file paths for ICU. + +#include "double-conversion-utils.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +class DoubleToStringConverter { + public: +#if 0 // not needed for ICU + // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint + // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the + // function returns false. + static const int kMaxFixedDigitsBeforePoint = 60; + static const int kMaxFixedDigitsAfterPoint = 60; + + // When calling ToExponential with a requested_digits + // parameter > kMaxExponentialDigits then the function returns false. + static const int kMaxExponentialDigits = 120; + + // When calling ToPrecision with a requested_digits + // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits + // then the function returns false. + static const int kMinPrecisionDigits = 1; + static const int kMaxPrecisionDigits = 120; + + enum Flags { + NO_FLAGS = 0, + EMIT_POSITIVE_EXPONENT_SIGN = 1, + EMIT_TRAILING_DECIMAL_POINT = 2, + EMIT_TRAILING_ZERO_AFTER_POINT = 4, + UNIQUE_ZERO = 8 + }; + + // Flags should be a bit-or combination of the possible Flags-enum. + // - NO_FLAGS: no special flags. + // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent + // form, emits a '+' for positive exponents. Example: 1.2e+2. + // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is + // converted into decimal format then a trailing decimal point is appended. + // Example: 2345.0 is converted to "2345.". + // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point + // emits a trailing '0'-character. This flag requires the + // EXMIT_TRAILING_DECIMAL_POINT flag. + // Example: 2345.0 is converted to "2345.0". + // - UNIQUE_ZERO: "-0.0" is converted to "0.0". + // + // Infinity symbol and nan_symbol provide the string representation for these + // special values. If the string is NULL and the special value is encountered + // then the conversion functions return false. + // + // The exponent_character is used in exponential representations. It is + // usually 'e' or 'E'. + // + // When converting to the shortest representation the converter will + // represent input numbers in decimal format if they are in the interval + // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[ + // (lower boundary included, greater boundary excluded). + // Example: with decimal_in_shortest_low = -6 and + // decimal_in_shortest_high = 21: + // ToShortest(0.000001) -> "0.000001" + // ToShortest(0.0000001) -> "1e-7" + // ToShortest(111111111111111111111.0) -> "111111111111111110000" + // ToShortest(100000000000000000000.0) -> "100000000000000000000" + // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" + // + // When converting to precision mode the converter may add + // max_leading_padding_zeroes before returning the number in exponential + // format. + // Example with max_leading_padding_zeroes_in_precision_mode = 6. + // ToPrecision(0.0000012345, 2) -> "0.0000012" + // ToPrecision(0.00000012345, 2) -> "1.2e-7" + // Similarily the converter may add up to + // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid + // returning an exponential representation. A zero added by the + // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. + // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: + // ToPrecision(230.0, 2) -> "230" + // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. + // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. + // + // The min_exponent_width is used for exponential representations. + // The converter adds leading '0's to the exponent until the exponent + // is at least min_exponent_width digits long. + // The min_exponent_width is clamped to 5. + // As such, the exponent may never have more than 5 digits in total. + DoubleToStringConverter(int flags, + const char* infinity_symbol, + const char* nan_symbol, + char exponent_character, + int decimal_in_shortest_low, + int decimal_in_shortest_high, + int max_leading_padding_zeroes_in_precision_mode, + int max_trailing_padding_zeroes_in_precision_mode, + int min_exponent_width = 0) + : flags_(flags), + infinity_symbol_(infinity_symbol), + nan_symbol_(nan_symbol), + exponent_character_(exponent_character), + decimal_in_shortest_low_(decimal_in_shortest_low), + decimal_in_shortest_high_(decimal_in_shortest_high), + max_leading_padding_zeroes_in_precision_mode_( + max_leading_padding_zeroes_in_precision_mode), + max_trailing_padding_zeroes_in_precision_mode_( + max_trailing_padding_zeroes_in_precision_mode), + min_exponent_width_(min_exponent_width) { + // When 'trailing zero after the point' is set, then 'trailing point' + // must be set too. + DOUBLE_CONVERSION_ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || + !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0)); + } + + // Returns a converter following the EcmaScript specification. + static const DoubleToStringConverter& EcmaScriptConverter(); + + // Computes the shortest string of digits that correctly represent the input + // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high + // (see constructor) it then either returns a decimal representation, or an + // exponential representation. + // Example with decimal_in_shortest_low = -6, + // decimal_in_shortest_high = 21, + // EMIT_POSITIVE_EXPONENT_SIGN activated, and + // EMIT_TRAILING_DECIMAL_POINT deactived: + // ToShortest(0.000001) -> "0.000001" + // ToShortest(0.0000001) -> "1e-7" + // ToShortest(111111111111111111111.0) -> "111111111111111110000" + // ToShortest(100000000000000000000.0) -> "100000000000000000000" + // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" + // + // Note: the conversion may round the output if the returned string + // is accurate enough to uniquely identify the input-number. + // For example the most precise representation of the double 9e59 equals + // "899999999999999918767229449717619953810131273674690656206848", but + // the converter will return the shorter (but still correct) "9e59". + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except when the input value is special and no infinity_symbol or + // nan_symbol has been given to the constructor. + bool ToShortest(double value, StringBuilder* result_builder) const { + return ToShortestIeeeNumber(value, result_builder, SHORTEST); + } + + // Same as ToShortest, but for single-precision floats. + bool ToShortestSingle(float value, StringBuilder* result_builder) const { + return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE); + } + + + // Computes a decimal representation with a fixed number of digits after the + // decimal point. The last emitted digit is rounded. + // + // Examples: + // ToFixed(3.12, 1) -> "3.1" + // ToFixed(3.1415, 3) -> "3.142" + // ToFixed(1234.56789, 4) -> "1234.5679" + // ToFixed(1.23, 5) -> "1.23000" + // ToFixed(0.1, 4) -> "0.1000" + // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00" + // ToFixed(0.1, 30) -> "0.100000000000000005551115123126" + // ToFixed(0.1, 17) -> "0.10000000000000001" + // + // If requested_digits equals 0, then the tail of the result depends on + // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT. + // Examples, for requested_digits == 0, + // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be + // - false and false: then 123.45 -> 123 + // 0.678 -> 1 + // - true and false: then 123.45 -> 123. + // 0.678 -> 1. + // - true and true: then 123.45 -> 123.0 + // 0.678 -> 1.0 + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except for the following cases: + // - the input value is special and no infinity_symbol or nan_symbol has + // been provided to the constructor, + // - 'value' > 10^kMaxFixedDigitsBeforePoint, or + // - 'requested_digits' > kMaxFixedDigitsAfterPoint. + // The last two conditions imply that the result will never contain more than + // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters + // (one additional character for the sign, and one for the decimal point). + bool ToFixed(double value, + int requested_digits, + StringBuilder* result_builder) const; + + // Computes a representation in exponential format with requested_digits + // after the decimal point. The last emitted digit is rounded. + // If requested_digits equals -1, then the shortest exponential representation + // is computed. + // + // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and + // exponent_character set to 'e'. + // ToExponential(3.12, 1) -> "3.1e0" + // ToExponential(5.0, 3) -> "5.000e0" + // ToExponential(0.001, 2) -> "1.00e-3" + // ToExponential(3.1415, -1) -> "3.1415e0" + // ToExponential(3.1415, 4) -> "3.1415e0" + // ToExponential(3.1415, 3) -> "3.142e0" + // ToExponential(123456789000000, 3) -> "1.235e14" + // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30" + // ToExponential(1000000000000000019884624838656.0, 32) -> + // "1.00000000000000001988462483865600e30" + // ToExponential(1234, 0) -> "1e3" + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except for the following cases: + // - the input value is special and no infinity_symbol or nan_symbol has + // been provided to the constructor, + // - 'requested_digits' > kMaxExponentialDigits. + // The last condition implies that the result will never contain more than + // kMaxExponentialDigits + 8 characters (the sign, the digit before the + // decimal point, the decimal point, the exponent character, the + // exponent's sign, and at most 3 exponent digits). + bool ToExponential(double value, + int requested_digits, + StringBuilder* result_builder) const; + + // Computes 'precision' leading digits of the given 'value' and returns them + // either in exponential or decimal format, depending on + // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the + // constructor). + // The last computed digit is rounded. + // + // Example with max_leading_padding_zeroes_in_precision_mode = 6. + // ToPrecision(0.0000012345, 2) -> "0.0000012" + // ToPrecision(0.00000012345, 2) -> "1.2e-7" + // Similarily the converter may add up to + // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid + // returning an exponential representation. A zero added by the + // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. + // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: + // ToPrecision(230.0, 2) -> "230" + // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. + // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. + // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no + // EMIT_TRAILING_ZERO_AFTER_POINT: + // ToPrecision(123450.0, 6) -> "123450" + // ToPrecision(123450.0, 5) -> "123450" + // ToPrecision(123450.0, 4) -> "123500" + // ToPrecision(123450.0, 3) -> "123000" + // ToPrecision(123450.0, 2) -> "1.2e5" + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except for the following cases: + // - the input value is special and no infinity_symbol or nan_symbol has + // been provided to the constructor, + // - precision < kMinPericisionDigits + // - precision > kMaxPrecisionDigits + // The last condition implies that the result will never contain more than + // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the + // exponent character, the exponent's sign, and at most 3 exponent digits). + bool ToPrecision(double value, + int precision, + StringBuilder* result_builder) const; +#endif // not needed for ICU + + enum DtoaMode { + // Produce the shortest correct representation. + // For example the output of 0.299999999999999988897 is (the less accurate + // but correct) 0.3. + SHORTEST, + // Same as SHORTEST, but for single-precision floats. + SHORTEST_SINGLE, + // Produce a fixed number of digits after the decimal point. + // For instance fixed(0.1, 4) becomes 0.1000 + // If the input number is big, the output will be big. + FIXED, + // Fixed number of digits (independent of the decimal point). + PRECISION + }; + + // The maximal number of digits that are needed to emit a double in base 10. + // A higher precision can be achieved by using more digits, but the shortest + // accurate representation of any double will never use more digits than + // kBase10MaximalLength. + // Note that DoubleToAscii null-terminates its input. So the given buffer + // should be at least kBase10MaximalLength + 1 characters long. + static const int kBase10MaximalLength = 17; + + // Converts the given double 'v' to digit characters. 'v' must not be NaN, + // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also + // applies to 'v' after it has been casted to a single-precision float. That + // is, in this mode static_cast(v) must not be NaN, +Infinity or + // -Infinity. + // + // The result should be interpreted as buffer * 10^(point-length). + // + // The digits are written to the buffer in the platform's charset, which is + // often UTF-8 (with ASCII-range digits) but may be another charset, such + // as EBCDIC. + // + // The output depends on the given mode: + // - SHORTEST: produce the least amount of digits for which the internal + // identity requirement is still satisfied. If the digits are printed + // (together with the correct exponent) then reading this number will give + // 'v' again. The buffer will choose the representation that is closest to + // 'v'. If there are two at the same distance, than the one farther away + // from 0 is chosen (halfway cases - ending with 5 - are rounded up). + // In this mode the 'requested_digits' parameter is ignored. + // - SHORTEST_SINGLE: same as SHORTEST but with single-precision. + // - FIXED: produces digits necessary to print a given number with + // 'requested_digits' digits after the decimal point. The produced digits + // might be too short in which case the caller has to fill the remainder + // with '0's. + // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. + // Halfway cases are rounded towards +/-Infinity (away from 0). The call + // toFixed(0.15, 2) thus returns buffer="2", point=0. + // The returned buffer may contain digits that would be truncated from the + // shortest representation of the input. + // - PRECISION: produces 'requested_digits' where the first digit is not '0'. + // Even though the length of produced digits usually equals + // 'requested_digits', the function is allowed to return fewer digits, in + // which case the caller has to fill the missing digits with '0's. + // Halfway cases are again rounded away from 0. + // DoubleToAscii expects the given buffer to be big enough to hold all + // digits and a terminating null-character. In SHORTEST-mode it expects a + // buffer of at least kBase10MaximalLength + 1. In all other modes the + // requested_digits parameter and the padding-zeroes limit the size of the + // output. Don't forget the decimal point, the exponent character and the + // terminating null-character when computing the maximal output size. + // The given length is only used in debug mode to ensure the buffer is big + // enough. + // ICU PATCH: Export this as U_I18N_API for unit tests. + static void U_I18N_API DoubleToAscii(double v, + DtoaMode mode, + int requested_digits, + char* buffer, + int buffer_length, + bool* sign, + int* length, + int* point); + +#if 0 // not needed for ICU + private: + // Implementation for ToShortest and ToShortestSingle. + bool ToShortestIeeeNumber(double value, + StringBuilder* result_builder, + DtoaMode mode) const; + + // If the value is a special value (NaN or Infinity) constructs the + // corresponding string using the configured infinity/nan-symbol. + // If either of them is NULL or the value is not special then the + // function returns false. + bool HandleSpecialValues(double value, StringBuilder* result_builder) const; + // Constructs an exponential representation (i.e. 1.234e56). + // The given exponent assumes a decimal point after the first decimal digit. + void CreateExponentialRepresentation(const char* decimal_digits, + int length, + int exponent, + StringBuilder* result_builder) const; + // Creates a decimal representation (i.e 1234.5678). + void CreateDecimalRepresentation(const char* decimal_digits, + int length, + int decimal_point, + int digits_after_point, + StringBuilder* result_builder) const; + + const int flags_; + const char* const infinity_symbol_; + const char* const nan_symbol_; + const char exponent_character_; + const int decimal_in_shortest_low_; + const int decimal_in_shortest_high_; + const int max_leading_padding_zeroes_in_precision_mode_; + const int max_trailing_padding_zeroes_in_precision_mode_; + const int min_exponent_width_; +#endif // not needed for ICU + + DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter); +}; + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END + +#endif // DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_ +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-fast-dtoa.cpp icu-65.1/source/i18n/double-conversion-fast-dtoa.cpp --- icu-64.2/source/i18n/double-conversion-fast-dtoa.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-fast-dtoa.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -152,7 +152,7 @@ // Conceptually rest ~= too_high - buffer // We need to do the following tests in this order to avoid over- and // underflows. - ASSERT(rest <= unsafe_interval); + DOUBLE_CONVERSION_ASSERT(rest <= unsafe_interval); while (rest < small_distance && // Negated condition 1 unsafe_interval - rest >= ten_kappa && // Negated condition 2 (rest + ten_kappa < small_distance || // buffer{-1} > w_high @@ -198,7 +198,7 @@ uint64_t ten_kappa, uint64_t unit, int* kappa) { - ASSERT(rest < ten_kappa); + DOUBLE_CONVERSION_ASSERT(rest < ten_kappa); // The following tests are done in a specific order to avoid overflows. They // will work correctly with any uint64 values of rest < ten_kappa and unit. // @@ -255,7 +255,7 @@ int number_bits, uint32_t* power, int* exponent_plus_one) { - ASSERT(number < (1u << (number_bits + 1))); + DOUBLE_CONVERSION_ASSERT(number < (1u << (number_bits + 1))); // 1233/4096 is approximately 1/lg(10). int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12); // We increment to skip over the first entry in the kPowersOf10 table. @@ -317,9 +317,9 @@ Vector buffer, int* length, int* kappa) { - ASSERT(low.e() == w.e() && w.e() == high.e()); - ASSERT(low.f() + 1 <= high.f() - 1); - ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); + DOUBLE_CONVERSION_ASSERT(low.e() == w.e() && w.e() == high.e()); + DOUBLE_CONVERSION_ASSERT(low.f() + 1 <= high.f() - 1); + DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); // low, w and high are imprecise, but by less than one ulp (unit in the last // place). // If we remove (resp. add) 1 ulp from low (resp. high) we are certain that @@ -361,7 +361,7 @@ // that is smaller than integrals. while (*kappa > 0) { int digit = integrals / divisor; - ASSERT(digit <= 9); + DOUBLE_CONVERSION_ASSERT(digit <= 9); buffer[*length] = static_cast('0' + digit); (*length)++; integrals %= divisor; @@ -388,16 +388,16 @@ // data (like the interval or 'unit'), too. // Note that the multiplication by 10 does not overflow, because w.e >= -60 // and thus one.e >= -60. - ASSERT(one.e() >= -60); - ASSERT(fractionals < one.f()); - ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); + DOUBLE_CONVERSION_ASSERT(one.e() >= -60); + DOUBLE_CONVERSION_ASSERT(fractionals < one.f()); + DOUBLE_CONVERSION_ASSERT(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); for (;;) { fractionals *= 10; unit *= 10; unsafe_interval.set_f(unsafe_interval.f() * 10); // Integer division by one. int digit = static_cast(fractionals >> -one.e()); - ASSERT(digit <= 9); + DOUBLE_CONVERSION_ASSERT(digit <= 9); buffer[*length] = static_cast('0' + digit); (*length)++; fractionals &= one.f() - 1; // Modulo by one. @@ -444,9 +444,9 @@ Vector buffer, int* length, int* kappa) { - ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); - ASSERT(kMinimalTargetExponent >= -60); - ASSERT(kMaximalTargetExponent <= -32); + DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); + DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent >= -60); + DOUBLE_CONVERSION_ASSERT(kMaximalTargetExponent <= -32); // w is assumed to have an error less than 1 unit. Whenever w is scaled we // also scale its error. uint64_t w_error = 1; @@ -472,7 +472,7 @@ // that is smaller than 'integrals'. while (*kappa > 0) { int digit = integrals / divisor; - ASSERT(digit <= 9); + DOUBLE_CONVERSION_ASSERT(digit <= 9); buffer[*length] = static_cast('0' + digit); (*length)++; requested_digits--; @@ -498,15 +498,15 @@ // data (the 'unit'), too. // Note that the multiplication by 10 does not overflow, because w.e >= -60 // and thus one.e >= -60. - ASSERT(one.e() >= -60); - ASSERT(fractionals < one.f()); - ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); + DOUBLE_CONVERSION_ASSERT(one.e() >= -60); + DOUBLE_CONVERSION_ASSERT(fractionals < one.f()); + DOUBLE_CONVERSION_ASSERT(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); while (requested_digits > 0 && fractionals > w_error) { fractionals *= 10; w_error *= 10; // Integer division by one. int digit = static_cast(fractionals >> -one.e()); - ASSERT(digit <= 9); + DOUBLE_CONVERSION_ASSERT(digit <= 9); buffer[*length] = static_cast('0' + digit); (*length)++; requested_digits--; @@ -544,11 +544,11 @@ if (mode == FAST_DTOA_SHORTEST) { Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus); } else { - ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE); + DOUBLE_CONVERSION_ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE); float single_v = static_cast(v); Single(single_v).NormalizedBoundaries(&boundary_minus, &boundary_plus); } - ASSERT(boundary_plus.e() == w.e()); + DOUBLE_CONVERSION_ASSERT(boundary_plus.e() == w.e()); DiyFp ten_mk; // Cached power of ten: 10^-k int mk; // -k int ten_mk_minimal_binary_exponent = @@ -559,7 +559,7 @@ ten_mk_minimal_binary_exponent, ten_mk_maximal_binary_exponent, &ten_mk, &mk); - ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + + DOUBLE_CONVERSION_ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + DiyFp::kSignificandSize) && (kMaximalTargetExponent >= w.e() + ten_mk.e() + DiyFp::kSignificandSize)); @@ -573,7 +573,7 @@ // In other words: let f = scaled_w.f() and e = scaled_w.e(), then // (f-1) * 2^e < w*10^k < (f+1) * 2^e DiyFp scaled_w = DiyFp::Times(w, ten_mk); - ASSERT(scaled_w.e() == + DOUBLE_CONVERSION_ASSERT(scaled_w.e() == boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize); // In theory it would be possible to avoid some recomputations by computing // the difference between w and boundary_minus/plus (a power of 2) and to @@ -618,7 +618,7 @@ ten_mk_minimal_binary_exponent, ten_mk_maximal_binary_exponent, &ten_mk, &mk); - ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + + DOUBLE_CONVERSION_ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + DiyFp::kSignificandSize) && (kMaximalTargetExponent >= w.e() + ten_mk.e() + DiyFp::kSignificandSize)); @@ -652,8 +652,8 @@ Vector buffer, int* length, int* decimal_point) { - ASSERT(v > 0); - ASSERT(!Double(v).IsSpecial()); + DOUBLE_CONVERSION_ASSERT(v > 0); + DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial()); bool result = false; int decimal_exponent = 0; @@ -667,7 +667,7 @@ buffer, length, &decimal_exponent); break; default: - UNREACHABLE(); + DOUBLE_CONVERSION_UNREACHABLE(); } if (result) { *decimal_point = *length + decimal_exponent; diff -Nru icu-64.2/source/i18n/double-conversion.h icu-65.1/source/i18n/double-conversion.h --- icu-64.2/source/i18n/double-conversion.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion.h 2019-10-03 11:16:41.000000000 +0000 @@ -39,561 +39,8 @@ // ICU PATCH: Customize header file paths for ICU. -#include "double-conversion-utils.h" - -// ICU PATCH: Wrap in ICU namespace -U_NAMESPACE_BEGIN - -namespace double_conversion { - -class DoubleToStringConverter { - public: -#if 0 // not needed for ICU - // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint - // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the - // function returns false. - static const int kMaxFixedDigitsBeforePoint = 60; - static const int kMaxFixedDigitsAfterPoint = 60; - - // When calling ToExponential with a requested_digits - // parameter > kMaxExponentialDigits then the function returns false. - static const int kMaxExponentialDigits = 120; - - // When calling ToPrecision with a requested_digits - // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits - // then the function returns false. - static const int kMinPrecisionDigits = 1; - static const int kMaxPrecisionDigits = 120; - - enum Flags { - NO_FLAGS = 0, - EMIT_POSITIVE_EXPONENT_SIGN = 1, - EMIT_TRAILING_DECIMAL_POINT = 2, - EMIT_TRAILING_ZERO_AFTER_POINT = 4, - UNIQUE_ZERO = 8 - }; - - // Flags should be a bit-or combination of the possible Flags-enum. - // - NO_FLAGS: no special flags. - // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent - // form, emits a '+' for positive exponents. Example: 1.2e+2. - // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is - // converted into decimal format then a trailing decimal point is appended. - // Example: 2345.0 is converted to "2345.". - // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point - // emits a trailing '0'-character. This flag requires the - // EXMIT_TRAILING_DECIMAL_POINT flag. - // Example: 2345.0 is converted to "2345.0". - // - UNIQUE_ZERO: "-0.0" is converted to "0.0". - // - // Infinity symbol and nan_symbol provide the string representation for these - // special values. If the string is NULL and the special value is encountered - // then the conversion functions return false. - // - // The exponent_character is used in exponential representations. It is - // usually 'e' or 'E'. - // - // When converting to the shortest representation the converter will - // represent input numbers in decimal format if they are in the interval - // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[ - // (lower boundary included, greater boundary excluded). - // Example: with decimal_in_shortest_low = -6 and - // decimal_in_shortest_high = 21: - // ToShortest(0.000001) -> "0.000001" - // ToShortest(0.0000001) -> "1e-7" - // ToShortest(111111111111111111111.0) -> "111111111111111110000" - // ToShortest(100000000000000000000.0) -> "100000000000000000000" - // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" - // - // When converting to precision mode the converter may add - // max_leading_padding_zeroes before returning the number in exponential - // format. - // Example with max_leading_padding_zeroes_in_precision_mode = 6. - // ToPrecision(0.0000012345, 2) -> "0.0000012" - // ToPrecision(0.00000012345, 2) -> "1.2e-7" - // Similarily the converter may add up to - // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid - // returning an exponential representation. A zero added by the - // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. - // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: - // ToPrecision(230.0, 2) -> "230" - // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. - // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. - DoubleToStringConverter(int flags, - const char* infinity_symbol, - const char* nan_symbol, - char exponent_character, - int decimal_in_shortest_low, - int decimal_in_shortest_high, - int max_leading_padding_zeroes_in_precision_mode, - int max_trailing_padding_zeroes_in_precision_mode) - : flags_(flags), - infinity_symbol_(infinity_symbol), - nan_symbol_(nan_symbol), - exponent_character_(exponent_character), - decimal_in_shortest_low_(decimal_in_shortest_low), - decimal_in_shortest_high_(decimal_in_shortest_high), - max_leading_padding_zeroes_in_precision_mode_( - max_leading_padding_zeroes_in_precision_mode), - max_trailing_padding_zeroes_in_precision_mode_( - max_trailing_padding_zeroes_in_precision_mode) { - // When 'trailing zero after the point' is set, then 'trailing point' - // must be set too. - ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || - !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0)); - } - - // Returns a converter following the EcmaScript specification. - static const DoubleToStringConverter& EcmaScriptConverter(); - - // Computes the shortest string of digits that correctly represent the input - // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high - // (see constructor) it then either returns a decimal representation, or an - // exponential representation. - // Example with decimal_in_shortest_low = -6, - // decimal_in_shortest_high = 21, - // EMIT_POSITIVE_EXPONENT_SIGN activated, and - // EMIT_TRAILING_DECIMAL_POINT deactived: - // ToShortest(0.000001) -> "0.000001" - // ToShortest(0.0000001) -> "1e-7" - // ToShortest(111111111111111111111.0) -> "111111111111111110000" - // ToShortest(100000000000000000000.0) -> "100000000000000000000" - // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" - // - // Note: the conversion may round the output if the returned string - // is accurate enough to uniquely identify the input-number. - // For example the most precise representation of the double 9e59 equals - // "899999999999999918767229449717619953810131273674690656206848", but - // the converter will return the shorter (but still correct) "9e59". - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except when the input value is special and no infinity_symbol or - // nan_symbol has been given to the constructor. - bool ToShortest(double value, StringBuilder* result_builder) const { - return ToShortestIeeeNumber(value, result_builder, SHORTEST); - } - - // Same as ToShortest, but for single-precision floats. - bool ToShortestSingle(float value, StringBuilder* result_builder) const { - return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE); - } - - - // Computes a decimal representation with a fixed number of digits after the - // decimal point. The last emitted digit is rounded. - // - // Examples: - // ToFixed(3.12, 1) -> "3.1" - // ToFixed(3.1415, 3) -> "3.142" - // ToFixed(1234.56789, 4) -> "1234.5679" - // ToFixed(1.23, 5) -> "1.23000" - // ToFixed(0.1, 4) -> "0.1000" - // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00" - // ToFixed(0.1, 30) -> "0.100000000000000005551115123126" - // ToFixed(0.1, 17) -> "0.10000000000000001" - // - // If requested_digits equals 0, then the tail of the result depends on - // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT. - // Examples, for requested_digits == 0, - // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be - // - false and false: then 123.45 -> 123 - // 0.678 -> 1 - // - true and false: then 123.45 -> 123. - // 0.678 -> 1. - // - true and true: then 123.45 -> 123.0 - // 0.678 -> 1.0 - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except for the following cases: - // - the input value is special and no infinity_symbol or nan_symbol has - // been provided to the constructor, - // - 'value' > 10^kMaxFixedDigitsBeforePoint, or - // - 'requested_digits' > kMaxFixedDigitsAfterPoint. - // The last two conditions imply that the result will never contain more than - // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters - // (one additional character for the sign, and one for the decimal point). - bool ToFixed(double value, - int requested_digits, - StringBuilder* result_builder) const; - - // Computes a representation in exponential format with requested_digits - // after the decimal point. The last emitted digit is rounded. - // If requested_digits equals -1, then the shortest exponential representation - // is computed. - // - // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and - // exponent_character set to 'e'. - // ToExponential(3.12, 1) -> "3.1e0" - // ToExponential(5.0, 3) -> "5.000e0" - // ToExponential(0.001, 2) -> "1.00e-3" - // ToExponential(3.1415, -1) -> "3.1415e0" - // ToExponential(3.1415, 4) -> "3.1415e0" - // ToExponential(3.1415, 3) -> "3.142e0" - // ToExponential(123456789000000, 3) -> "1.235e14" - // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30" - // ToExponential(1000000000000000019884624838656.0, 32) -> - // "1.00000000000000001988462483865600e30" - // ToExponential(1234, 0) -> "1e3" - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except for the following cases: - // - the input value is special and no infinity_symbol or nan_symbol has - // been provided to the constructor, - // - 'requested_digits' > kMaxExponentialDigits. - // The last condition implies that the result will never contain more than - // kMaxExponentialDigits + 8 characters (the sign, the digit before the - // decimal point, the decimal point, the exponent character, the - // exponent's sign, and at most 3 exponent digits). - bool ToExponential(double value, - int requested_digits, - StringBuilder* result_builder) const; - - // Computes 'precision' leading digits of the given 'value' and returns them - // either in exponential or decimal format, depending on - // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the - // constructor). - // The last computed digit is rounded. - // - // Example with max_leading_padding_zeroes_in_precision_mode = 6. - // ToPrecision(0.0000012345, 2) -> "0.0000012" - // ToPrecision(0.00000012345, 2) -> "1.2e-7" - // Similarily the converter may add up to - // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid - // returning an exponential representation. A zero added by the - // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. - // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: - // ToPrecision(230.0, 2) -> "230" - // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. - // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. - // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no - // EMIT_TRAILING_ZERO_AFTER_POINT: - // ToPrecision(123450.0, 6) -> "123450" - // ToPrecision(123450.0, 5) -> "123450" - // ToPrecision(123450.0, 4) -> "123500" - // ToPrecision(123450.0, 3) -> "123000" - // ToPrecision(123450.0, 2) -> "1.2e5" - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except for the following cases: - // - the input value is special and no infinity_symbol or nan_symbol has - // been provided to the constructor, - // - precision < kMinPericisionDigits - // - precision > kMaxPrecisionDigits - // The last condition implies that the result will never contain more than - // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the - // exponent character, the exponent's sign, and at most 3 exponent digits). - bool ToPrecision(double value, - int precision, - StringBuilder* result_builder) const; -#endif // not needed for ICU - - enum DtoaMode { - // Produce the shortest correct representation. - // For example the output of 0.299999999999999988897 is (the less accurate - // but correct) 0.3. - SHORTEST, - // Same as SHORTEST, but for single-precision floats. - SHORTEST_SINGLE, - // Produce a fixed number of digits after the decimal point. - // For instance fixed(0.1, 4) becomes 0.1000 - // If the input number is big, the output will be big. - FIXED, - // Fixed number of digits (independent of the decimal point). - PRECISION - }; - - // The maximal number of digits that are needed to emit a double in base 10. - // A higher precision can be achieved by using more digits, but the shortest - // accurate representation of any double will never use more digits than - // kBase10MaximalLength. - // Note that DoubleToAscii null-terminates its input. So the given buffer - // should be at least kBase10MaximalLength + 1 characters long. - static const int kBase10MaximalLength = 17; - - // Converts the given double 'v' to digit characters. 'v' must not be NaN, - // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also - // applies to 'v' after it has been casted to a single-precision float. That - // is, in this mode static_cast(v) must not be NaN, +Infinity or - // -Infinity. - // - // The result should be interpreted as buffer * 10^(point-length). - // - // The digits are written to the buffer in the platform's charset, which is - // often UTF-8 (with ASCII-range digits) but may be another charset, such - // as EBCDIC. - // - // The output depends on the given mode: - // - SHORTEST: produce the least amount of digits for which the internal - // identity requirement is still satisfied. If the digits are printed - // (together with the correct exponent) then reading this number will give - // 'v' again. The buffer will choose the representation that is closest to - // 'v'. If there are two at the same distance, than the one farther away - // from 0 is chosen (halfway cases - ending with 5 - are rounded up). - // In this mode the 'requested_digits' parameter is ignored. - // - SHORTEST_SINGLE: same as SHORTEST but with single-precision. - // - FIXED: produces digits necessary to print a given number with - // 'requested_digits' digits after the decimal point. The produced digits - // might be too short in which case the caller has to fill the remainder - // with '0's. - // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. - // Halfway cases are rounded towards +/-Infinity (away from 0). The call - // toFixed(0.15, 2) thus returns buffer="2", point=0. - // The returned buffer may contain digits that would be truncated from the - // shortest representation of the input. - // - PRECISION: produces 'requested_digits' where the first digit is not '0'. - // Even though the length of produced digits usually equals - // 'requested_digits', the function is allowed to return fewer digits, in - // which case the caller has to fill the missing digits with '0's. - // Halfway cases are again rounded away from 0. - // DoubleToAscii expects the given buffer to be big enough to hold all - // digits and a terminating null-character. In SHORTEST-mode it expects a - // buffer of at least kBase10MaximalLength + 1. In all other modes the - // requested_digits parameter and the padding-zeroes limit the size of the - // output. Don't forget the decimal point, the exponent character and the - // terminating null-character when computing the maximal output size. - // The given length is only used in debug mode to ensure the buffer is big - // enough. - // ICU PATCH: Export this as U_I18N_API for unit tests. - static void U_I18N_API DoubleToAscii(double v, - DtoaMode mode, - int requested_digits, - char* buffer, - int buffer_length, - bool* sign, - int* length, - int* point); - -#if 0 // not needed for ICU - private: - // Implementation for ToShortest and ToShortestSingle. - bool ToShortestIeeeNumber(double value, - StringBuilder* result_builder, - DtoaMode mode) const; - - // If the value is a special value (NaN or Infinity) constructs the - // corresponding string using the configured infinity/nan-symbol. - // If either of them is NULL or the value is not special then the - // function returns false. - bool HandleSpecialValues(double value, StringBuilder* result_builder) const; - // Constructs an exponential representation (i.e. 1.234e56). - // The given exponent assumes a decimal point after the first decimal digit. - void CreateExponentialRepresentation(const char* decimal_digits, - int length, - int exponent, - StringBuilder* result_builder) const; - // Creates a decimal representation (i.e 1234.5678). - void CreateDecimalRepresentation(const char* decimal_digits, - int length, - int decimal_point, - int digits_after_point, - StringBuilder* result_builder) const; - - const int flags_; - const char* const infinity_symbol_; - const char* const nan_symbol_; - const char exponent_character_; - const int decimal_in_shortest_low_; - const int decimal_in_shortest_high_; - const int max_leading_padding_zeroes_in_precision_mode_; - const int max_trailing_padding_zeroes_in_precision_mode_; -#endif // not needed for ICU - - DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter); -}; - - -class StringToDoubleConverter { - public: - // Enumeration for allowing octals and ignoring junk when converting - // strings to numbers. - enum Flags { - NO_FLAGS = 0, - ALLOW_HEX = 1, - ALLOW_OCTALS = 2, - ALLOW_TRAILING_JUNK = 4, - ALLOW_LEADING_SPACES = 8, - ALLOW_TRAILING_SPACES = 16, - ALLOW_SPACES_AFTER_SIGN = 32, - ALLOW_CASE_INSENSIBILITY = 64, - ALLOW_HEX_FLOATS = 128, - }; - - static const uc16 kNoSeparator = '\0'; - - // Flags should be a bit-or combination of the possible Flags-enum. - // - NO_FLAGS: no special flags. - // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers. - // Ex: StringToDouble("0x1234") -> 4660.0 - // In StringToDouble("0x1234.56") the characters ".56" are trailing - // junk. The result of the call is hence dependent on - // the ALLOW_TRAILING_JUNK flag and/or the junk value. - // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK, - // the string will not be parsed as "0" followed by junk. - // - // - ALLOW_OCTALS: recognizes the prefix "0" for octals: - // If a sequence of octal digits starts with '0', then the number is - // read as octal integer. Octal numbers may only be integers. - // Ex: StringToDouble("01234") -> 668.0 - // StringToDouble("012349") -> 12349.0 // Not a sequence of octal - // // digits. - // In StringToDouble("01234.56") the characters ".56" are trailing - // junk. The result of the call is hence dependent on - // the ALLOW_TRAILING_JUNK flag and/or the junk value. - // In StringToDouble("01234e56") the characters "e56" are trailing - // junk, too. - // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of - // a double literal. - // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces, - // new-lines, and tabs. - // - ALLOW_TRAILING_SPACES: ignore trailing whitespace. - // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign. - // Ex: StringToDouble("- 123.2") -> -123.2. - // StringToDouble("+ 123.2") -> 123.2 - // - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values: - // infinity and nan. - // - ALLOW_HEX_FLOATS: allows hexadecimal float literals. - // This *must* start with "0x" and separate the exponent with "p". - // Examples: 0x1.2p3 == 9.0 - // 0x10.1p0 == 16.0625 - // ALLOW_HEX and ALLOW_HEX_FLOATS are indendent. - // - // empty_string_value is returned when an empty string is given as input. - // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string - // containing only spaces is converted to the 'empty_string_value', too. - // - // junk_string_value is returned when - // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not - // part of a double-literal) is found. - // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a - // double literal. - // - // infinity_symbol and nan_symbol are strings that are used to detect - // inputs that represent infinity and NaN. They can be null, in which case - // they are ignored. - // The conversion routine first reads any possible signs. Then it compares the - // following character of the input-string with the first character of - // the infinity, and nan-symbol. If either matches, the function assumes, that - // a match has been found, and expects the following input characters to match - // the remaining characters of the special-value symbol. - // This means that the following restrictions apply to special-value symbols: - // - they must not start with signs ('+', or '-'), - // - they must not have the same first character. - // - they must not start with digits. - // - // If the separator character is not kNoSeparator, then that specific - // character is ignored when in between two valid digits of the significant. - // It is not allowed to appear in the exponent. - // It is not allowed to lead or trail the number. - // It is not allowed to appear twice next to each other. - // - // Examples: - // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK, - // empty_string_value = 0.0, - // junk_string_value = NaN, - // infinity_symbol = "infinity", - // nan_symbol = "nan": - // StringToDouble("0x1234") -> 4660.0. - // StringToDouble("0x1234K") -> 4660.0. - // StringToDouble("") -> 0.0 // empty_string_value. - // StringToDouble(" ") -> NaN // junk_string_value. - // StringToDouble(" 1") -> NaN // junk_string_value. - // StringToDouble("0x") -> NaN // junk_string_value. - // StringToDouble("-123.45") -> -123.45. - // StringToDouble("--123.45") -> NaN // junk_string_value. - // StringToDouble("123e45") -> 123e45. - // StringToDouble("123E45") -> 123e45. - // StringToDouble("123e+45") -> 123e45. - // StringToDouble("123E-45") -> 123e-45. - // StringToDouble("123e") -> 123.0 // trailing junk ignored. - // StringToDouble("123e-") -> 123.0 // trailing junk ignored. - // StringToDouble("+NaN") -> NaN // NaN string literal. - // StringToDouble("-infinity") -> -inf. // infinity literal. - // StringToDouble("Infinity") -> NaN // junk_string_value. - // - // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES, - // empty_string_value = 0.0, - // junk_string_value = NaN, - // infinity_symbol = NULL, - // nan_symbol = NULL: - // StringToDouble("0x1234") -> NaN // junk_string_value. - // StringToDouble("01234") -> 668.0. - // StringToDouble("") -> 0.0 // empty_string_value. - // StringToDouble(" ") -> 0.0 // empty_string_value. - // StringToDouble(" 1") -> 1.0 - // StringToDouble("0x") -> NaN // junk_string_value. - // StringToDouble("0123e45") -> NaN // junk_string_value. - // StringToDouble("01239E45") -> 1239e45. - // StringToDouble("-infinity") -> NaN // junk_string_value. - // StringToDouble("NaN") -> NaN // junk_string_value. - // - // flags = NO_FLAGS, - // separator = ' ': - // StringToDouble("1 2 3 4") -> 1234.0 - // StringToDouble("1 2") -> NaN // junk_string_value - // StringToDouble("1 000 000.0") -> 1000000.0 - // StringToDouble("1.000 000") -> 1.0 - // StringToDouble("1.0e1 000") -> NaN // junk_string_value - StringToDoubleConverter(int flags, - double empty_string_value, - double junk_string_value, - const char* infinity_symbol, - const char* nan_symbol, - uc16 separator = kNoSeparator) - : flags_(flags), - empty_string_value_(empty_string_value), - junk_string_value_(junk_string_value), - infinity_symbol_(infinity_symbol), - nan_symbol_(nan_symbol), - separator_(separator) { - } - - // Performs the conversion. - // The output parameter 'processed_characters_count' is set to the number - // of characters that have been processed to read the number. - // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included - // in the 'processed_characters_count'. Trailing junk is never included. - double StringToDouble(const char* buffer, - int length, - int* processed_characters_count) const; - - // Same as StringToDouble above but for 16 bit characters. - double StringToDouble(const uc16* buffer, - int length, - int* processed_characters_count) const; - - // Same as StringToDouble but reads a float. - // Note that this is not equivalent to static_cast(StringToDouble(...)) - // due to potential double-rounding. - float StringToFloat(const char* buffer, - int length, - int* processed_characters_count) const; - - // Same as StringToFloat above but for 16 bit characters. - float StringToFloat(const uc16* buffer, - int length, - int* processed_characters_count) const; - - private: - const int flags_; - const double empty_string_value_; - const double junk_string_value_; - const char* const infinity_symbol_; - const char* const nan_symbol_; - const uc16 separator_; - - template - double StringToIeee(Iterator start_pointer, - int length, - bool read_as_double, - int* processed_characters_count) const; - - DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); -}; - -} // namespace double_conversion - -// ICU PATCH: Close ICU namespace -U_NAMESPACE_END +#include "double-conversion-string-to-double.h" +#include "double-conversion-double-to-string.h" #endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ #endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-ieee.h icu-65.1/source/i18n/double-conversion-ieee.h --- icu-64.2/source/i18n/double-conversion-ieee.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-ieee.h 2019-10-03 11:16:41.000000000 +0000 @@ -55,12 +55,14 @@ // Helper functions for doubles. class Double { public: - static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000); - static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF); - static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000); + static const uint64_t kSignMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000); + static const uint64_t kExponentMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kSignificandMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF); + static const uint64_t kHiddenBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000); static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit. static const int kSignificandSize = 53; + static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; + static const int kMaxExponent = 0x7FF - kExponentBias; Double() : d64_(0) {} explicit Double(double d) : d64_(double_to_uint64(d)) {} @@ -71,14 +73,14 @@ // The value encoded by this Double must be greater or equal to +0.0. // It must not be special (infinity, or NaN). DiyFp AsDiyFp() const { - ASSERT(Sign() > 0); - ASSERT(!IsSpecial()); + DOUBLE_CONVERSION_ASSERT(Sign() > 0); + DOUBLE_CONVERSION_ASSERT(!IsSpecial()); return DiyFp(Significand(), Exponent()); } // The value encoded by this Double must be strictly greater than 0. DiyFp AsNormalizedDiyFp() const { - ASSERT(value() > 0.0); + DOUBLE_CONVERSION_ASSERT(value() > 0.0); uint64_t f = Significand(); int e = Exponent(); @@ -174,7 +176,7 @@ // Precondition: the value encoded by this Double must be greater or equal // than +0.0. DiyFp UpperBoundary() const { - ASSERT(Sign() > 0); + DOUBLE_CONVERSION_ASSERT(Sign() > 0); return DiyFp(Significand() * 2 + 1, Exponent() - 1); } @@ -183,7 +185,7 @@ // exponent as m_plus. // Precondition: the value encoded by this Double must be greater than 0. void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { - ASSERT(value() > 0.0); + DOUBLE_CONVERSION_ASSERT(value() > 0.0); DiyFp v = this->AsDiyFp(); DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); DiyFp m_minus; @@ -236,11 +238,9 @@ } private: - static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; static const int kDenormalExponent = -kExponentBias + 1; - static const int kMaxExponent = 0x7FF - kExponentBias; - static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000); + static const uint64_t kInfinity = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kNaN = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF80000, 00000000); const uint64_t d64_; @@ -271,7 +271,7 @@ (biased_exponent << kPhysicalSignificandSize); } - DC_DISALLOW_COPY_AND_ASSIGN(Double); + DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Double); }; class Single { @@ -290,8 +290,8 @@ // The value encoded by this Single must be greater or equal to +0.0. // It must not be special (infinity, or NaN). DiyFp AsDiyFp() const { - ASSERT(Sign() > 0); - ASSERT(!IsSpecial()); + DOUBLE_CONVERSION_ASSERT(Sign() > 0); + DOUBLE_CONVERSION_ASSERT(!IsSpecial()); return DiyFp(Significand(), Exponent()); } @@ -354,7 +354,7 @@ // exponent as m_plus. // Precondition: the value encoded by this Single must be greater than 0. void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { - ASSERT(value() > 0.0); + DOUBLE_CONVERSION_ASSERT(value() > 0.0); DiyFp v = this->AsDiyFp(); DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); DiyFp m_minus; @@ -372,7 +372,7 @@ // Precondition: the value encoded by this Single must be greater or equal // than +0.0. DiyFp UpperBoundary() const { - ASSERT(Sign() > 0); + DOUBLE_CONVERSION_ASSERT(Sign() > 0); return DiyFp(Significand() * 2 + 1, Exponent() - 1); } @@ -408,7 +408,7 @@ const uint32_t d32_; - DC_DISALLOW_COPY_AND_ASSIGN(Single); + DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Single); }; } // namespace double_conversion diff -Nru icu-64.2/source/i18n/double-conversion-string-to-double.cpp icu-65.1/source/i18n/double-conversion-string-to-double.cpp --- icu-64.2/source/i18n/double-conversion-string-to-double.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-string-to-double.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,790 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +// ICU PATCH: Do not include std::locale. + +#include +// #include +#include + +// ICU PATCH: Customize header file paths for ICU. + +#include "double-conversion-string-to-double.h" + +#include "double-conversion-ieee.h" +#include "double-conversion-strtod.h" +#include "double-conversion-utils.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +namespace { + +inline char ToLower(char ch) { +#if 0 // do not include std::locale in ICU + static const std::ctype& cType = + std::use_facet >(std::locale::classic()); + return cType.tolower(ch); +#else + (void)ch; + DOUBLE_CONVERSION_UNREACHABLE(); +#endif +} + +inline char Pass(char ch) { + return ch; +} + +template +static inline bool ConsumeSubStringImpl(Iterator* current, + Iterator end, + const char* substring, + Converter converter) { + DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring); + for (substring++; *substring != '\0'; substring++) { + ++*current; + if (*current == end || converter(**current) != *substring) { + return false; + } + } + ++*current; + return true; +} + +// Consumes the given substring from the iterator. +// Returns false, if the substring does not match. +template +static bool ConsumeSubString(Iterator* current, + Iterator end, + const char* substring, + bool allow_case_insensitivity) { + if (allow_case_insensitivity) { + return ConsumeSubStringImpl(current, end, substring, ToLower); + } else { + return ConsumeSubStringImpl(current, end, substring, Pass); + } +} + +// Consumes first character of the str is equal to ch +inline bool ConsumeFirstCharacter(char ch, + const char* str, + bool case_insensitivity) { + return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0]; +} +} // namespace + +// Maximum number of significant digits in decimal representation. +// The longest possible double in decimal representation is +// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 +// (768 digits). If we parse a number whose first digits are equal to a +// mean of 2 adjacent doubles (that could have up to 769 digits) the result +// must be rounded to the bigger one unless the tail consists of zeros, so +// we don't need to preserve all the digits. +const int kMaxSignificantDigits = 772; + + +static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; +static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7); + + +static const uc16 kWhitespaceTable16[] = { + 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195, + 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279 +}; +static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16); + + +static bool isWhitespace(int x) { + if (x < 128) { + for (int i = 0; i < kWhitespaceTable7Length; i++) { + if (kWhitespaceTable7[i] == x) return true; + } + } else { + for (int i = 0; i < kWhitespaceTable16Length; i++) { + if (kWhitespaceTable16[i] == x) return true; + } + } + return false; +} + + +// Returns true if a nonspace found and false if the end has reached. +template +static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { + while (*current != end) { + if (!isWhitespace(**current)) return true; + ++*current; + } + return false; +} + + +static bool isDigit(int x, int radix) { + return (x >= '0' && x <= '9' && x < '0' + radix) + || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) + || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); +} + + +static double SignedZero(bool sign) { + return sign ? -0.0 : 0.0; +} + + +// Returns true if 'c' is a decimal digit that is valid for the given radix. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the last +// condition was always true. By moving it into a separate function the +// compiler wouldn't warn anymore. +#ifdef _MSC_VER +#pragma optimize("",off) +static bool IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} +#pragma optimize("",on) +#else +static bool inline IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} +#endif +// Returns true if 'c' is a character digit that is valid for the given radix. +// The 'a_character' should be 'a' or 'A'. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the first +// condition was always false. By moving it into a separate function the +// compiler wouldn't warn anymore. +static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { + return radix > 10 && c >= a_character && c < a_character + radix - 10; +} + +// Returns true, when the iterator is equal to end. +template +static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) { + if (separator == StringToDoubleConverter::kNoSeparator) { + ++(*it); + return *it == end; + } + if (!isDigit(**it, base)) { + ++(*it); + return *it == end; + } + ++(*it); + if (*it == end) return true; + if (*it + 1 == end) return false; + if (**it == separator && isDigit(*(*it + 1), base)) { + ++(*it); + } + return *it == end; +} + +// Checks whether the string in the range start-end is a hex-float string. +// This function assumes that the leading '0x'/'0X' is already consumed. +// +// Hex float strings are of one of the following forms: +// - hex_digits+ 'p' ('+'|'-')? exponent_digits+ +// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+ +// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+ +template +static bool IsHexFloatString(Iterator start, + Iterator end, + uc16 separator, + bool allow_trailing_junk) { + DOUBLE_CONVERSION_ASSERT(start != end); + + Iterator current = start; + + bool saw_digit = false; + while (isDigit(*current, 16)) { + saw_digit = true; + if (Advance(¤t, separator, 16, end)) return false; + } + if (*current == '.') { + if (Advance(¤t, separator, 16, end)) return false; + while (isDigit(*current, 16)) { + saw_digit = true; + if (Advance(¤t, separator, 16, end)) return false; + } + } + if (!saw_digit) return false; + if (*current != 'p' && *current != 'P') return false; + if (Advance(¤t, separator, 16, end)) return false; + if (*current == '+' || *current == '-') { + if (Advance(¤t, separator, 16, end)) return false; + } + if (!isDigit(*current, 10)) return false; + if (Advance(¤t, separator, 16, end)) return true; + while (isDigit(*current, 10)) { + if (Advance(¤t, separator, 16, end)) return true; + } + return allow_trailing_junk || !AdvanceToNonspace(¤t, end); +} + + +// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. +// +// If parse_as_hex_float is true, then the string must be a valid +// hex-float. +template +static double RadixStringToIeee(Iterator* current, + Iterator end, + bool sign, + uc16 separator, + bool parse_as_hex_float, + bool allow_trailing_junk, + double junk_string_value, + bool read_as_double, + bool* result_is_junk) { + DOUBLE_CONVERSION_ASSERT(*current != end); + DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float || + IsHexFloatString(*current, end, separator, allow_trailing_junk)); + + const int kDoubleSize = Double::kSignificandSize; + const int kSingleSize = Single::kSignificandSize; + const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; + + *result_is_junk = true; + + int64_t number = 0; + int exponent = 0; + const int radix = (1 << radix_log_2); + // Whether we have encountered a '.' and are parsing the decimal digits. + // Only relevant if parse_as_hex_float is true. + bool post_decimal = false; + + // Skip leading 0s. + while (**current == '0') { + if (Advance(current, separator, radix, end)) { + *result_is_junk = false; + return SignedZero(sign); + } + } + + while (true) { + int digit; + if (IsDecimalDigitForRadix(**current, radix)) { + digit = static_cast(**current) - '0'; + if (post_decimal) exponent -= radix_log_2; + } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { + digit = static_cast(**current) - 'a' + 10; + if (post_decimal) exponent -= radix_log_2; + } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { + digit = static_cast(**current) - 'A' + 10; + if (post_decimal) exponent -= radix_log_2; + } else if (parse_as_hex_float && **current == '.') { + post_decimal = true; + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + continue; + } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { + break; + } else { + if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { + break; + } else { + return junk_string_value; + } + } + + number = number * radix + digit; + int overflow = static_cast(number >> kSignificandSize); + if (overflow != 0) { + // Overflow occurred. Need to determine which direction to round the + // result. + int overflow_bits_count = 1; + while (overflow > 1) { + overflow_bits_count++; + overflow >>= 1; + } + + int dropped_bits_mask = ((1 << overflow_bits_count) - 1); + int dropped_bits = static_cast(number) & dropped_bits_mask; + number >>= overflow_bits_count; + exponent += overflow_bits_count; + + bool zero_tail = true; + for (;;) { + if (Advance(current, separator, radix, end)) break; + if (parse_as_hex_float && **current == '.') { + // Just run over the '.'. We are just trying to see whether there is + // a non-zero digit somewhere. + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + post_decimal = true; + } + if (!isDigit(**current, radix)) break; + zero_tail = zero_tail && **current == '0'; + if (!post_decimal) exponent += radix_log_2; + } + + if (!parse_as_hex_float && + !allow_trailing_junk && + AdvanceToNonspace(current, end)) { + return junk_string_value; + } + + int middle_value = (1 << (overflow_bits_count - 1)); + if (dropped_bits > middle_value) { + number++; // Rounding up. + } else if (dropped_bits == middle_value) { + // Rounding to even to consistency with decimals: half-way case rounds + // up if significant part is odd and down otherwise. + if ((number & 1) != 0 || !zero_tail) { + number++; // Rounding up. + } + } + + // Rounding up may cause overflow. + if ((number & ((int64_t)1 << kSignificandSize)) != 0) { + exponent++; + number >>= 1; + } + break; + } + if (Advance(current, separator, radix, end)) break; + } + + DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize)); + DOUBLE_CONVERSION_ASSERT(static_cast(static_cast(number)) == number); + + *result_is_junk = false; + + if (parse_as_hex_float) { + DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P'); + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + bool is_negative = false; + if (**current == '+') { + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + } else if (**current == '-') { + is_negative = true; + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + } + int written_exponent = 0; + while (IsDecimalDigitForRadix(**current, 10)) { + // No need to read exponents if they are too big. That could potentially overflow + // the `written_exponent` variable. + if (abs(written_exponent) <= 100 * Double::kMaxExponent) { + written_exponent = 10 * written_exponent + **current - '0'; + } + if (Advance(current, separator, radix, end)) break; + } + if (is_negative) written_exponent = -written_exponent; + exponent += written_exponent; + } + + if (exponent == 0 || number == 0) { + if (sign) { + if (number == 0) return -0.0; + number = -number; + } + return static_cast(number); + } + + DOUBLE_CONVERSION_ASSERT(number != 0); + double result = Double(DiyFp(number, exponent)).value(); + return sign ? -result : result; +} + +template +double StringToDoubleConverter::StringToIeee( + Iterator input, + int length, + bool read_as_double, + int* processed_characters_count) const { + Iterator current = input; + Iterator end = input + length; + + *processed_characters_count = 0; + + const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; + const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; + const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; + const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; + const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0; + + // To make sure that iterator dereferencing is valid the following + // convention is used: + // 1. Each '++current' statement is followed by check for equality to 'end'. + // 2. If AdvanceToNonspace returned false then current == end. + // 3. If 'current' becomes equal to 'end' the function returns or goes to + // 'parsing_done'. + // 4. 'current' is not dereferenced after the 'parsing_done' label. + // 5. Code before 'parsing_done' may rely on 'current != end'. + if (current == end) return empty_string_value_; + + if (allow_leading_spaces || allow_trailing_spaces) { + if (!AdvanceToNonspace(¤t, end)) { + *processed_characters_count = static_cast(current - input); + return empty_string_value_; + } + if (!allow_leading_spaces && (input != current)) { + // No leading spaces allowed, but AdvanceToNonspace moved forward. + return junk_string_value_; + } + } + + // The longest form of simplified number is: "-.1eXXX\0". + const int kBufferSize = kMaxSignificantDigits + 10; + char buffer[kBufferSize]; // NOLINT: size is known at compile time. + int buffer_pos = 0; + + // Exponent will be adjusted if insignificant digits of the integer part + // or insignificant leading zeros of the fractional part are dropped. + int exponent = 0; + int significant_digits = 0; + int insignificant_digits = 0; + bool nonzero_digit_dropped = false; + + bool sign = false; + + if (*current == '+' || *current == '-') { + sign = (*current == '-'); + ++current; + Iterator next_non_space = current; + // Skip following spaces (if allowed). + if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; + if (!allow_spaces_after_sign && (current != next_non_space)) { + return junk_string_value_; + } + current = next_non_space; + } + + if (infinity_symbol_ != NULL) { + if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) { + if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensitivity)) { + return junk_string_value_; + } + + if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { + return junk_string_value_; + } + if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + return junk_string_value_; + } + + DOUBLE_CONVERSION_ASSERT(buffer_pos == 0); + *processed_characters_count = static_cast(current - input); + return sign ? -Double::Infinity() : Double::Infinity(); + } + } + + if (nan_symbol_ != NULL) { + if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) { + if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensitivity)) { + return junk_string_value_; + } + + if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { + return junk_string_value_; + } + if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + return junk_string_value_; + } + + DOUBLE_CONVERSION_ASSERT(buffer_pos == 0); + *processed_characters_count = static_cast(current - input); + return sign ? -Double::NaN() : Double::NaN(); + } + } + + bool leading_zero = false; + if (*current == '0') { + if (Advance(¤t, separator_, 10, end)) { + *processed_characters_count = static_cast(current - input); + return SignedZero(sign); + } + + leading_zero = true; + + // It could be hexadecimal value. + if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) && + (*current == 'x' || *current == 'X')) { + ++current; + + if (current == end) return junk_string_value_; // "0x" + + bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) && + IsHexFloatString(current, end, separator_, allow_trailing_junk); + + if (!parse_as_hex_float && !isDigit(*current, 16)) { + return junk_string_value_; + } + + bool result_is_junk; + double result = RadixStringToIeee<4>(¤t, + end, + sign, + separator_, + parse_as_hex_float, + allow_trailing_junk, + junk_string_value_, + read_as_double, + &result_is_junk); + if (!result_is_junk) { + if (allow_trailing_spaces) AdvanceToNonspace(¤t, end); + *processed_characters_count = static_cast(current - input); + } + return result; + } + + // Ignore leading zeros in the integer part. + while (*current == '0') { + if (Advance(¤t, separator_, 10, end)) { + *processed_characters_count = static_cast(current - input); + return SignedZero(sign); + } + } + } + + bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; + + // Copy significant digits of the integer part (if any) to the buffer. + while (*current >= '0' && *current <= '9') { + if (significant_digits < kMaxSignificantDigits) { + DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); + buffer[buffer_pos++] = static_cast(*current); + significant_digits++; + // Will later check if it's an octal in the buffer. + } else { + insignificant_digits++; // Move the digit into the exponential part. + nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; + } + octal = octal && *current < '8'; + if (Advance(¤t, separator_, 10, end)) goto parsing_done; + } + + if (significant_digits == 0) { + octal = false; + } + + if (*current == '.') { + if (octal && !allow_trailing_junk) return junk_string_value_; + if (octal) goto parsing_done; + + if (Advance(¤t, separator_, 10, end)) { + if (significant_digits == 0 && !leading_zero) { + return junk_string_value_; + } else { + goto parsing_done; + } + } + + if (significant_digits == 0) { + // octal = false; + // Integer part consists of 0 or is absent. Significant digits start after + // leading zeros (if any). + while (*current == '0') { + if (Advance(¤t, separator_, 10, end)) { + *processed_characters_count = static_cast(current - input); + return SignedZero(sign); + } + exponent--; // Move this 0 into the exponent. + } + } + + // There is a fractional part. + // We don't emit a '.', but adjust the exponent instead. + while (*current >= '0' && *current <= '9') { + if (significant_digits < kMaxSignificantDigits) { + DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); + buffer[buffer_pos++] = static_cast(*current); + significant_digits++; + exponent--; + } else { + // Ignore insignificant digits in the fractional part. + nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; + } + if (Advance(¤t, separator_, 10, end)) goto parsing_done; + } + } + + if (!leading_zero && exponent == 0 && significant_digits == 0) { + // If leading_zeros is true then the string contains zeros. + // If exponent < 0 then string was [+-]\.0*... + // If significant_digits != 0 the string is not equal to 0. + // Otherwise there are no digits in the string. + return junk_string_value_; + } + + // Parse exponential part. + if (*current == 'e' || *current == 'E') { + if (octal && !allow_trailing_junk) return junk_string_value_; + if (octal) goto parsing_done; + Iterator junk_begin = current; + ++current; + if (current == end) { + if (allow_trailing_junk) { + current = junk_begin; + goto parsing_done; + } else { + return junk_string_value_; + } + } + char exponen_sign = '+'; + if (*current == '+' || *current == '-') { + exponen_sign = static_cast(*current); + ++current; + if (current == end) { + if (allow_trailing_junk) { + current = junk_begin; + goto parsing_done; + } else { + return junk_string_value_; + } + } + } + + if (current == end || *current < '0' || *current > '9') { + if (allow_trailing_junk) { + current = junk_begin; + goto parsing_done; + } else { + return junk_string_value_; + } + } + + const int max_exponent = INT_MAX / 2; + DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); + int num = 0; + do { + // Check overflow. + int digit = *current - '0'; + if (num >= max_exponent / 10 + && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { + num = max_exponent; + } else { + num = num * 10 + digit; + } + ++current; + } while (current != end && *current >= '0' && *current <= '9'); + + exponent += (exponen_sign == '-' ? -num : num); + } + + if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { + return junk_string_value_; + } + if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + return junk_string_value_; + } + if (allow_trailing_spaces) { + AdvanceToNonspace(¤t, end); + } + + parsing_done: + exponent += insignificant_digits; + + if (octal) { + double result; + bool result_is_junk; + char* start = buffer; + result = RadixStringToIeee<3>(&start, + buffer + buffer_pos, + sign, + separator_, + false, // Don't parse as hex_float. + allow_trailing_junk, + junk_string_value_, + read_as_double, + &result_is_junk); + DOUBLE_CONVERSION_ASSERT(!result_is_junk); + *processed_characters_count = static_cast(current - input); + return result; + } + + if (nonzero_digit_dropped) { + buffer[buffer_pos++] = '1'; + exponent--; + } + + DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); + buffer[buffer_pos] = '\0'; + + double converted; + if (read_as_double) { + converted = Strtod(Vector(buffer, buffer_pos), exponent); + } else { + converted = Strtof(Vector(buffer, buffer_pos), exponent); + } + *processed_characters_count = static_cast(current - input); + return sign? -converted: converted; +} + + +double StringToDoubleConverter::StringToDouble( + const char* buffer, + int length, + int* processed_characters_count) const { + return StringToIeee(buffer, length, true, processed_characters_count); +} + + +double StringToDoubleConverter::StringToDouble( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return StringToIeee(buffer, length, true, processed_characters_count); +} + + +float StringToDoubleConverter::StringToFloat( + const char* buffer, + int length, + int* processed_characters_count) const { + return static_cast(StringToIeee(buffer, length, false, + processed_characters_count)); +} + + +float StringToDoubleConverter::StringToFloat( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return static_cast(StringToIeee(buffer, length, false, + processed_characters_count)); +} + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-string-to-double.h icu-65.1/source/i18n/double-conversion-string-to-double.h --- icu-64.2/source/i18n/double-conversion-string-to-double.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-string-to-double.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,244 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +#ifndef DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_ +#define DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_ + +// ICU PATCH: Customize header file paths for ICU. + +#include "double-conversion-utils.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +class StringToDoubleConverter { + public: + // Enumeration for allowing octals and ignoring junk when converting + // strings to numbers. + enum Flags { + NO_FLAGS = 0, + ALLOW_HEX = 1, + ALLOW_OCTALS = 2, + ALLOW_TRAILING_JUNK = 4, + ALLOW_LEADING_SPACES = 8, + ALLOW_TRAILING_SPACES = 16, + ALLOW_SPACES_AFTER_SIGN = 32, + ALLOW_CASE_INSENSITIVITY = 64, + ALLOW_CASE_INSENSIBILITY = 64, // Deprecated + ALLOW_HEX_FLOATS = 128, + }; + + static const uc16 kNoSeparator = '\0'; + + // Flags should be a bit-or combination of the possible Flags-enum. + // - NO_FLAGS: no special flags. + // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers. + // Ex: StringToDouble("0x1234") -> 4660.0 + // In StringToDouble("0x1234.56") the characters ".56" are trailing + // junk. The result of the call is hence dependent on + // the ALLOW_TRAILING_JUNK flag and/or the junk value. + // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK, + // the string will not be parsed as "0" followed by junk. + // + // - ALLOW_OCTALS: recognizes the prefix "0" for octals: + // If a sequence of octal digits starts with '0', then the number is + // read as octal integer. Octal numbers may only be integers. + // Ex: StringToDouble("01234") -> 668.0 + // StringToDouble("012349") -> 12349.0 // Not a sequence of octal + // // digits. + // In StringToDouble("01234.56") the characters ".56" are trailing + // junk. The result of the call is hence dependent on + // the ALLOW_TRAILING_JUNK flag and/or the junk value. + // In StringToDouble("01234e56") the characters "e56" are trailing + // junk, too. + // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of + // a double literal. + // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces, + // new-lines, and tabs. + // - ALLOW_TRAILING_SPACES: ignore trailing whitespace. + // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign. + // Ex: StringToDouble("- 123.2") -> -123.2. + // StringToDouble("+ 123.2") -> 123.2 + // - ALLOW_CASE_INSENSITIVITY: ignore case of characters for special values: + // infinity and nan. + // - ALLOW_HEX_FLOATS: allows hexadecimal float literals. + // This *must* start with "0x" and separate the exponent with "p". + // Examples: 0x1.2p3 == 9.0 + // 0x10.1p0 == 16.0625 + // ALLOW_HEX and ALLOW_HEX_FLOATS are indendent. + // + // empty_string_value is returned when an empty string is given as input. + // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string + // containing only spaces is converted to the 'empty_string_value', too. + // + // junk_string_value is returned when + // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not + // part of a double-literal) is found. + // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a + // double literal. + // + // infinity_symbol and nan_symbol are strings that are used to detect + // inputs that represent infinity and NaN. They can be null, in which case + // they are ignored. + // The conversion routine first reads any possible signs. Then it compares the + // following character of the input-string with the first character of + // the infinity, and nan-symbol. If either matches, the function assumes, that + // a match has been found, and expects the following input characters to match + // the remaining characters of the special-value symbol. + // This means that the following restrictions apply to special-value symbols: + // - they must not start with signs ('+', or '-'), + // - they must not have the same first character. + // - they must not start with digits. + // + // If the separator character is not kNoSeparator, then that specific + // character is ignored when in between two valid digits of the significant. + // It is not allowed to appear in the exponent. + // It is not allowed to lead or trail the number. + // It is not allowed to appear twice next to each other. + // + // Examples: + // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK, + // empty_string_value = 0.0, + // junk_string_value = NaN, + // infinity_symbol = "infinity", + // nan_symbol = "nan": + // StringToDouble("0x1234") -> 4660.0. + // StringToDouble("0x1234K") -> 4660.0. + // StringToDouble("") -> 0.0 // empty_string_value. + // StringToDouble(" ") -> NaN // junk_string_value. + // StringToDouble(" 1") -> NaN // junk_string_value. + // StringToDouble("0x") -> NaN // junk_string_value. + // StringToDouble("-123.45") -> -123.45. + // StringToDouble("--123.45") -> NaN // junk_string_value. + // StringToDouble("123e45") -> 123e45. + // StringToDouble("123E45") -> 123e45. + // StringToDouble("123e+45") -> 123e45. + // StringToDouble("123E-45") -> 123e-45. + // StringToDouble("123e") -> 123.0 // trailing junk ignored. + // StringToDouble("123e-") -> 123.0 // trailing junk ignored. + // StringToDouble("+NaN") -> NaN // NaN string literal. + // StringToDouble("-infinity") -> -inf. // infinity literal. + // StringToDouble("Infinity") -> NaN // junk_string_value. + // + // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES, + // empty_string_value = 0.0, + // junk_string_value = NaN, + // infinity_symbol = NULL, + // nan_symbol = NULL: + // StringToDouble("0x1234") -> NaN // junk_string_value. + // StringToDouble("01234") -> 668.0. + // StringToDouble("") -> 0.0 // empty_string_value. + // StringToDouble(" ") -> 0.0 // empty_string_value. + // StringToDouble(" 1") -> 1.0 + // StringToDouble("0x") -> NaN // junk_string_value. + // StringToDouble("0123e45") -> NaN // junk_string_value. + // StringToDouble("01239E45") -> 1239e45. + // StringToDouble("-infinity") -> NaN // junk_string_value. + // StringToDouble("NaN") -> NaN // junk_string_value. + // + // flags = NO_FLAGS, + // separator = ' ': + // StringToDouble("1 2 3 4") -> 1234.0 + // StringToDouble("1 2") -> NaN // junk_string_value + // StringToDouble("1 000 000.0") -> 1000000.0 + // StringToDouble("1.000 000") -> 1.0 + // StringToDouble("1.0e1 000") -> NaN // junk_string_value + StringToDoubleConverter(int flags, + double empty_string_value, + double junk_string_value, + const char* infinity_symbol, + const char* nan_symbol, + uc16 separator = kNoSeparator) + : flags_(flags), + empty_string_value_(empty_string_value), + junk_string_value_(junk_string_value), + infinity_symbol_(infinity_symbol), + nan_symbol_(nan_symbol), + separator_(separator) { + } + + // Performs the conversion. + // The output parameter 'processed_characters_count' is set to the number + // of characters that have been processed to read the number. + // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included + // in the 'processed_characters_count'. Trailing junk is never included. + double StringToDouble(const char* buffer, + int length, + int* processed_characters_count) const; + + // Same as StringToDouble above but for 16 bit characters. + double StringToDouble(const uc16* buffer, + int length, + int* processed_characters_count) const; + + // Same as StringToDouble but reads a float. + // Note that this is not equivalent to static_cast(StringToDouble(...)) + // due to potential double-rounding. + float StringToFloat(const char* buffer, + int length, + int* processed_characters_count) const; + + // Same as StringToFloat above but for 16 bit characters. + float StringToFloat(const uc16* buffer, + int length, + int* processed_characters_count) const; + + private: + const int flags_; + const double empty_string_value_; + const double junk_string_value_; + const char* const infinity_symbol_; + const char* const nan_symbol_; + const uc16 separator_; + + template + double StringToIeee(Iterator start_pointer, + int length, + bool read_as_double, + int* processed_characters_count) const; + + DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); +}; + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END + +#endif // DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_ +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff -Nru icu-64.2/source/i18n/double-conversion-strtod.cpp icu-65.1/source/i18n/double-conversion-strtod.cpp --- icu-64.2/source/i18n/double-conversion-strtod.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-strtod.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -34,16 +34,15 @@ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING -#include -#include +#include +#include // ICU PATCH: Customize header file paths for ICU. -// The file fixed-dtoa.h is not needed. -#include "double-conversion-strtod.h" #include "double-conversion-bignum.h" #include "double-conversion-cached-powers.h" #include "double-conversion-ieee.h" +#include "double-conversion-strtod.h" // ICU PATCH: Wrap in ICU namespace U_NAMESPACE_BEGIN @@ -67,7 +66,7 @@ static const int kMinDecimalPower = -324; // 2^64 = 18446744073709551616 -static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); +static const uint64_t kMaxUint64 = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); static const double exact_powers_of_ten[] = { @@ -96,7 +95,7 @@ // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 10000000000000000000000.0 }; -static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); +static const int kExactPowersOfTenSize = DOUBLE_CONVERSION_ARRAY_SIZE(exact_powers_of_ten); // Maximum number of significant digits in the decimal representation. // In fact the value is 772 (see conversions.cc), but to give us some margin @@ -132,7 +131,7 @@ } // The input buffer has been trimmed. Therefore the last digit must be // different from '0'. - ASSERT(buffer[buffer.length() - 1] != '0'); + DOUBLE_CONVERSION_ASSERT(buffer[buffer.length() - 1] != '0'); // Set the last digit to be non-zero. This is sufficient to guarantee // correct rounding. significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; @@ -153,7 +152,7 @@ exponent += left_trimmed.length() - right_trimmed.length(); if (right_trimmed.length() > kMaxSignificantDecimalDigits) { (void) space_size; // Mark variable as used. - ASSERT(space_size >= kMaxSignificantDecimalDigits); + DOUBLE_CONVERSION_ASSERT(space_size >= kMaxSignificantDecimalDigits); CutToMaxSignificantDigits(right_trimmed, exponent, buffer_copy_space, updated_exponent); *trimmed = Vector(buffer_copy_space, @@ -176,7 +175,7 @@ int i = 0; while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { int digit = buffer[i++] - '0'; - ASSERT(0 <= digit && digit <= 9); + DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9); result = 10 * result + digit; } *number_of_read_digits = i; @@ -220,7 +219,7 @@ // Note that the ARM simulator is compiled for 32bits. It therefore exhibits // the same problem. return false; -#endif +#else if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { int read_digits; // The trimmed input fits into a double. @@ -232,14 +231,14 @@ if (exponent < 0 && -exponent < kExactPowersOfTenSize) { // 10^-exponent fits into a double. *result = static_cast(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); + DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length()); *result /= exact_powers_of_ten[-exponent]; return true; } if (0 <= exponent && exponent < kExactPowersOfTenSize) { // 10^exponent fits into a double. *result = static_cast(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); + DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length()); *result *= exact_powers_of_ten[exponent]; return true; } @@ -251,34 +250,35 @@ // 10^remaining_digits. As a result the remaining exponent now fits // into a double too. *result = static_cast(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); + DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length()); *result *= exact_powers_of_ten[remaining_digits]; *result *= exact_powers_of_ten[exponent - remaining_digits]; return true; } } return false; +#endif } // Returns 10^exponent as an exact DiyFp. // The given exponent must be in the range [1; kDecimalExponentDistance[. static DiyFp AdjustmentPowerOfTen(int exponent) { - ASSERT(0 < exponent); - ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); + DOUBLE_CONVERSION_ASSERT(0 < exponent); + DOUBLE_CONVERSION_ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); // Simply hardcode the remaining powers for the given decimal exponent // distance. - ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); + DOUBLE_CONVERSION_ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); switch (exponent) { - case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); - case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); - case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); - case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); - case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); - case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); - case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); + case 1: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xa0000000, 00000000), -60); + case 2: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc8000000, 00000000), -57); + case 3: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xfa000000, 00000000), -54); + case 4: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50); + case 5: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc3500000, 00000000), -47); + case 6: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xf4240000, 00000000), -44); + case 7: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x98968000, 00000000), -40); default: - UNREACHABLE(); + DOUBLE_CONVERSION_UNREACHABLE(); } } @@ -307,7 +307,7 @@ input.Normalize(); error <<= old_e - input.e(); - ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); + DOUBLE_CONVERSION_ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); if (exponent < PowersOfTenCache::kMinDecimalExponent) { *result = 0.0; return true; @@ -325,7 +325,7 @@ if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { // The product of input with the adjustment power fits into a 64 bit // integer. - ASSERT(DiyFp::kSignificandSize == 64); + DOUBLE_CONVERSION_ASSERT(DiyFp::kSignificandSize == 64); } else { // The adjustment power is exact. There is hence only an error of 0.5. error += kDenominator / 2; @@ -367,8 +367,8 @@ precision_digits_count -= shift_amount; } // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too. - ASSERT(DiyFp::kSignificandSize == 64); - ASSERT(precision_digits_count < 64); + DOUBLE_CONVERSION_ASSERT(DiyFp::kSignificandSize == 64); + DOUBLE_CONVERSION_ASSERT(precision_digits_count < 64); uint64_t one64 = 1; uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; uint64_t precision_bits = input.f() & precision_bits_mask; @@ -407,14 +407,14 @@ static int CompareBufferWithDiyFp(Vector buffer, int exponent, DiyFp diy_fp) { - ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); - ASSERT(buffer.length() + exponent > kMinDecimalPower); - ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); + DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); + DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent > kMinDecimalPower); + DOUBLE_CONVERSION_ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); // Make sure that the Bignum will be able to hold all our numbers. // Our Bignum implementation has a separate field for exponents. Shifts will // consume at most one bigit (< 64 bits). // ln(10) == 3.3219... - ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); + DOUBLE_CONVERSION_ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); Bignum buffer_bignum; Bignum diy_fp_bignum; buffer_bignum.AssignDecimalString(buffer); @@ -460,18 +460,33 @@ return false; } -double Strtod(Vector buffer, int exponent) { - char copy_buffer[kMaxSignificantDecimalDigits]; - Vector trimmed; - int updated_exponent; - TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, - &trimmed, &updated_exponent); - exponent = updated_exponent; +#if U_DEBUG // needed for ICU only in debug mode +static bool IsDigit(const char d) { + return ('0' <= d) && (d <= '9'); +} - double guess; - bool is_correct = ComputeGuess(trimmed, exponent, &guess); - if (is_correct) return guess; +static bool IsNonZeroDigit(const char d) { + return ('1' <= d) && (d <= '9'); +} + +static bool AssertTrimmedDigits(const Vector& buffer) { + for(int i = 0; i < buffer.length(); ++i) { + if(!IsDigit(buffer[i])) { + return false; + } + } + return (buffer.length() == 0) || (IsNonZeroDigit(buffer[0]) && IsNonZeroDigit(buffer[buffer.length()-1])); +} +#endif // needed for ICU only in debug mode +double StrtodTrimmed(Vector trimmed, int exponent) { + DOUBLE_CONVERSION_ASSERT(trimmed.length() <= kMaxSignificantDecimalDigits); + DOUBLE_CONVERSION_ASSERT(AssertTrimmedDigits(trimmed)); + double guess; + const bool is_correct = ComputeGuess(trimmed, exponent, &guess); + if (is_correct) { + return guess; + } DiyFp upper_boundary = Double(guess).UpperBoundary(); int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); if (comparison < 0) { @@ -486,6 +501,39 @@ } } +double Strtod(Vector buffer, int exponent) { + char copy_buffer[kMaxSignificantDecimalDigits]; + Vector trimmed; + int updated_exponent; + TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, + &trimmed, &updated_exponent); + return StrtodTrimmed(trimmed, updated_exponent); +} + +static float SanitizedDoubletof(double d) { + DOUBLE_CONVERSION_ASSERT(d >= 0.0); + // ASAN has a sanitize check that disallows casting doubles to floats if + // they are too big. + // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks + // The behavior should be covered by IEEE 754, but some projects use this + // flag, so work around it. + float max_finite = 3.4028234663852885981170418348451692544e+38; + // The half-way point between the max-finite and infinity value. + // Since infinity has an even significand everything equal or greater than + // this value should become infinity. + double half_max_finite_infinity = + 3.40282356779733661637539395458142568448e+38; + if (d >= max_finite) { + if (d >= half_max_finite_infinity) { + return Single::Infinity(); + } else { + return max_finite; + } + } else { + return static_cast(d); + } +} + float Strtof(Vector buffer, int exponent) { char copy_buffer[kMaxSignificantDecimalDigits]; Vector trimmed; @@ -497,7 +545,7 @@ double double_guess; bool is_correct = ComputeGuess(trimmed, exponent, &double_guess); - float float_guess = static_cast(double_guess); + float float_guess = SanitizedDoubletof(double_guess); if (float_guess == double_guess) { // This shortcut triggers for integer values. return float_guess; @@ -520,18 +568,18 @@ double double_next = Double(double_guess).NextDouble(); double double_previous = Double(double_guess).PreviousDouble(); - float f1 = static_cast(double_previous); + float f1 = SanitizedDoubletof(double_previous); float f2 = float_guess; - float f3 = static_cast(double_next); + float f3 = SanitizedDoubletof(double_next); float f4; if (is_correct) { f4 = f3; } else { double double_next2 = Double(double_next).NextDouble(); - f4 = static_cast(double_next2); + f4 = SanitizedDoubletof(double_next2); } (void) f2; // Mark variable as used. - ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); + DOUBLE_CONVERSION_ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); // If the guess doesn't lie near a single-precision boundary we can simply // return its float-value. @@ -539,11 +587,11 @@ return float_guess; } - ASSERT((f1 != f2 && f2 == f3 && f3 == f4) || + DOUBLE_CONVERSION_ASSERT((f1 != f2 && f2 == f3 && f3 == f4) || (f1 == f2 && f2 != f3 && f3 == f4) || (f1 == f2 && f2 == f3 && f3 != f4)); - // guess and next are the two possible canditates (in the same way that + // guess and next are the two possible candidates (in the same way that // double_guess was the lower candidate for a double-precision guess). float guess = f1; float next = f4; diff -Nru icu-64.2/source/i18n/double-conversion-strtod.h icu-65.1/source/i18n/double-conversion-strtod.h --- icu-64.2/source/i18n/double-conversion-strtod.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-strtod.h 2019-10-03 11:16:41.000000000 +0000 @@ -54,6 +54,11 @@ // contain a dot or a sign. It must not start with '0', and must not be empty. float Strtof(Vector buffer, int exponent); +// For special use cases, the heart of the Strtod() function is also available +// separately, it assumes that 'trimmed' is as produced by TrimAndCut(), i.e. +// no leading or trailing zeros, also no lone zero, and not 'too many' digits. +double StrtodTrimmed(Vector trimmed, int exponent); + } // namespace double_conversion // ICU PATCH: Close ICU namespace diff -Nru icu-64.2/source/i18n/double-conversion-utils.h icu-65.1/source/i18n/double-conversion-utils.h --- icu-64.2/source/i18n/double-conversion-utils.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/double-conversion-utils.h 2019-10-03 11:16:41.000000000 +0000 @@ -42,10 +42,12 @@ // ICU PATCH: Use U_ASSERT instead of #include "uassert.h" -#define ASSERT U_ASSERT - -#ifndef UNIMPLEMENTED -#define UNIMPLEMENTED() (abort()) +#ifndef DOUBLE_CONVERSION_ASSERT +#define DOUBLE_CONVERSION_ASSERT(condition) \ + U_ASSERT(condition); +#endif +#ifndef DOUBLE_CONVERSION_UNIMPLEMENTED +#define DOUBLE_CONVERSION_UNIMPLEMENTED() (abort()) #endif #ifndef DOUBLE_CONVERSION_NO_RETURN #ifdef _MSC_VER @@ -54,16 +56,23 @@ #define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn)) #endif #endif -#ifndef UNREACHABLE +#ifndef DOUBLE_CONVERSION_UNREACHABLE #ifdef _MSC_VER void DOUBLE_CONVERSION_NO_RETURN abort_noreturn(); inline void abort_noreturn() { abort(); } -#define UNREACHABLE() (abort_noreturn()) +#define DOUBLE_CONVERSION_UNREACHABLE() (abort_noreturn()) #else -#define UNREACHABLE() (abort()) +#define DOUBLE_CONVERSION_UNREACHABLE() (abort()) #endif #endif +#ifndef DOUBLE_CONVERSION_UNUSED +#ifdef __GNUC__ +#define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) +#else +#define DOUBLE_CONVERSION_UNUSED +#endif +#endif // Double operations detection based on target architecture. // Linux uses a 80bit wide floating point stack on x86. This induces double @@ -99,9 +108,9 @@ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ defined(__SH4__) || defined(__alpha__) || \ - defined(_MIPS_ARCH_MIPS32R2) || \ + defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\ defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \ - defined(__riscv) || \ + defined(__riscv) || defined(__e2k__) || \ defined(__or1k__) || defined(__arc__) || \ defined(__EMSCRIPTEN__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 @@ -141,24 +150,24 @@ // The following macro works on both 32 and 64-bit platforms. // Usage: instead of writing 0x1234567890123456 -// write UINT64_2PART_C(0x12345678,90123456); -#define UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) +// write DOUBLE_CONVERSION_UINT64_2PART_C(0x12345678,90123456); +#define DOUBLE_CONVERSION_UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) -// The expression ARRAY_SIZE(a) is a compile-time constant of type +// The expression DOUBLE_CONVERSION_ARRAY_SIZE(a) is a compile-time constant of type // size_t which represents the number of elements of the given -// array. You should only use ARRAY_SIZE on statically allocated +// array. You should only use DOUBLE_CONVERSION_ARRAY_SIZE on statically allocated // arrays. -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) \ +#ifndef DOUBLE_CONVERSION_ARRAY_SIZE +#define DOUBLE_CONVERSION_ARRAY_SIZE(a) \ ((sizeof(a) / sizeof(*(a))) / \ static_cast(!(sizeof(a) % sizeof(*(a))))) #endif // A macro to disallow the evil copy constructor and operator= functions // This should be used in the private: declarations for a class -#ifndef DC_DISALLOW_COPY_AND_ASSIGN -#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \ +#ifndef DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN +#define DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) #endif @@ -169,10 +178,10 @@ // This should be used in the private: declarations for a class // that wants to prevent anyone from instantiating it. This is // especially useful for classes containing only static methods. -#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS -#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ +#ifndef DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS +#define DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ TypeName(); \ - DC_DISALLOW_COPY_AND_ASSIGN(TypeName) + DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName) #endif // ICU PATCH: Wrap in ICU namespace @@ -180,25 +189,9 @@ namespace double_conversion { -static const int kCharSize = sizeof(char); - -// Returns the maximum of the two parameters. -template -static T Max(T a, T b) { - return a < b ? b : a; -} - - -// Returns the minimum of the two parameters. -template -static T Min(T a, T b) { - return a < b ? a : b; -} - - inline int StrLength(const char* string) { size_t length = strlen(string); - ASSERT(length == static_cast(static_cast(length))); + DOUBLE_CONVERSION_ASSERT(length == static_cast(static_cast(length))); return static_cast(length); } @@ -208,15 +201,15 @@ public: Vector() : start_(NULL), length_(0) {} Vector(T* data, int len) : start_(data), length_(len) { - ASSERT(len == 0 || (len > 0 && data != NULL)); + DOUBLE_CONVERSION_ASSERT(len == 0 || (len > 0 && data != NULL)); } // Returns a vector using the same backing storage as this one, // spanning from and including 'from', to but not including 'to'. Vector SubVector(int from, int to) { - ASSERT(to <= length_); - ASSERT(from < to); - ASSERT(0 <= from); + DOUBLE_CONVERSION_ASSERT(to <= length_); + DOUBLE_CONVERSION_ASSERT(from < to); + DOUBLE_CONVERSION_ASSERT(0 <= from); return Vector(start() + from, to - from); } @@ -231,7 +224,7 @@ // Access individual vector elements - checks bounds in debug mode. T& operator[](int index) const { - ASSERT(0 <= index && index < length_); + DOUBLE_CONVERSION_ASSERT(0 <= index && index < length_); return start_[index]; } @@ -239,6 +232,11 @@ T& last() { return start_[length_ - 1]; } + void pop_back() { + DOUBLE_CONVERSION_ASSERT(!is_empty()); + --length_; + } + private: T* start_; int length_; @@ -259,7 +257,7 @@ // Get the current position in the builder. int position() const { - ASSERT(!is_finalized()); + DOUBLE_CONVERSION_ASSERT(!is_finalized()); return position_; } @@ -270,8 +268,8 @@ // 0-characters; use the Finalize() method to terminate the string // instead. void AddCharacter(char c) { - ASSERT(c != '\0'); - ASSERT(!is_finalized() && position_ < buffer_.length()); + DOUBLE_CONVERSION_ASSERT(c != '\0'); + DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length()); buffer_[position_++] = c; } @@ -284,9 +282,9 @@ // Add the first 'n' characters of the given string 's' to the // builder. The input string must have enough characters. void AddSubstring(const char* s, int n) { - ASSERT(!is_finalized() && position_ + n < buffer_.length()); - ASSERT(static_cast(n) <= strlen(s)); - memmove(&buffer_[position_], s, n * kCharSize); + DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ + n < buffer_.length()); + DOUBLE_CONVERSION_ASSERT(static_cast(n) <= strlen(s)); + memmove(&buffer_[position_], s, n); position_ += n; } @@ -301,13 +299,13 @@ // Finalize the string by 0-terminating it and returning the buffer. char* Finalize() { - ASSERT(!is_finalized() && position_ < buffer_.length()); + DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length()); buffer_[position_] = '\0'; // Make sure nobody managed to add a 0-character to the // buffer while building the string. - ASSERT(strlen(buffer_.start()) == static_cast(position_)); + DOUBLE_CONVERSION_ASSERT(strlen(buffer_.start()) == static_cast(position_)); position_ = -1; - ASSERT(is_finalized()); + DOUBLE_CONVERSION_ASSERT(is_finalized()); return buffer_.start(); } @@ -317,7 +315,7 @@ bool is_finalized() const { return position_ < 0; } - DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); + DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); }; // The type-based aliasing rule allows the compiler to assume that pointers of @@ -345,13 +343,14 @@ // enough that it can no longer see that you have cast one pointer type to // another thus avoiding the warning. template -inline Dest BitCast(const Source& source) { +Dest BitCast(const Source& source) { // Compile time assertion: sizeof(Dest) == sizeof(Source) // A compile error here means your Dest and Source have different sizes. #if __cplusplus >= 201103L static_assert(sizeof(Dest) == sizeof(Source), "source and destination size mismatch"); #else + DOUBLE_CONVERSION_UNUSED typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; #endif @@ -361,7 +360,7 @@ } template -inline Dest BitCast(Source* source) { +Dest BitCast(Source* source) { return BitCast(reinterpret_cast(source)); } diff -Nru icu-64.2/source/i18n/dtfmtsym.cpp icu-65.1/source/i18n/dtfmtsym.cpp --- icu-64.2/source/i18n/dtfmtsym.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dtfmtsym.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1246,7 +1246,7 @@ DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const { const UnicodeString **result = NULL; - static UMutex LOCK = U_MUTEX_INITIALIZER; + static UMutex LOCK; umtx_lock(&LOCK); if (fZoneStrings == NULL) { @@ -2177,16 +2177,16 @@ // The ordering of the following statements is important. if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) { fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]); - }; + } if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) { fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]); - }; + } if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) { fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]); - }; + } if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) { fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]); - }; + } // end of hack fLeapMonthPatternsCount = kMonthPatternsCount; } else { @@ -2338,11 +2338,21 @@ assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount); } - // Load AM/PM markers + // Load AM/PM markers; if wide or narrow not available, use short + UErrorCode ampmStatus = U_ZERO_ERROR; initField(&fAmPms, fAmPmsCount, calendarSink, - buildResourcePath(path, gAmPmMarkersTag, status), status); + buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus); + if (U_FAILURE(ampmStatus)) { + initField(&fAmPms, fAmPmsCount, calendarSink, + buildResourcePath(path, gAmPmMarkersAbbrTag, status), status); + } + ampmStatus = U_ZERO_ERROR; initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink, - buildResourcePath(path, gAmPmMarkersNarrowTag, status), status); + buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus); + if (U_FAILURE(ampmStatus)) { + initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink, + buildResourcePath(path, gAmPmMarkersAbbrTag, status), status); + } // Load quarters initField(&fQuarters, fQuartersCount, calendarSink, diff -Nru icu-64.2/source/i18n/dtitvfmt.cpp icu-65.1/source/i18n/dtitvfmt.cpp --- icu-64.2/source/i18n/dtitvfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dtitvfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -82,10 +82,7 @@ // Mutex, protects access to fDateFormat, fFromCalendar and fToCalendar. // Needed because these data members are modified by const methods of DateIntervalFormat. -static UMutex *gFormatterMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gFormatterMutex; DateIntervalFormat* U_EXPORT2 DateIntervalFormat::createInstance(const UnicodeString& skeleton, @@ -171,9 +168,9 @@ delete fTimePattern; delete fDateTimeFormat; { - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); if ( itvfmt.fDateFormat ) { - fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone(); + fDateFormat = itvfmt.fDateFormat->clone(); } else { fDateFormat = NULL; } @@ -199,9 +196,9 @@ fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i]; } fLocale = itvfmt.fLocale; - fDatePattern = (itvfmt.fDatePattern)? (UnicodeString*)itvfmt.fDatePattern->clone(): NULL; - fTimePattern = (itvfmt.fTimePattern)? (UnicodeString*)itvfmt.fTimePattern->clone(): NULL; - fDateTimeFormat = (itvfmt.fDateTimeFormat)? (UnicodeString*)itvfmt.fDateTimeFormat->clone(): NULL; + fDatePattern = (itvfmt.fDatePattern)? itvfmt.fDatePattern->clone(): NULL; + fTimePattern = (itvfmt.fTimePattern)? itvfmt.fTimePattern->clone(): NULL; + fDateTimeFormat = (itvfmt.fDateTimeFormat)? itvfmt.fDateTimeFormat->clone(): NULL; } return *this; } @@ -218,8 +215,8 @@ } -Format* -DateIntervalFormat::clone(void) const { +DateIntervalFormat* +DateIntervalFormat::clone() const { return new DateIntervalFormat(*this); } @@ -233,7 +230,7 @@ if ((fInfo != fmt->fInfo) && (fInfo == NULL || fmt->fInfo == NULL)) {return FALSE;} if (fInfo && fmt->fInfo && (*fInfo != *fmt->fInfo )) {return FALSE;} { - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); if (fDateFormat != fmt->fDateFormat && (fDateFormat == NULL || fmt->fDateFormat == NULL)) {return FALSE;} if (fDateFormat && fmt->fDateFormat && (*fDateFormat != *fmt->fDateFormat)) {return FALSE;} } @@ -295,7 +292,7 @@ handler.setAcceptFirstOnly(TRUE); int8_t ignore; - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); return formatIntervalImpl(*dtInterval, appendTo, ignore, handler, status); } @@ -312,7 +309,7 @@ auto handler = result->getHandler(status); handler.setCategory(UFIELD_CATEGORY_DATE); { - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); formatIntervalImpl(dtInterval, string, firstIndex, handler, status); } handler.getError(status); @@ -344,7 +341,7 @@ handler.setAcceptFirstOnly(TRUE); int8_t ignore; - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); return formatImpl(fromCalendar, toCalendar, appendTo, ignore, handler, status); } @@ -362,7 +359,7 @@ auto handler = result->getHandler(status); handler.setCategory(UFIELD_CATEGORY_DATE); { - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); formatImpl(fromCalendar, toCalendar, string, firstIndex, handler, status); } handler.getError(status); @@ -600,7 +597,7 @@ DateIntervalFormat::getTimeZone() const { if (fDateFormat != NULL) { - Mutex lock(gFormatterMutex()); + Mutex lock(&gFormatterMutex); return fDateFormat->getTimeZone(); } // If fDateFormat is NULL (unexpected), create default timezone. diff -Nru icu-64.2/source/i18n/dtitv_impl.h icu-65.1/source/i18n/dtitv_impl.h --- icu-64.2/source/i18n/dtitv_impl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dtitv_impl.h 2019-10-03 11:16:41.000000000 +0000 @@ -88,7 +88,7 @@ #define MAX_E_COUNT 5 #define MAX_M_COUNT 5 //#define MAX_INTERVAL_INDEX 4 -#define MAX_POSITIVE_INT 56632; +#define MAX_POSITIVE_INT 56632 #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/dtitvinf.cpp icu-65.1/source/i18n/dtitvinf.cpp --- icu-64.2/source/i18n/dtitvinf.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dtitvinf.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -42,7 +42,9 @@ #ifdef DTITVINF_DEBUG -#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; } +#define PRINTMESG(msg) UPRV_BLOCK_MACRO_BEGIN { \ + std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; \ +} UPRV_BLOCK_MACRO_END #endif UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo) diff -Nru icu-64.2/source/i18n/dtptngen.cpp icu-65.1/source/i18n/dtptngen.cpp --- icu-64.2/source/i18n/dtptngen.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/dtptngen.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,7 @@ #include "unicode/ures.h" #include "unicode/ustring.h" #include "unicode/rep.h" +#include "unicode/region.h" #include "cpputils.h" #include "mutex.h" #include "umutex.h" @@ -613,29 +614,56 @@ ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status); } -void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) { - if (U_FAILURE(status)) { return; } - Locale maxLocale(locale); - maxLocale.addLikelySubtags(status); - if (U_FAILURE(status)) { - return; - } - - const char *country = maxLocale.getCountry(); - if (*country == '\0') { country = "001"; } - const char *language = maxLocale.getLanguage(); - +static int32_t* getAllowedHourFormatsLangCountry(const char* language, const char* country, UErrorCode& status) { CharString langCountry; - langCountry.append(language, static_cast(uprv_strlen(language)), status); + langCountry.append(language, status); langCountry.append('_', status); - langCountry.append(country, static_cast(uprv_strlen(country)), status); + langCountry.append(country, status); - int32_t *allowedFormats; + int32_t* allowedFormats; allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, langCountry.data()); if (allowedFormats == nullptr) { allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, const_cast(country)); } + return allowedFormats; +} + +void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) { + if (U_FAILURE(status)) { return; } + + const char *language = locale.getLanguage(); + const char *country = locale.getCountry(); + Locale maxLocale; // must be here for correct lifetime + if (*language == '\0' || *country == '\0') { + maxLocale = locale; + UErrorCode localStatus = U_ZERO_ERROR; + maxLocale.addLikelySubtags(localStatus); + if (U_SUCCESS(localStatus)) { + language = maxLocale.getLanguage(); + country = maxLocale.getCountry(); + } + } + if (*language == '\0') { + // Unexpected, but fail gracefully + language = "und"; + } + if (*country == '\0') { + country = "001"; + } + + int32_t* allowedFormats = getAllowedHourFormatsLangCountry(language, country, status); + + // Check if the region has an alias + if (allowedFormats == nullptr) { + UErrorCode localStatus = U_ZERO_ERROR; + const Region* region = Region::getInstance(country, localStatus); + if (U_SUCCESS(localStatus)) { + country = region->getRegionCode(); // the real region code + allowedFormats = getAllowedHourFormatsLangCountry(language, country, status); + } + } + if (allowedFormats != nullptr) { // Lookup is successful // Here allowedFormats points to a list consisting of key for preferredFormat, // followed by one or more keys for allowedFormats, then followed by ALLOWED_HOUR_FORMAT_UNKNOWN. @@ -787,6 +815,7 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& destination, UErrorCode& err) { destination.clear().append(DT_DateTimeGregorianTag, -1, err); // initial default if ( U_SUCCESS(err) ) { + UErrorCode localStatus = U_ZERO_ERROR; char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY]; // obtain a locale that always has the calendar key value that should be used ures_getFunctionalEquivalent( @@ -798,8 +827,7 @@ locale.getName(), nullptr, FALSE, - &err); - if (U_FAILURE(err)) { return; } + &localStatus); localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination // now get the calendar key value from that locale char calendarType[ULOC_KEYWORDS_CAPACITY]; @@ -808,13 +836,17 @@ "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, - &err); - if (U_FAILURE(err)) { return; } + &localStatus); + // If the input locale was invalid, don't fail with missing resource error, instead + // continue with default of Gregorian. + if (U_FAILURE(localStatus) && localStatus != U_MISSING_RESOURCE_ERROR) { + err = localStatus; + return; + } if (calendarTypeLen < ULOC_KEYWORDS_CAPACITY) { destination.clear().append(calendarType, -1, err); if (U_FAILURE(err)) { return; } } - err = U_ZERO_ERROR; } } @@ -2543,7 +2575,8 @@ } -PtnSkeleton::PtnSkeleton() { +PtnSkeleton::PtnSkeleton() + : addedDefaultDayPeriod(FALSE) { } PtnSkeleton::PtnSkeleton(const PtnSkeleton& other) { @@ -2554,6 +2587,7 @@ uprv_memcpy(type, other.type, sizeof(type)); original.copyFrom(other.original); baseOriginal.copyFrom(other.baseOriginal); + addedDefaultDayPeriod = other.addedDefaultDayPeriod; } void PtnSkeleton::clear() { diff -Nru icu-64.2/source/i18n/esctrn.cpp icu-65.1/source/i18n/esctrn.cpp --- icu-64.2/source/i18n/esctrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/esctrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -122,7 +122,7 @@ /** * Transliterator API. */ -Transliterator* EscapeTransliterator::clone() const { +EscapeTransliterator* EscapeTransliterator::clone() const { return new EscapeTransliterator(*this); } diff -Nru icu-64.2/source/i18n/esctrn.h icu-65.1/source/i18n/esctrn.h --- icu-64.2/source/i18n/esctrn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/esctrn.h 2019-10-03 11:16:41.000000000 +0000 @@ -115,7 +115,7 @@ /** * Transliterator API. */ - virtual Transliterator* clone() const; + virtual EscapeTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/ethpccal.cpp icu-65.1/source/i18n/ethpccal.cpp --- icu-64.2/source/i18n/ethpccal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/ethpccal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -46,7 +46,7 @@ { } -Calendar* +EthiopicCalendar* EthiopicCalendar::clone() const { return new EthiopicCalendar(*this); diff -Nru icu-64.2/source/i18n/ethpccal.h icu-65.1/source/i18n/ethpccal.h --- icu-64.2/source/i18n/ethpccal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/ethpccal.h 2019-10-03 11:16:41.000000000 +0000 @@ -141,7 +141,7 @@ * @return return a polymorphic copy of this calendar. * @internal */ - virtual Calendar* clone() const; + virtual EthiopicCalendar* clone() const; /** * return the calendar type, "ethiopic" diff -Nru icu-64.2/source/i18n/fmtable.cpp icu-65.1/source/i18n/fmtable.cpp --- icu-64.2/source/i18n/fmtable.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/fmtable.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -736,7 +736,7 @@ fDecimalStr->append("Infinity", status); } else if (fDecimalQuantity->isNaN()) { fDecimalStr->append("NaN", status); - } else if (fDecimalQuantity->isZero()) { + } else if (fDecimalQuantity->isZeroish()) { fDecimalStr->append("0", -1, status); } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) { diff -Nru icu-64.2/source/i18n/formatted_string_builder.cpp icu-65.1/source/i18n/formatted_string_builder.cpp --- icu-64.2/source/i18n/formatted_string_builder.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/formatted_string_builder.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,439 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "formatted_string_builder.h" +#include "unicode/ustring.h" +#include "unicode/utf16.h" + +namespace { + +// A version of uprv_memcpy that checks for length 0. +// By default, uprv_memcpy requires a length of at least 1. +inline void uprv_memcpy2(void* dest, const void* src, size_t len) { + if (len > 0) { + uprv_memcpy(dest, src, len); + } +} + +// A version of uprv_memmove that checks for length 0. +// By default, uprv_memmove requires a length of at least 1. +inline void uprv_memmove2(void* dest, const void* src, size_t len) { + if (len > 0) { + uprv_memmove(dest, src, len); + } +} + +} // namespace + + +U_NAMESPACE_BEGIN + +FormattedStringBuilder::FormattedStringBuilder() { +#if U_DEBUG + // Initializing the memory to non-zero helps catch some bugs that involve + // reading from an improperly terminated string. + for (int32_t i=0; i DEFAULT_CAPACITY) { + // FIXME: uprv_malloc + // C++ note: malloc appears in two places: here and in prepareForInsertHelper. + auto newChars = static_cast (uprv_malloc(sizeof(char16_t) * capacity)); + auto newFields = static_cast(uprv_malloc(sizeof(Field) * capacity)); + if (newChars == nullptr || newFields == nullptr) { + // UErrorCode is not available; fail silently. + uprv_free(newChars); + uprv_free(newFields); + *this = FormattedStringBuilder(); // can't fail + return *this; + } + + fUsingHeap = true; + fChars.heap.capacity = capacity; + fChars.heap.ptr = newChars; + fFields.heap.capacity = capacity; + fFields.heap.ptr = newFields; + } + + uprv_memcpy2(getCharPtr(), other.getCharPtr(), sizeof(char16_t) * capacity); + uprv_memcpy2(getFieldPtr(), other.getFieldPtr(), sizeof(Field) * capacity); + + fZero = other.fZero; + fLength = other.fLength; + return *this; +} + +int32_t FormattedStringBuilder::length() const { + return fLength; +} + +int32_t FormattedStringBuilder::codePointCount() const { + return u_countChar32(getCharPtr() + fZero, fLength); +} + +UChar32 FormattedStringBuilder::getFirstCodePoint() const { + if (fLength == 0) { + return -1; + } + UChar32 cp; + U16_GET(getCharPtr() + fZero, 0, 0, fLength, cp); + return cp; +} + +UChar32 FormattedStringBuilder::getLastCodePoint() const { + if (fLength == 0) { + return -1; + } + int32_t offset = fLength; + U16_BACK_1(getCharPtr() + fZero, 0, offset); + UChar32 cp; + U16_GET(getCharPtr() + fZero, 0, offset, fLength, cp); + return cp; +} + +UChar32 FormattedStringBuilder::codePointAt(int32_t index) const { + UChar32 cp; + U16_GET(getCharPtr() + fZero, 0, index, fLength, cp); + return cp; +} + +UChar32 FormattedStringBuilder::codePointBefore(int32_t index) const { + int32_t offset = index; + U16_BACK_1(getCharPtr() + fZero, 0, offset); + UChar32 cp; + U16_GET(getCharPtr() + fZero, 0, offset, fLength, cp); + return cp; +} + +FormattedStringBuilder &FormattedStringBuilder::clear() { + // TODO: Reset the heap here? + fZero = getCapacity() / 2; + fLength = 0; + return *this; +} + +int32_t +FormattedStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status) { + int32_t count = U16_LENGTH(codePoint); + int32_t position = prepareForInsert(index, count, status); + if (U_FAILURE(status)) { + return count; + } + if (count == 1) { + getCharPtr()[position] = (char16_t) codePoint; + getFieldPtr()[position] = field; + } else { + getCharPtr()[position] = U16_LEAD(codePoint); + getCharPtr()[position + 1] = U16_TRAIL(codePoint); + getFieldPtr()[position] = getFieldPtr()[position + 1] = field; + } + return count; +} + +int32_t FormattedStringBuilder::insert(int32_t index, const UnicodeString &unistr, Field field, + UErrorCode &status) { + if (unistr.length() == 0) { + // Nothing to insert. + return 0; + } else if (unistr.length() == 1) { + // Fast path: insert using insertCodePoint. + return insertCodePoint(index, unistr.charAt(0), field, status); + } else { + return insert(index, unistr, 0, unistr.length(), field, status); + } +} + +int32_t +FormattedStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, + Field field, UErrorCode &status) { + int32_t count = end - start; + int32_t position = prepareForInsert(index, count, status); + if (U_FAILURE(status)) { + return count; + } + for (int32_t i = 0; i < count; i++) { + getCharPtr()[position + i] = unistr.charAt(start + i); + getFieldPtr()[position + i] = field; + } + return count; +} + +int32_t +FormattedStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr, + int32_t startOther, int32_t endOther, Field field, UErrorCode& status) { + int32_t thisLength = endThis - startThis; + int32_t otherLength = endOther - startOther; + int32_t count = otherLength - thisLength; + int32_t position; + if (count > 0) { + // Overall, chars need to be added. + position = prepareForInsert(startThis, count, status); + } else { + // Overall, chars need to be removed or kept the same. + position = remove(startThis, -count); + } + if (U_FAILURE(status)) { + return count; + } + for (int32_t i = 0; i < otherLength; i++) { + getCharPtr()[position + i] = unistr.charAt(startOther + i); + getFieldPtr()[position + i] = field; + } + return count; +} + +int32_t FormattedStringBuilder::append(const FormattedStringBuilder &other, UErrorCode &status) { + return insert(fLength, other, status); +} + +int32_t +FormattedStringBuilder::insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status) { + if (this == &other) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + int32_t count = other.fLength; + if (count == 0) { + // Nothing to insert. + return 0; + } + int32_t position = prepareForInsert(index, count, status); + if (U_FAILURE(status)) { + return count; + } + for (int32_t i = 0; i < count; i++) { + getCharPtr()[position + i] = other.charAt(i); + getFieldPtr()[position + i] = other.fieldAt(i); + } + return count; +} + +void FormattedStringBuilder::writeTerminator(UErrorCode& status) { + int32_t position = prepareForInsert(fLength, 1, status); + if (U_FAILURE(status)) { + return; + } + getCharPtr()[position] = 0; + getFieldPtr()[position] = UNUM_FIELD_COUNT; + fLength--; +} + +int32_t FormattedStringBuilder::prepareForInsert(int32_t index, int32_t count, UErrorCode &status) { + U_ASSERT(index >= 0); + U_ASSERT(index <= fLength); + U_ASSERT(count >= 0); + if (index == 0 && fZero - count >= 0) { + // Append to start + fZero -= count; + fLength += count; + return fZero; + } else if (index == fLength && fZero + fLength + count < getCapacity()) { + // Append to end + fLength += count; + return fZero + fLength - count; + } else { + // Move chars around and/or allocate more space + return prepareForInsertHelper(index, count, status); + } +} + +int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status) { + int32_t oldCapacity = getCapacity(); + int32_t oldZero = fZero; + char16_t *oldChars = getCharPtr(); + Field *oldFields = getFieldPtr(); + if (fLength + count > oldCapacity) { + int32_t newCapacity = (fLength + count) * 2; + int32_t newZero = newCapacity / 2 - (fLength + count) / 2; + + // C++ note: malloc appears in two places: here and in the assignment operator. + auto newChars = static_cast (uprv_malloc(sizeof(char16_t) * newCapacity)); + auto newFields = static_cast(uprv_malloc(sizeof(Field) * newCapacity)); + if (newChars == nullptr || newFields == nullptr) { + uprv_free(newChars); + uprv_free(newFields); + status = U_MEMORY_ALLOCATION_ERROR; + return -1; + } + + // First copy the prefix and then the suffix, leaving room for the new chars that the + // caller wants to insert. + // C++ note: memcpy is OK because the src and dest do not overlap. + uprv_memcpy2(newChars + newZero, oldChars + oldZero, sizeof(char16_t) * index); + uprv_memcpy2(newChars + newZero + index + count, + oldChars + oldZero + index, + sizeof(char16_t) * (fLength - index)); + uprv_memcpy2(newFields + newZero, oldFields + oldZero, sizeof(Field) * index); + uprv_memcpy2(newFields + newZero + index + count, + oldFields + oldZero + index, + sizeof(Field) * (fLength - index)); + + if (fUsingHeap) { + uprv_free(oldChars); + uprv_free(oldFields); + } + fUsingHeap = true; + fChars.heap.ptr = newChars; + fChars.heap.capacity = newCapacity; + fFields.heap.ptr = newFields; + fFields.heap.capacity = newCapacity; + fZero = newZero; + fLength += count; + } else { + int32_t newZero = oldCapacity / 2 - (fLength + count) / 2; + + // C++ note: memmove is required because src and dest may overlap. + // First copy the entire string to the location of the prefix, and then move the suffix + // to make room for the new chars that the caller wants to insert. + uprv_memmove2(oldChars + newZero, oldChars + oldZero, sizeof(char16_t) * fLength); + uprv_memmove2(oldChars + newZero + index + count, + oldChars + newZero + index, + sizeof(char16_t) * (fLength - index)); + uprv_memmove2(oldFields + newZero, oldFields + oldZero, sizeof(Field) * fLength); + uprv_memmove2(oldFields + newZero + index + count, + oldFields + newZero + index, + sizeof(Field) * (fLength - index)); + + fZero = newZero; + fLength += count; + } + return fZero + index; +} + +int32_t FormattedStringBuilder::remove(int32_t index, int32_t count) { + // TODO: Reset the heap here? (If the string after removal can fit on stack?) + int32_t position = index + fZero; + uprv_memmove2(getCharPtr() + position, + getCharPtr() + position + count, + sizeof(char16_t) * (fLength - index - count)); + uprv_memmove2(getFieldPtr() + position, + getFieldPtr() + position + count, + sizeof(Field) * (fLength - index - count)); + fLength -= count; + return position; +} + +UnicodeString FormattedStringBuilder::toUnicodeString() const { + return UnicodeString(getCharPtr() + fZero, fLength); +} + +const UnicodeString FormattedStringBuilder::toTempUnicodeString() const { + // Readonly-alias constructor: + return UnicodeString(FALSE, getCharPtr() + fZero, fLength); +} + +UnicodeString FormattedStringBuilder::toDebugString() const { + UnicodeString sb; + sb.append(u"", -1); + return sb; +} + +const char16_t *FormattedStringBuilder::chars() const { + return getCharPtr() + fZero; +} + +bool FormattedStringBuilder::contentEquals(const FormattedStringBuilder &other) const { + if (fLength != other.fLength) { + return false; + } + for (int32_t i = 0; i < fLength; i++) { + if (charAt(i) != other.charAt(i) || fieldAt(i) != other.fieldAt(i)) { + return false; + } + } + return true; +} + +bool FormattedStringBuilder::containsField(Field field) const { + for (int32_t i = 0; i < fLength; i++) { + if (field == fieldAt(i)) { + return true; + } + } + return false; +} + +U_NAMESPACE_END + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/formatted_string_builder.h icu-65.1/source/i18n/formatted_string_builder.h --- icu-64.2/source/i18n/formatted_string_builder.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/formatted_string_builder.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,253 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#ifndef __NUMBER_STRINGBUILDER_H__ +#define __NUMBER_STRINGBUILDER_H__ + + +#include +#include "unicode/unum.h" // for UNUM_FIELD_COUNT +#include "cstring.h" +#include "uassert.h" +#include "fphdlimp.h" + +U_NAMESPACE_BEGIN + +class FormattedValueStringBuilderImpl; + +/** + * A StringBuilder optimized for formatting. It implements the following key + * features beyond a UnicodeString: + * + *
      + *
    1. Efficient prepend as well as append. + *
    2. Keeps tracks of Fields in an efficient manner. + *
    + * + * See also FormattedValueStringBuilderImpl. + * + * @author sffc (Shane Carr) + */ +class U_I18N_API FormattedStringBuilder : public UMemory { + private: + static const int32_t DEFAULT_CAPACITY = 40; + + template + union ValueOrHeapArray { + T value[DEFAULT_CAPACITY]; + struct { + T *ptr; + int32_t capacity; + } heap; + }; + + public: + FormattedStringBuilder(); + + ~FormattedStringBuilder(); + + FormattedStringBuilder(const FormattedStringBuilder &other); + + // Convention: bottom 4 bits for field, top 4 bits for field category. + // Field category 0 implies the number category so that the number field + // literals can be directly passed as a Field type. + // See the helper functions in "StringBuilderFieldUtils" below. + typedef uint8_t Field; + + FormattedStringBuilder &operator=(const FormattedStringBuilder &other); + + int32_t length() const; + + int32_t codePointCount() const; + + inline char16_t charAt(int32_t index) const { + U_ASSERT(index >= 0); + U_ASSERT(index < fLength); + return getCharPtr()[fZero + index]; + } + + inline Field fieldAt(int32_t index) const { + U_ASSERT(index >= 0); + U_ASSERT(index < fLength); + return getFieldPtr()[fZero + index]; + } + + UChar32 getFirstCodePoint() const; + + UChar32 getLastCodePoint() const; + + UChar32 codePointAt(int32_t index) const; + + UChar32 codePointBefore(int32_t index) const; + + FormattedStringBuilder &clear(); + + /** Appends a UTF-16 code unit. */ + inline int32_t appendChar16(char16_t codeUnit, Field field, UErrorCode& status) { + // appendCodePoint handles both code units and code points. + return insertCodePoint(fLength, codeUnit, field, status); + } + + /** Inserts a UTF-16 code unit. Note: insert at index 0 is very efficient. */ + inline int32_t insertChar16(int32_t index, char16_t codeUnit, Field field, UErrorCode& status) { + // insertCodePoint handles both code units and code points. + return insertCodePoint(index, codeUnit, field, status); + } + + /** Appends a Unicode code point. */ + inline int32_t appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status) { + return insertCodePoint(fLength, codePoint, field, status); + } + + /** Inserts a Unicode code point. Note: insert at index 0 is very efficient. */ + int32_t insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status); + + /** Appends a string. */ + inline int32_t append(const UnicodeString &unistr, Field field, UErrorCode &status) { + return insert(fLength, unistr, field, status); + } + + /** Inserts a string. Note: insert at index 0 is very efficient. */ + int32_t insert(int32_t index, const UnicodeString &unistr, Field field, UErrorCode &status); + + /** Inserts a substring. Note: insert at index 0 is very efficient. + * + * @param start Start index of the substring of unistr to be inserted. + * @param end End index of the substring of unistr to be inserted (exclusive). + */ + int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field, + UErrorCode &status); + + /** Deletes a substring and then inserts a string at that same position. + * Similar to JavaScript Array.prototype.splice(). + * + * @param startThis Start of the span to delete. + * @param endThis End of the span to delete (exclusive). + * @param unistr The string to insert at the deletion position. + * @param startOther Start index of the substring of unistr to be inserted. + * @param endOther End index of the substring of unistr to be inserted (exclusive). + */ + int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr, + int32_t startOther, int32_t endOther, Field field, UErrorCode& status); + + /** Appends a formatted string. */ + int32_t append(const FormattedStringBuilder &other, UErrorCode &status); + + /** Inserts a formatted string. Note: insert at index 0 is very efficient. */ + int32_t insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status); + + /** + * Ensures that the string buffer contains a NUL terminator. The NUL terminator does + * not count toward the string length. Any further changes to the string (insert or + * append) may invalidate the NUL terminator. + * + * You should call this method after the formatted string is completely built if you + * plan to return a pointer to the string from a C API. + */ + void writeTerminator(UErrorCode& status); + + /** + * Gets a "safe" UnicodeString that can be used even after the FormattedStringBuilder is destructed. + */ + UnicodeString toUnicodeString() const; + + /** + * Gets an "unsafe" UnicodeString that is valid only as long as the FormattedStringBuilder is alive and + * unchanged. Slightly faster than toUnicodeString(). + */ + const UnicodeString toTempUnicodeString() const; + + UnicodeString toDebugString() const; + + const char16_t *chars() const; + + bool contentEquals(const FormattedStringBuilder &other) const; + + bool containsField(Field field) const; + + private: + bool fUsingHeap = false; + ValueOrHeapArray fChars; + ValueOrHeapArray fFields; + int32_t fZero = DEFAULT_CAPACITY / 2; + int32_t fLength = 0; + + inline char16_t *getCharPtr() { + return fUsingHeap ? fChars.heap.ptr : fChars.value; + } + + inline const char16_t *getCharPtr() const { + return fUsingHeap ? fChars.heap.ptr : fChars.value; + } + + inline Field *getFieldPtr() { + return fUsingHeap ? fFields.heap.ptr : fFields.value; + } + + inline const Field *getFieldPtr() const { + return fUsingHeap ? fFields.heap.ptr : fFields.value; + } + + inline int32_t getCapacity() const { + return fUsingHeap ? fChars.heap.capacity : DEFAULT_CAPACITY; + } + + int32_t prepareForInsert(int32_t index, int32_t count, UErrorCode &status); + + int32_t prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status); + + int32_t remove(int32_t index, int32_t count); + + friend class FormattedValueStringBuilderImpl; +}; + +/** + * Helper functions for dealing with the Field typedef, which stores fields + * in a compressed format. + */ +class StringBuilderFieldUtils { +public: + struct CategoryFieldPair { + int32_t category; + int32_t field; + }; + + /** Compile-time function to construct a Field from a category and a field */ + template + static constexpr FormattedStringBuilder::Field compress() { + static_assert(category != 0, "cannot use Undefined category in FieldUtils"); + static_assert(category <= 0xf, "only 4 bits for category"); + static_assert(field <= 0xf, "only 4 bits for field"); + return static_cast((category << 4) | field); + } + + /** Runtime inline function to unpack the category and field from the Field */ + static inline CategoryFieldPair expand(FormattedStringBuilder::Field field) { + if (field == UNUM_FIELD_COUNT) { + return {UFIELD_CATEGORY_UNDEFINED, 0}; + } + CategoryFieldPair ret = { + (field >> 4), + (field & 0xf) + }; + if (ret.category == 0) { + ret.category = UFIELD_CATEGORY_NUMBER; + } + return ret; + } + + static inline bool isNumericField(FormattedStringBuilder::Field field) { + int8_t category = field >> 4; + return category == 0 || category == UFIELD_CATEGORY_NUMBER; + } +}; + +U_NAMESPACE_END + + +#endif //__NUMBER_STRINGBUILDER_H__ + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/formattedval_impl.h icu-65.1/source/i18n/formattedval_impl.h --- icu-64.2/source/i18n/formattedval_impl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/formattedval_impl.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,7 +18,7 @@ #include "fphdlimp.h" #include "util.h" #include "uvectr32.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" /** @@ -67,7 +67,9 @@ U_NAMESPACE_BEGIN -/** Implementation using FieldPositionHandler to accept fields. */ +/** + * Implementation of FormattedValue using FieldPositionHandler to accept fields. + */ class FormattedValueFieldPositionIteratorImpl : public UMemory, public FormattedValue { public: @@ -112,12 +114,21 @@ }; -class FormattedValueNumberStringBuilderImpl : public UMemory, public FormattedValue { +/** + * Implementation of FormattedValue based on FormattedStringBuilder. + * + * The implementation currently revolves around numbers and number fields. + * However, it can be generalized in the future when there is a need. + * + * @author sffc (Shane Carr) + */ +// Exported as U_I18N_API for tests +class U_I18N_API FormattedValueStringBuilderImpl : public UMemory, public FormattedValue { public: - FormattedValueNumberStringBuilderImpl(number::impl::Field numericField); + FormattedValueStringBuilderImpl(FormattedStringBuilder::Field numericField); - virtual ~FormattedValueNumberStringBuilderImpl(); + virtual ~FormattedValueStringBuilderImpl(); // Implementation of FormattedValue (const): @@ -126,17 +137,25 @@ Appendable& appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE; UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; - inline number::impl::NumberStringBuilder& getStringRef() { + // Additional helper functions: + UBool nextFieldPosition(FieldPosition& fp, UErrorCode& status) const; + void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; + inline FormattedStringBuilder& getStringRef() { return fString; } - - inline const number::impl::NumberStringBuilder& getStringRef() const { + inline const FormattedStringBuilder& getStringRef() const { return fString; } private: - number::impl::NumberStringBuilder fString; - number::impl::Field fNumericField; + FormattedStringBuilder fString; + FormattedStringBuilder::Field fNumericField; + + bool nextPositionImpl(ConstrainedFieldPosition& cfpos, FormattedStringBuilder::Field numericField, UErrorCode& status) const; + static bool isIntOrGroup(FormattedStringBuilder::Field field); + static bool isNumericField(FormattedStringBuilder::Field field); + int32_t trimBack(int32_t limit) const; + int32_t trimFront(int32_t start) const; }; diff -Nru icu-64.2/source/i18n/formattedval_sbimpl.cpp icu-65.1/source/i18n/formattedval_sbimpl.cpp --- icu-64.2/source/i18n/formattedval_sbimpl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/formattedval_sbimpl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -9,35 +9,203 @@ // Other independent implementations should go into their own cpp file for // better dependency modularization. +#include "unicode/ustring.h" #include "formattedval_impl.h" +#include "number_types.h" +#include "formatted_string_builder.h" +#include "number_utils.h" +#include "static_unicode_sets.h" U_NAMESPACE_BEGIN -FormattedValueNumberStringBuilderImpl::FormattedValueNumberStringBuilderImpl(number::impl::Field numericField) +typedef FormattedStringBuilder::Field Field; + + +FormattedValueStringBuilderImpl::FormattedValueStringBuilderImpl(Field numericField) : fNumericField(numericField) { } -FormattedValueNumberStringBuilderImpl::~FormattedValueNumberStringBuilderImpl() { +FormattedValueStringBuilderImpl::~FormattedValueStringBuilderImpl() { } -UnicodeString FormattedValueNumberStringBuilderImpl::toString(UErrorCode&) const { +UnicodeString FormattedValueStringBuilderImpl::toString(UErrorCode&) const { return fString.toUnicodeString(); } -UnicodeString FormattedValueNumberStringBuilderImpl::toTempString(UErrorCode&) const { +UnicodeString FormattedValueStringBuilderImpl::toTempString(UErrorCode&) const { return fString.toTempUnicodeString(); } -Appendable& FormattedValueNumberStringBuilderImpl::appendTo(Appendable& appendable, UErrorCode&) const { +Appendable& FormattedValueStringBuilderImpl::appendTo(Appendable& appendable, UErrorCode&) const { appendable.appendString(fString.chars(), fString.length()); return appendable; } -UBool FormattedValueNumberStringBuilderImpl::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const { +UBool FormattedValueStringBuilderImpl::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const { // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool - return fString.nextPosition(cfpos, fNumericField, status) ? TRUE : FALSE; + return nextPositionImpl(cfpos, fNumericField, status) ? TRUE : FALSE; +} + +UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErrorCode& status) const { + int32_t rawField = fp.getField(); + + if (rawField == FieldPosition::DONT_CARE) { + return FALSE; + } + + if (rawField < 0 || rawField >= UNUM_FIELD_COUNT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + + ConstrainedFieldPosition cfpos; + cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField); + cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex()); + if (nextPositionImpl(cfpos, 0, status)) { + fp.setBeginIndex(cfpos.getStart()); + fp.setEndIndex(cfpos.getLimit()); + return TRUE; + } + + // Special case: fraction should start after integer if fraction is not present + if (rawField == UNUM_FRACTION_FIELD && fp.getEndIndex() == 0) { + bool inside = false; + int32_t i = fString.fZero; + for (; i < fString.fZero + fString.fLength; i++) { + if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == UNUM_DECIMAL_SEPARATOR_FIELD) { + inside = true; + } else if (inside) { + break; + } + } + fp.setBeginIndex(i - fString.fZero); + fp.setEndIndex(i - fString.fZero); + } + + return FALSE; +} + +void FormattedValueStringBuilderImpl::getAllFieldPositions(FieldPositionIteratorHandler& fpih, + UErrorCode& status) const { + ConstrainedFieldPosition cfpos; + while (nextPositionImpl(cfpos, 0, status)) { + fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit()); + } +} + +// Signal the end of the string using a field that doesn't exist and that is +// different from UNUM_FIELD_COUNT, which is used for "null number field". +static constexpr Field kEndField = 0xff; + +bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const { + auto numericCAF = StringBuilderFieldUtils::expand(numericField); + int32_t fieldStart = -1; + Field currField = UNUM_FIELD_COUNT; + for (int32_t i = fString.fZero + cfpos.getLimit(); i <= fString.fZero + fString.fLength; i++) { + Field _field = (i < fString.fZero + fString.fLength) ? fString.getFieldPtr()[i] : kEndField; + // Case 1: currently scanning a field. + if (currField != UNUM_FIELD_COUNT) { + if (currField != _field) { + int32_t end = i - fString.fZero; + // Grouping separators can be whitespace; don't throw them out! + if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { + end = trimBack(i - fString.fZero); + } + if (end <= fieldStart) { + // Entire field position is ignorable; skip. + fieldStart = -1; + currField = UNUM_FIELD_COUNT; + i--; // look at this index again + continue; + } + int32_t start = fieldStart; + if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { + start = trimFront(start); + } + auto caf = StringBuilderFieldUtils::expand(currField); + cfpos.setState(caf.category, caf.field, start, end); + return true; + } + continue; + } + // Special case: coalesce the INTEGER if we are pointing at the end of the INTEGER. + if (cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD) + && i > fString.fZero + // don't return the same field twice in a row: + && i - fString.fZero > cfpos.getLimit() + && isIntOrGroup(fString.getFieldPtr()[i - 1]) + && !isIntOrGroup(_field)) { + int j = i - 1; + for (; j >= fString.fZero && isIntOrGroup(fString.getFieldPtr()[j]); j--) {} + cfpos.setState( + UFIELD_CATEGORY_NUMBER, + UNUM_INTEGER_FIELD, + j - fString.fZero + 1, + i - fString.fZero); + return true; + } + // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC. + if (numericField != 0 + && cfpos.matchesField(numericCAF.category, numericCAF.field) + && i > fString.fZero + // don't return the same field twice in a row: + && (i - fString.fZero > cfpos.getLimit() + || cfpos.getCategory() != numericCAF.category + || cfpos.getField() != numericCAF.field) + && isNumericField(fString.getFieldPtr()[i - 1]) + && !isNumericField(_field)) { + int j = i - 1; + for (; j >= fString.fZero && isNumericField(fString.getFieldPtr()[j]); j--) {} + cfpos.setState( + numericCAF.category, + numericCAF.field, + j - fString.fZero + 1, + i - fString.fZero); + return true; + } + // Special case: skip over INTEGER; will be coalesced later. + if (_field == UNUM_INTEGER_FIELD) { + _field = UNUM_FIELD_COUNT; + } + // Case 2: no field starting at this position. + if (_field == UNUM_FIELD_COUNT || _field == kEndField) { + continue; + } + // Case 3: check for field starting at this position + auto caf = StringBuilderFieldUtils::expand(_field); + if (cfpos.matchesField(caf.category, caf.field)) { + fieldStart = i - fString.fZero; + currField = _field; + } + } + + U_ASSERT(currField == UNUM_FIELD_COUNT); + return false; +} + +bool FormattedValueStringBuilderImpl::isIntOrGroup(Field field) { + return field == UNUM_INTEGER_FIELD + || field == UNUM_GROUPING_SEPARATOR_FIELD; +} + +bool FormattedValueStringBuilderImpl::isNumericField(Field field) { + return StringBuilderFieldUtils::isNumericField(field); +} + +int32_t FormattedValueStringBuilderImpl::trimBack(int32_t limit) const { + return unisets::get(unisets::DEFAULT_IGNORABLES)->spanBack( + fString.getCharPtr() + fString.fZero, + limit, + USET_SPAN_CONTAINED); +} + +int32_t FormattedValueStringBuilderImpl::trimFront(int32_t start) const { + return start + unisets::get(unisets::DEFAULT_IGNORABLES)->span( + fString.getCharPtr() + fString.fZero + start, + fString.fLength - start, + USET_SPAN_CONTAINED); } diff -Nru icu-64.2/source/i18n/funcrepl.cpp icu-65.1/source/i18n/funcrepl.cpp --- icu-64.2/source/i18n/funcrepl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/funcrepl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -59,7 +59,7 @@ /** * Implement UnicodeFunctor */ -UnicodeFunctor* FunctionReplacer::clone() const { +FunctionReplacer* FunctionReplacer::clone() const { return new FunctionReplacer(*this); } diff -Nru icu-64.2/source/i18n/funcrepl.h icu-65.1/source/i18n/funcrepl.h --- icu-64.2/source/i18n/funcrepl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/funcrepl.h 2019-10-03 11:16:41.000000000 +0000 @@ -70,7 +70,7 @@ /** * Implement UnicodeFunctor */ - virtual UnicodeFunctor* clone() const; + virtual FunctionReplacer* clone() const; /** * UnicodeFunctor API. Cast 'this' to a UnicodeReplacer* pointer diff -Nru icu-64.2/source/i18n/gender.cpp icu-65.1/source/i18n/gender.cpp --- icu-64.2/source/i18n/gender.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/gender.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -98,7 +98,7 @@ return NULL; } - static UMutex gGenderMetaLock = U_MUTEX_INITIALIZER; + static UMutex gGenderMetaLock; const GenderInfo* result = NULL; const char* key = locale.getName(); { diff -Nru icu-64.2/source/i18n/gregocal.cpp icu-65.1/source/i18n/gregocal.cpp --- icu-64.2/source/i18n/gregocal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/gregocal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -286,7 +286,7 @@ // ------------------------------------- -Calendar* GregorianCalendar::clone() const +GregorianCalendar* GregorianCalendar::clone() const { return new GregorianCalendar(*this); } @@ -324,26 +324,26 @@ if (U_FAILURE(status)) return; - fGregorianCutover = date; - // Precompute two internal variables which we use to do the actual // cutover computations. These are the normalized cutover, which is the // midnight at or before the cutover, and the cutover year. The // normalized cutover is in pure date milliseconds; it contains no time // of day or timezone component, and it used to compare against other // pure date values. - int32_t cutoverDay = (int32_t)ClockMath::floorDivide(fGregorianCutover, (double)kOneDay); - fNormalizedGregorianCutover = cutoverDay * kOneDay; + double cutoverDay = ClockMath::floorDivide(date, (double)kOneDay); - // Handle the rare case of numeric overflow. If the user specifies a - // change of UDate(Long.MIN_VALUE), in order to get a pure Gregorian - // calendar, then the epoch day is -106751991168, which when multiplied - // by ONE_DAY gives 9223372036794351616 -- the negative value is too - // large for 64 bits, and overflows into a positive value. We correct - // this by using the next day, which for all intents is semantically - // equivalent. - if (cutoverDay < 0 && fNormalizedGregorianCutover > 0) { - fNormalizedGregorianCutover = (cutoverDay + 1) * kOneDay; + // Handle the rare case of numeric overflow where the user specifies a time + // outside of INT32_MIN .. INT32_MAX number of days. + + if (cutoverDay <= INT32_MIN) { + cutoverDay = INT32_MIN; + fGregorianCutover = fNormalizedGregorianCutover = cutoverDay * kOneDay; + } else if (cutoverDay >= INT32_MAX) { + cutoverDay = INT32_MAX; + fGregorianCutover = fNormalizedGregorianCutover = cutoverDay * kOneDay; + } else { + fNormalizedGregorianCutover = cutoverDay * kOneDay; + fGregorianCutover = date; } // Normalize the year so BC values are represented as 0 and negative @@ -360,7 +360,7 @@ fGregorianCutoverYear = cal->get(UCAL_YEAR, status); if (cal->get(UCAL_ERA, status) == BC) fGregorianCutoverYear = 1 - fGregorianCutoverYear; - fCutoverJulianDay = cutoverDay; + fCutoverJulianDay = (int32_t)cutoverDay; delete cal; } diff -Nru icu-64.2/source/i18n/hebrwcal.cpp icu-65.1/source/i18n/hebrwcal.cpp --- icu-64.2/source/i18n/hebrwcal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/hebrwcal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -169,7 +169,7 @@ return "hebrew"; } -Calendar* HebrewCalendar::clone() const { +HebrewCalendar* HebrewCalendar::clone() const { return new HebrewCalendar(*this); } diff -Nru icu-64.2/source/i18n/hebrwcal.h icu-65.1/source/i18n/hebrwcal.h --- icu-64.2/source/i18n/hebrwcal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/hebrwcal.h 2019-10-03 11:16:41.000000000 +0000 @@ -192,7 +192,7 @@ * @return return a polymorphic copy of this calendar. * @internal */ - virtual Calendar* clone(void) const; + virtual HebrewCalendar* clone() const; public: /** diff -Nru icu-64.2/source/i18n/i18n_uwp.vcxproj icu-65.1/source/i18n/i18n_uwp.vcxproj --- icu-64.2/source/i18n/i18n_uwp.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/i18n_uwp.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,10 @@ Debug ARM + + Debug + ARM64 + Release Win32 @@ -25,6 +29,10 @@ Release ARM + + Release + ARM64 +
    {6786C051-383B-47E0-9E82-B8B994E06A25} @@ -51,20 +59,14 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\ReleaseUWP\ - .\x86\ReleaseUWP\ - .\x86\DebugUWP\ - .\x86\DebugUWP\ - .\x64\ReleaseUWP\ - .\x64\ReleaseUWP\ - .\x64\DebugUWP\ - .\x64\DebugUWP\ - .\arm\ReleaseUWP\ - .\arm\ReleaseUWP\ - .\arm\DebugUWP\ - .\arm\DebugUWP\ - false + .\$(Platform)\$(Configuration)UWP\ + .\$(Platform)\$(Configuration)UWP\ + + .\x86\$(Configuration)UWP\ + .\x86\$(Configuration)UWP\ + true + false @@ -88,6 +90,7 @@ NotUsing false /utf-8 %(AdditionalOptions) + ProgramDatabase 0x0409 @@ -127,7 +130,6 @@ Disabled EnableFastChecks true - EditAndContinue _DEBUG;%(PreprocessorDefinitions) @@ -166,6 +168,17 @@ MachineARM + + + ARM64 + + + ARM64;WIN32;%(PreprocessorDefinitions) + + + MachineARM64 + + .\..\..\lib32uwp\icuin.tlb @@ -177,7 +190,7 @@ .\x86\ReleaseUWP/ - ..\..\bin32uwp\icuin64.dll + ..\..\bin32uwp\icuin65.dll .\..\..\lib32uwp\icuin.pdb ..\..\lib32uwp\icuin.lib ..\..\lib32uwp\icuuc.lib;%(AdditionalDependencies) @@ -194,7 +207,7 @@ .\x86\DebugUWP/ - ..\..\bin32uwp\icuin64d.dll + ..\..\bin32uwp\icuin65d.dll .\..\..\lib32uwp\icuind.pdb ..\..\lib32uwp\icuind.lib ..\..\lib32uwp\icuucd.lib;%(AdditionalDependencies) @@ -211,7 +224,7 @@ .\x64\ReleaseUWP/ - ..\..\bin64uwp\icuin64.dll + ..\..\bin64uwp\icuin65.dll .\..\..\lib64uwp\icuin.pdb ..\..\lib64uwp\icuin.lib ..\..\lib64uwp\icuuc.lib;%(AdditionalDependencies) @@ -228,7 +241,7 @@ .\x64\DebugUWP/ - ..\..\bin64uwp\icuin64d.dll + ..\..\bin64uwp\icuin65d.dll .\..\..\lib64uwp\icuind.pdb ..\..\lib64uwp\icuind.lib ..\..\lib64uwp\icuucd.lib;%(AdditionalDependencies) @@ -245,7 +258,7 @@ .\ARM\ReleaseUWP/ - ..\..\binARMuwp\icuin64.dll + ..\..\binARMuwp\icuin65.dll .\..\..\libARMuwp\icuin.pdb ..\..\libARMuwp\icuin.lib ..\..\libARMuwp\icuuc.lib;%(AdditionalDependencies) @@ -262,12 +275,46 @@ .\ARM\DebugUWP/ - ..\..\binARMuwp\icuin64d.dll + ..\..\binARMuwp\icuin65d.dll .\..\..\libARMuwp\icuind.pdb ..\..\libARMuwp\icuind.lib ..\..\libARMuwp\icuucd.lib;%(AdditionalDependencies) + + + .\..\..\libARM64uwp\icuin.tlb + + + .\ARM64\ReleaseUWP/i18n.pch + .\ARM64\ReleaseUWP/ + .\ARM64\ReleaseUWP/ + .\ARM64\ReleaseUWP/ + + + ..\..\binARM64uwp\icuin65.dll + .\..\..\libARM64uwp\icuin.pdb + ..\..\libARM64uwp\icuin.lib + ..\..\libARM64uwp\icuuc.lib;%(AdditionalDependencies) + + + + + .\..\..\libARM64uwp\icuind.tlb + + + .\ARM64\DebugUWP/i18n.pch + .\ARM64\DebugUWP/ + .\ARM64\DebugUWP/ + .\ARM64\DebugUWP/ + + + ..\..\binARM64uwp\icuin65d.dll + .\..\..\libARM64uwp\icuind.pdb + ..\..\libARM64uwp\icuind.lib + ..\..\libARM64uwp\icuucd.lib;%(AdditionalDependencies) + + @@ -332,10 +379,10 @@ - + + - @@ -385,14 +432,14 @@ - + - + @@ -547,8 +594,11 @@ + + + @@ -646,7 +696,7 @@ - + @@ -654,7 +704,7 @@ - + diff -Nru icu-64.2/source/i18n/i18n.vcxproj icu-65.1/source/i18n/i18n.vcxproj --- icu-64.2/source/i18n/i18n.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/i18n.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -35,33 +35,37 @@ <_ProjectFileVersion>10.0.30319.1 - .\..\..\lib\ - .\x86\Release\ - false - .\..\..\lib\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false + + $(OutDir)\icuin.tlb + U_ATTRIBUTE_DEPRECATED=;U_I18N_IMPLEMENTATION;%(PreprocessorDefinitions) false Level3 ..\..\include;..\common;%(AdditionalIncludeDirectories) Default + ProgramDatabase + $(OutDir)/icuin.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/icuin.pdb ../common;%(AdditionalIncludeDirectories) - 0x4a900000 + .\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) @@ -72,6 +76,9 @@ icuucd.lib;%(AdditionalDependencies) + ..\..\$(IcuBinOutputDir)\icuin65d.dll + .\..\..\$(IcuLibOutputDir)\icuind.pdb + ..\..\$(IcuLibOutputDir)\icuind.lib
    @@ -82,83 +89,9 @@ icuuc.lib;%(AdditionalDependencies) - -
    - - - .\..\..\lib\icuin.tlb - - - .\x86\Release/i18n.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - - - ..\..\bin\icuin64.dll - .\..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\lib\icuin.pdb - false - - - ..\..\lib\icuin.lib - - - - - .\..\..\lib\icuind.tlb - - - .\x86\Debug/i18n.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true - EditAndContinue - - - ..\..\bin\icuin64d.dll - .\..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\lib\icuind.pdb - false - - - ..\..\lib\icuind.lib - - - - - .\..\..\lib64\icuin.tlb - - - .\x64\Release/i18n.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - - - ..\..\bin64\icuin64.dll - .\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\lib64\icuin.pdb - ..\..\lib64\icuin.lib - - - - - .\..\..\lib64\icuind.tlb - - - .\x64\Debug/i18n.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - ProgramDatabase - - - ..\..\bin64\icuin64d.dll - .\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\lib64\icuind.pdb - ..\..\lib64\icuind.lib + ..\..\$(IcuBinOutputDir)\icuin65.dll + .\..\..\$(IcuLibOutputDir)\icuin.pdb + ..\..\$(IcuLibOutputDir)\icuin.lib @@ -225,10 +158,10 @@ - + + - @@ -278,14 +211,14 @@ - + - + @@ -442,8 +375,11 @@ + + + @@ -541,7 +477,7 @@ - + @@ -549,7 +485,7 @@ - + diff -Nru icu-64.2/source/i18n/i18n.vcxproj.filters icu-65.1/source/i18n/i18n.vcxproj.filters --- icu-64.2/source/i18n/i18n.vcxproj.filters 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/i18n.vcxproj.filters 2019-10-03 11:16:41.000000000 +0000 @@ -117,16 +117,16 @@ formatting - + formatting formatting - + formatting - + formatting @@ -585,7 +585,7 @@ formatting - + formatting @@ -606,7 +606,7 @@ formatting - + formatting @@ -776,6 +776,9 @@ formatting + + formatting + formatting @@ -785,6 +788,12 @@ formatting + + formatting + + + formatting + formatting @@ -878,7 +887,7 @@ formatting - + formatting @@ -902,7 +911,7 @@ formatting - + formatting diff -Nru icu-64.2/source/i18n/indiancal.cpp icu-65.1/source/i18n/indiancal.cpp --- icu-64.2/source/i18n/indiancal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/indiancal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -35,7 +35,7 @@ //------------------------------------------------------------------------- -Calendar* IndianCalendar::clone() const { +IndianCalendar* IndianCalendar::clone() const { return new IndianCalendar(*this); } diff -Nru icu-64.2/source/i18n/indiancal.h icu-65.1/source/i18n/indiancal.h --- icu-64.2/source/i18n/indiancal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/indiancal.h 2019-10-03 11:16:41.000000000 +0000 @@ -186,7 +186,7 @@ // TODO: copy c'tor, etc // clone - virtual Calendar* clone() const; + virtual IndianCalendar* clone() const; private: /** diff -Nru icu-64.2/source/i18n/islamcal.cpp icu-65.1/source/i18n/islamcal.cpp --- icu-64.2/source/i18n/islamcal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/islamcal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -227,7 +227,7 @@ return sType; } -Calendar* IslamicCalendar::clone() const { +IslamicCalendar* IslamicCalendar::clone() const { return new IslamicCalendar(*this); } @@ -470,7 +470,7 @@ { double age = 0; - static UMutex astroLock = U_MUTEX_INITIALIZER; // pod bay door lock + static UMutex astroLock; // pod bay door lock umtx_lock(&astroLock); if(gIslamicCalendarAstro == NULL) { gIslamicCalendarAstro = new CalendarAstronomer(); diff -Nru icu-64.2/source/i18n/islamcal.h icu-65.1/source/i18n/islamcal.h --- icu-64.2/source/i18n/islamcal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/islamcal.h 2019-10-03 11:16:41.000000000 +0000 @@ -230,7 +230,7 @@ // TODO: copy c'tor, etc // clone - virtual Calendar* clone() const; + virtual IslamicCalendar* clone() const; private: /** diff -Nru icu-64.2/source/i18n/japancal.cpp icu-65.1/source/i18n/japancal.cpp --- icu-64.2/source/i18n/japancal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/japancal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -136,7 +136,7 @@ return *this; } -Calendar* JapaneseCalendar::clone(void) const +JapaneseCalendar* JapaneseCalendar::clone() const { return new JapaneseCalendar(*this); } diff -Nru icu-64.2/source/i18n/japancal.h icu-65.1/source/i18n/japancal.h --- icu-64.2/source/i18n/japancal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/japancal.h 2019-10-03 11:16:41.000000000 +0000 @@ -116,7 +116,7 @@ * @return return a polymorphic copy of this calendar. * @internal */ - virtual Calendar* clone(void) const; + virtual JapaneseCalendar* clone() const; /** * Return the extended year defined by the current fields. In the diff -Nru icu-64.2/source/i18n/listformatter.cpp icu-65.1/source/i18n/listformatter.cpp --- icu-64.2/source/i18n/listformatter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/listformatter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -144,7 +144,7 @@ keyBuffer.append(':', errorCode).append(style, errorCode); UnicodeString key(keyBuffer.data(), -1, US_INV); ListFormatInternal* result = nullptr; - static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; + static UMutex listFormatterMutex; { Mutex m(&listFormatterMutex); if (listPatternHash == nullptr) { @@ -478,8 +478,8 @@ if (index == 0) { offset = 0; } - int32_t offsetFirst; - int32_t offsetSecond; + int32_t offsetFirst = 0; + int32_t offsetSecond = 0; int32_t prefixLength = 0; // for n items, there are 2 * (n + 1) boundary including 0 and the upper // edge. diff -Nru icu-64.2/source/i18n/Makefile.in icu-65.1/source/i18n/Makefile.in --- icu-64.2/source/i18n/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -103,16 +103,18 @@ number_decimfmtprops.o number_fluent.o number_formatimpl.o number_grouping.o \ number_integerwidth.o number_longnames.o number_modifiers.o number_notation.o number_output.o \ number_padding.o number_patternmodifier.o number_patternstring.o \ -number_rounding.o number_scientific.o number_stringbuilder.o number_utils.o number_asformat.o \ +number_rounding.o number_scientific.o number_utils.o number_asformat.o \ number_mapper.o number_multiplier.o number_currencysymbols.o number_skeletons.o number_capi.o \ -double-conversion.o double-conversion-bignum-dtoa.o double-conversion-bignum.o \ -double-conversion-cached-powers.o double-conversion-diy-fp.o \ +double-conversion-string-to-double.o double-conversion-double-to-string.o \ +double-conversion-bignum-dtoa.o double-conversion-bignum.o \ +double-conversion-cached-powers.o \ double-conversion-fast-dtoa.o double-conversion-strtod.o \ -numparse_stringsegment.o numparse_parsednumber.o numparse_impl.o \ +string_segment.o numparse_parsednumber.o numparse_impl.o \ numparse_symbols.o numparse_decimal.o numparse_scientific.o numparse_currency.o \ numparse_affixes.o numparse_compositions.o numparse_validators.o \ numrange_fluent.o numrange_impl.o \ -erarules.o formattedvalue.o formattedval_iterimpl.o formattedval_sbimpl.o +erarules.o \ +formattedvalue.o formattedval_iterimpl.o formattedval_sbimpl.o formatted_string_builder.o ## Header files to install HEADERS = $(srcdir)/unicode/*.h diff -Nru icu-64.2/source/i18n/measfmt.cpp icu-65.1/source/i18n/measfmt.cpp --- icu-64.2/source/i18n/measfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/measfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -55,28 +55,23 @@ class NumericDateFormatters : public UMemory { public: // Formats like H:mm - SimpleDateFormat hourMinute; + UnicodeString hourMinute; // formats like M:ss - SimpleDateFormat minuteSecond; + UnicodeString minuteSecond; // formats like H:mm:ss - SimpleDateFormat hourMinuteSecond; + UnicodeString hourMinuteSecond; // Constructor that takes the actual patterns for hour-minute, // minute-second, and hour-minute-second respectively. NumericDateFormatters( const UnicodeString &hm, const UnicodeString &ms, - const UnicodeString &hms, - UErrorCode &status) : - hourMinute(hm, status), - minuteSecond(ms, status), - hourMinuteSecond(hms, status) { - const TimeZone *gmt = TimeZone::getGMT(); - hourMinute.setTimeZone(*gmt); - minuteSecond.setTimeZone(*gmt); - hourMinuteSecond.setTimeZone(*gmt); + const UnicodeString &hms) : + hourMinute(hm), + minuteSecond(ms), + hourMinuteSecond(hms) { } private: NumericDateFormatters(const NumericDateFormatters &other); @@ -233,8 +228,7 @@ NumericDateFormatters *result = new NumericDateFormatters( loadNumericDateFormatterPattern(resource, "hm", status), loadNumericDateFormatterPattern(resource, "ms", status), - loadNumericDateFormatterPattern(resource, "hms", status), - status); + loadNumericDateFormatterPattern(resource, "hms", status)); if (U_FAILURE(status)) { delete result; return NULL; @@ -466,7 +460,7 @@ **numberFormat == **rhs.numberFormat); } -Format *MeasureFormat::clone() const { +MeasureFormat *MeasureFormat::clone() const { return new MeasureFormat(*this); } @@ -691,9 +685,19 @@ } auto* df = dynamic_cast(&nf); if (df == nullptr) { - // Don't know how to handle other types of NumberFormat - status = U_UNSUPPORTED_ERROR; - return appendTo; + // Handle other types of NumberFormat using the ICU 63 code, modified to + // get the unitPattern from LongNameHandler and handle fallback to OTHER. + UnicodeString formattedNumber; + StandardPlural::Form pluralForm = QuantityFormatter::selectPlural( + amtNumber, nf, **pluralRules, formattedNumber, pos, status); + UnicodeString pattern = number::impl::LongNameHandler::getUnitPattern(getLocale(status), + amtUnit, getUnitWidth(fWidth), pluralForm, status); + // The above handles fallback from other widths to short, and from other plural forms to OTHER + if (U_FAILURE(status)) { + return appendTo; + } + SimpleFormatter formatter(pattern, 0, 1, status); + return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status); } number::FormattedNumber result; if (auto* lnf = df->toNumberFormatter(status)) { @@ -706,135 +710,112 @@ return appendTo; } -// Formats hours-minutes-seconds as 5:37:23 or similar. + +// Formats numeric time duration as 5:00:47 or 3:54. UnicodeString &MeasureFormat::formatNumeric( const Formattable *hms, // always length 3 - int32_t bitMap, // 1=hourset, 2=minuteset, 4=secondset + int32_t bitMap, // 1=hour set, 2=minute set, 4=second set UnicodeString &appendTo, UErrorCode &status) const { if (U_FAILURE(status)) { return appendTo; } - UDate millis = - (UDate) (((uprv_trunc(hms[0].getDouble(status)) * 60.0 - + uprv_trunc(hms[1].getDouble(status))) * 60.0 - + uprv_trunc(hms[2].getDouble(status))) * 1000.0); - switch (bitMap) { - case 5: // hs - case 7: // hms - return formatNumeric( - millis, - cache->getNumericDateFormatters()->hourMinuteSecond, - UDAT_SECOND_FIELD, - hms[2], - appendTo, - status); - break; - case 6: // ms - return formatNumeric( - millis, - cache->getNumericDateFormatters()->minuteSecond, - UDAT_SECOND_FIELD, - hms[2], - appendTo, - status); - break; - case 3: // hm - return formatNumeric( - millis, - cache->getNumericDateFormatters()->hourMinute, - UDAT_MINUTE_FIELD, - hms[1], - appendTo, - status); - break; - default: - status = U_INTERNAL_PROGRAM_ERROR; - return appendTo; - break; - } -} -static void appendRange( - const UnicodeString &src, - int32_t start, - int32_t end, - UnicodeString &dest) { - dest.append(src, start, end - start); -} + UnicodeString pattern; -static void appendRange( - const UnicodeString &src, - int32_t end, - UnicodeString &dest) { - dest.append(src, end, src.length() - end); -} - -// Formats time like 5:37:23 -UnicodeString &MeasureFormat::formatNumeric( - UDate date, // Time since epoch 1:30:00 would be 5400000 - const DateFormat &dateFmt, // h:mm, m:ss, or h:mm:ss - UDateFormatField smallestField, // seconds in 5:37:23.5 - const Formattable &smallestAmount, // 23.5 for 5:37:23.5 - UnicodeString &appendTo, - UErrorCode &status) const { + double hours = hms[0].getDouble(status); + double minutes = hms[1].getDouble(status); + double seconds = hms[2].getDouble(status); if (U_FAILURE(status)) { return appendTo; } - // Format the smallest amount with this object's NumberFormat - UnicodeString smallestAmountFormatted; - // We keep track of the integer part of smallest amount so that - // we can replace it later so that we get '0:00:09.3' instead of - // '0:00:9.3' - FieldPosition intFieldPosition(UNUM_INTEGER_FIELD); - (*numberFormat)->format( - smallestAmount, smallestAmountFormatted, intFieldPosition, status); - if ( - intFieldPosition.getBeginIndex() == 0 && - intFieldPosition.getEndIndex() == 0) { + // All possible combinations: "h", "m", "s", "hm", "hs", "ms", "hms" + if (bitMap == 5 || bitMap == 7) { // "hms" & "hs" (we add minutes if "hs") + pattern = cache->getNumericDateFormatters()->hourMinuteSecond; + hours = uprv_trunc(hours); + minutes = uprv_trunc(minutes); + } else if (bitMap == 3) { // "hm" + pattern = cache->getNumericDateFormatters()->hourMinute; + hours = uprv_trunc(hours); + } else if (bitMap == 6) { // "ms" + pattern = cache->getNumericDateFormatters()->minuteSecond; + minutes = uprv_trunc(minutes); + } else { // h m s, handled outside formatNumeric. No value is also an error. status = U_INTERNAL_PROGRAM_ERROR; return appendTo; } - // Format time. draft becomes something like '5:30:45' - // #13606: DateFormat is not thread-safe, but MeasureFormat advertises itself as thread-safe. - FieldPosition smallestFieldPosition(smallestField); - UnicodeString draft; - static UMutex dateFmtMutex = U_MUTEX_INITIALIZER; - umtx_lock(&dateFmtMutex); - dateFmt.format(date, draft, smallestFieldPosition, status); - umtx_unlock(&dateFmtMutex); - - // If we find field for smallest amount replace it with the formatted - // smallest amount from above taking care to replace the integer part - // with what is in original time. For example, If smallest amount - // is 9.35s and the formatted time is 0:00:09 then 9.35 becomes 09.35 - // and replacing yields 0:00:09.35 - if (smallestFieldPosition.getBeginIndex() != 0 || - smallestFieldPosition.getEndIndex() != 0) { - appendRange(draft, 0, smallestFieldPosition.getBeginIndex(), appendTo); - appendRange( - smallestAmountFormatted, - 0, - intFieldPosition.getBeginIndex(), - appendTo); - appendRange( - draft, - smallestFieldPosition.getBeginIndex(), - smallestFieldPosition.getEndIndex(), - appendTo); - appendRange( - smallestAmountFormatted, - intFieldPosition.getEndIndex(), - appendTo); - appendRange( - draft, - smallestFieldPosition.getEndIndex(), - appendTo); + const DecimalFormat *numberFormatter = dynamic_cast(numberFormat->get()); + if (!numberFormatter) { + status = U_INTERNAL_PROGRAM_ERROR; + return appendTo; + } + number::LocalizedNumberFormatter numberFormatter2; + if (auto* lnf = numberFormatter->toNumberFormatter(status)) { + numberFormatter2 = lnf->integerWidth(number::IntegerWidth::zeroFillTo(2)); } else { - appendTo.append(draft); + return appendTo; + } + + FormattedStringBuilder fsb; + + UBool protect = FALSE; + const int32_t patternLength = pattern.length(); + for (int32_t i = 0; i < patternLength; i++) { + char16_t c = pattern[i]; + + // Also set the proper field in this switch + // We don't use DateFormat.Field because this is not a date / time, is a duration. + double value = 0; + switch (c) { + case u'H': value = hours; break; + case u'm': value = minutes; break; + case u's': value = seconds; break; + } + + // For undefined field we use UNUM_FIELD_COUNT, for historical reasons. + // See cleanup bug: https://unicode-org.atlassian.net/browse/ICU-20665 + // But we give it a clear name, to keep "the ugly part" in one place. + constexpr UNumberFormatFields undefinedField = UNUM_FIELD_COUNT; + + // There is not enough info to add Field(s) for the unit because all we have are plain + // text patterns. For example in "21:51" there is no text for something like "hour", + // while in something like "21h51" there is ("h"). But we can't really tell... + switch (c) { + case u'H': + case u'm': + case u's': + if (protect) { + fsb.appendChar16(c, undefinedField, status); + } else { + UnicodeString tmp; + if ((i + 1 < patternLength) && pattern[i + 1] == c) { // doubled + tmp = numberFormatter2.formatDouble(value, status).toString(status); + i++; + } else { + numberFormatter->format(value, tmp, status); + } + // TODO: Use proper Field + fsb.append(tmp, undefinedField, status); + } + break; + case u'\'': + // '' is escaped apostrophe + if ((i + 1 < patternLength) && pattern[i + 1] == c) { + fsb.appendChar16(c, undefinedField, status); + i++; + } else { + protect = !protect; + } + break; + default: + fsb.appendChar16(c, undefinedField, status); + } } + + appendTo.append(fsb.toTempUnicodeString()); + return appendTo; } diff -Nru icu-64.2/source/i18n/measunit.cpp icu-65.1/source/i18n/measunit.cpp --- icu-64.2/source/i18n/measunit.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/measunit.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -43,21 +43,22 @@ 29, 328, 339, - 354, - 358, - 366, + 355, + 359, 368, - 372, - 393, - 395, - 409, - 412, + 370, + 374, + 381, + 402, + 404, 418, - 426, - 430, - 434, - 436, - 463 + 421, + 427, + 437, + 441, + 445, + 447, + 474 }; static const int32_t gIndexes[] = { @@ -69,21 +70,22 @@ 29, 29, 40, - 55, - 59, - 67, + 56, + 60, 69, - 73, - 94, - 96, - 110, - 113, + 71, + 75, + 82, + 103, + 105, 119, - 127, - 131, - 135, - 137, - 164 + 122, + 128, + 138, + 142, + 146, + 148, + 175 }; // Must be sorted alphabetically. @@ -100,6 +102,7 @@ "energy", "force", "frequency", + "graphics", "length", "light", "mass", @@ -456,6 +459,7 @@ "century", "day", "day-person", + "decade", "hour", "microsecond", "millisecond", @@ -480,12 +484,20 @@ "kilocalorie", "kilojoule", "kilowatt-hour", + "therm-us", "newton", "pound-force", "gigahertz", "hertz", "kilohertz", "megahertz", + "dot-per-centimeter", + "dot-per-inch", + "em", + "megapixel", + "pixel", + "pixel-per-centimeter", + "pixel-per-inch", "astronomical-unit", "centimeter", "decimeter", @@ -533,12 +545,14 @@ "milliwatt", "watt", "atmosphere", + "bar", "hectopascal", "inch-hg", "kilopascal", "megapascal", "millibar", "millimeter-of-mercury", + "pascal", "pound-per-square-inch", "kilometer-per-hour", "knot", @@ -581,18 +595,20 @@ // Must be sorted by first value and then second value. static int32_t unitPerUnitToSingleUnit[][4] = { - {379, 342, 18, 0}, - {381, 349, 18, 2}, - {383, 342, 18, 3}, - {383, 452, 4, 2}, - {383, 453, 4, 3}, - {402, 449, 3, 1}, - {405, 12, 17, 7}, - {455, 379, 4, 1} + {378, 382, 12, 5}, + {378, 387, 12, 6}, + {388, 343, 19, 0}, + {390, 350, 19, 2}, + {392, 343, 19, 3}, + {392, 463, 4, 2}, + {392, 464, 4, 3}, + {411, 460, 3, 1}, + {414, 12, 18, 9}, + {466, 388, 4, 1} }; // Shortcuts to the base unit in order to make the default constructor fast -static const int32_t kBaseTypeIdx = 15; +static const int32_t kBaseTypeIdx = 16; static const int32_t kBaseSubTypeIdx = 0; MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) { @@ -939,102 +955,110 @@ return MeasureUnit(7, 2); } -MeasureUnit *MeasureUnit::createHour(UErrorCode &status) { +MeasureUnit *MeasureUnit::createDecade(UErrorCode &status) { return MeasureUnit::create(7, 3, status); } -MeasureUnit MeasureUnit::getHour() { +MeasureUnit MeasureUnit::getDecade() { return MeasureUnit(7, 3); } -MeasureUnit *MeasureUnit::createMicrosecond(UErrorCode &status) { +MeasureUnit *MeasureUnit::createHour(UErrorCode &status) { return MeasureUnit::create(7, 4, status); } -MeasureUnit MeasureUnit::getMicrosecond() { +MeasureUnit MeasureUnit::getHour() { return MeasureUnit(7, 4); } -MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMicrosecond(UErrorCode &status) { return MeasureUnit::create(7, 5, status); } -MeasureUnit MeasureUnit::getMillisecond() { +MeasureUnit MeasureUnit::getMicrosecond() { return MeasureUnit(7, 5); } -MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) { return MeasureUnit::create(7, 6, status); } -MeasureUnit MeasureUnit::getMinute() { +MeasureUnit MeasureUnit::getMillisecond() { return MeasureUnit(7, 6); } -MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) { return MeasureUnit::create(7, 7, status); } -MeasureUnit MeasureUnit::getMonth() { +MeasureUnit MeasureUnit::getMinute() { return MeasureUnit(7, 7); } -MeasureUnit *MeasureUnit::createMonthPerson(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) { return MeasureUnit::create(7, 8, status); } -MeasureUnit MeasureUnit::getMonthPerson() { +MeasureUnit MeasureUnit::getMonth() { return MeasureUnit(7, 8); } -MeasureUnit *MeasureUnit::createNanosecond(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMonthPerson(UErrorCode &status) { return MeasureUnit::create(7, 9, status); } -MeasureUnit MeasureUnit::getNanosecond() { +MeasureUnit MeasureUnit::getMonthPerson() { return MeasureUnit(7, 9); } -MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) { +MeasureUnit *MeasureUnit::createNanosecond(UErrorCode &status) { return MeasureUnit::create(7, 10, status); } -MeasureUnit MeasureUnit::getSecond() { +MeasureUnit MeasureUnit::getNanosecond() { return MeasureUnit(7, 10); } -MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) { +MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) { return MeasureUnit::create(7, 11, status); } -MeasureUnit MeasureUnit::getWeek() { +MeasureUnit MeasureUnit::getSecond() { return MeasureUnit(7, 11); } -MeasureUnit *MeasureUnit::createWeekPerson(UErrorCode &status) { +MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) { return MeasureUnit::create(7, 12, status); } -MeasureUnit MeasureUnit::getWeekPerson() { +MeasureUnit MeasureUnit::getWeek() { return MeasureUnit(7, 12); } -MeasureUnit *MeasureUnit::createYear(UErrorCode &status) { +MeasureUnit *MeasureUnit::createWeekPerson(UErrorCode &status) { return MeasureUnit::create(7, 13, status); } -MeasureUnit MeasureUnit::getYear() { +MeasureUnit MeasureUnit::getWeekPerson() { return MeasureUnit(7, 13); } -MeasureUnit *MeasureUnit::createYearPerson(UErrorCode &status) { +MeasureUnit *MeasureUnit::createYear(UErrorCode &status) { return MeasureUnit::create(7, 14, status); } -MeasureUnit MeasureUnit::getYearPerson() { +MeasureUnit MeasureUnit::getYear() { return MeasureUnit(7, 14); } +MeasureUnit *MeasureUnit::createYearPerson(UErrorCode &status) { + return MeasureUnit::create(7, 15, status); +} + +MeasureUnit MeasureUnit::getYearPerson() { + return MeasureUnit(7, 15); +} + MeasureUnit *MeasureUnit::createAmpere(UErrorCode &status) { return MeasureUnit::create(8, 0, status); } @@ -1131,6 +1155,14 @@ return MeasureUnit(9, 7); } +MeasureUnit *MeasureUnit::createThermUs(UErrorCode &status) { + return MeasureUnit::create(9, 8, status); +} + +MeasureUnit MeasureUnit::getThermUs() { + return MeasureUnit(9, 8); +} + MeasureUnit *MeasureUnit::createNewton(UErrorCode &status) { return MeasureUnit::create(10, 0, status); } @@ -1179,708 +1211,780 @@ return MeasureUnit(11, 3); } -MeasureUnit *MeasureUnit::createAstronomicalUnit(UErrorCode &status) { +MeasureUnit *MeasureUnit::createDotPerCentimeter(UErrorCode &status) { return MeasureUnit::create(12, 0, status); } -MeasureUnit MeasureUnit::getAstronomicalUnit() { +MeasureUnit MeasureUnit::getDotPerCentimeter() { return MeasureUnit(12, 0); } -MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) { +MeasureUnit *MeasureUnit::createDotPerInch(UErrorCode &status) { return MeasureUnit::create(12, 1, status); } -MeasureUnit MeasureUnit::getCentimeter() { +MeasureUnit MeasureUnit::getDotPerInch() { return MeasureUnit(12, 1); } -MeasureUnit *MeasureUnit::createDecimeter(UErrorCode &status) { +MeasureUnit *MeasureUnit::createEm(UErrorCode &status) { return MeasureUnit::create(12, 2, status); } -MeasureUnit MeasureUnit::getDecimeter() { +MeasureUnit MeasureUnit::getEm() { return MeasureUnit(12, 2); } -MeasureUnit *MeasureUnit::createFathom(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMegapixel(UErrorCode &status) { return MeasureUnit::create(12, 3, status); } -MeasureUnit MeasureUnit::getFathom() { +MeasureUnit MeasureUnit::getMegapixel() { return MeasureUnit(12, 3); } -MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) { +MeasureUnit *MeasureUnit::createPixel(UErrorCode &status) { return MeasureUnit::create(12, 4, status); } -MeasureUnit MeasureUnit::getFoot() { +MeasureUnit MeasureUnit::getPixel() { return MeasureUnit(12, 4); } -MeasureUnit *MeasureUnit::createFurlong(UErrorCode &status) { +MeasureUnit *MeasureUnit::createPixelPerCentimeter(UErrorCode &status) { return MeasureUnit::create(12, 5, status); } -MeasureUnit MeasureUnit::getFurlong() { +MeasureUnit MeasureUnit::getPixelPerCentimeter() { return MeasureUnit(12, 5); } -MeasureUnit *MeasureUnit::createInch(UErrorCode &status) { +MeasureUnit *MeasureUnit::createPixelPerInch(UErrorCode &status) { return MeasureUnit::create(12, 6, status); } -MeasureUnit MeasureUnit::getInch() { +MeasureUnit MeasureUnit::getPixelPerInch() { return MeasureUnit(12, 6); } +MeasureUnit *MeasureUnit::createAstronomicalUnit(UErrorCode &status) { + return MeasureUnit::create(13, 0, status); +} + +MeasureUnit MeasureUnit::getAstronomicalUnit() { + return MeasureUnit(13, 0); +} + +MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) { + return MeasureUnit::create(13, 1, status); +} + +MeasureUnit MeasureUnit::getCentimeter() { + return MeasureUnit(13, 1); +} + +MeasureUnit *MeasureUnit::createDecimeter(UErrorCode &status) { + return MeasureUnit::create(13, 2, status); +} + +MeasureUnit MeasureUnit::getDecimeter() { + return MeasureUnit(13, 2); +} + +MeasureUnit *MeasureUnit::createFathom(UErrorCode &status) { + return MeasureUnit::create(13, 3, status); +} + +MeasureUnit MeasureUnit::getFathom() { + return MeasureUnit(13, 3); +} + +MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) { + return MeasureUnit::create(13, 4, status); +} + +MeasureUnit MeasureUnit::getFoot() { + return MeasureUnit(13, 4); +} + +MeasureUnit *MeasureUnit::createFurlong(UErrorCode &status) { + return MeasureUnit::create(13, 5, status); +} + +MeasureUnit MeasureUnit::getFurlong() { + return MeasureUnit(13, 5); +} + +MeasureUnit *MeasureUnit::createInch(UErrorCode &status) { + return MeasureUnit::create(13, 6, status); +} + +MeasureUnit MeasureUnit::getInch() { + return MeasureUnit(13, 6); +} + MeasureUnit *MeasureUnit::createKilometer(UErrorCode &status) { - return MeasureUnit::create(12, 7, status); + return MeasureUnit::create(13, 7, status); } MeasureUnit MeasureUnit::getKilometer() { - return MeasureUnit(12, 7); + return MeasureUnit(13, 7); } MeasureUnit *MeasureUnit::createLightYear(UErrorCode &status) { - return MeasureUnit::create(12, 8, status); + return MeasureUnit::create(13, 8, status); } MeasureUnit MeasureUnit::getLightYear() { - return MeasureUnit(12, 8); + return MeasureUnit(13, 8); } MeasureUnit *MeasureUnit::createMeter(UErrorCode &status) { - return MeasureUnit::create(12, 9, status); + return MeasureUnit::create(13, 9, status); } MeasureUnit MeasureUnit::getMeter() { - return MeasureUnit(12, 9); + return MeasureUnit(13, 9); } MeasureUnit *MeasureUnit::createMicrometer(UErrorCode &status) { - return MeasureUnit::create(12, 10, status); + return MeasureUnit::create(13, 10, status); } MeasureUnit MeasureUnit::getMicrometer() { - return MeasureUnit(12, 10); + return MeasureUnit(13, 10); } MeasureUnit *MeasureUnit::createMile(UErrorCode &status) { - return MeasureUnit::create(12, 11, status); + return MeasureUnit::create(13, 11, status); } MeasureUnit MeasureUnit::getMile() { - return MeasureUnit(12, 11); + return MeasureUnit(13, 11); } MeasureUnit *MeasureUnit::createMileScandinavian(UErrorCode &status) { - return MeasureUnit::create(12, 12, status); + return MeasureUnit::create(13, 12, status); } MeasureUnit MeasureUnit::getMileScandinavian() { - return MeasureUnit(12, 12); + return MeasureUnit(13, 12); } MeasureUnit *MeasureUnit::createMillimeter(UErrorCode &status) { - return MeasureUnit::create(12, 13, status); + return MeasureUnit::create(13, 13, status); } MeasureUnit MeasureUnit::getMillimeter() { - return MeasureUnit(12, 13); + return MeasureUnit(13, 13); } MeasureUnit *MeasureUnit::createNanometer(UErrorCode &status) { - return MeasureUnit::create(12, 14, status); + return MeasureUnit::create(13, 14, status); } MeasureUnit MeasureUnit::getNanometer() { - return MeasureUnit(12, 14); + return MeasureUnit(13, 14); } MeasureUnit *MeasureUnit::createNauticalMile(UErrorCode &status) { - return MeasureUnit::create(12, 15, status); + return MeasureUnit::create(13, 15, status); } MeasureUnit MeasureUnit::getNauticalMile() { - return MeasureUnit(12, 15); + return MeasureUnit(13, 15); } MeasureUnit *MeasureUnit::createParsec(UErrorCode &status) { - return MeasureUnit::create(12, 16, status); + return MeasureUnit::create(13, 16, status); } MeasureUnit MeasureUnit::getParsec() { - return MeasureUnit(12, 16); + return MeasureUnit(13, 16); } MeasureUnit *MeasureUnit::createPicometer(UErrorCode &status) { - return MeasureUnit::create(12, 17, status); + return MeasureUnit::create(13, 17, status); } MeasureUnit MeasureUnit::getPicometer() { - return MeasureUnit(12, 17); + return MeasureUnit(13, 17); } MeasureUnit *MeasureUnit::createPoint(UErrorCode &status) { - return MeasureUnit::create(12, 18, status); + return MeasureUnit::create(13, 18, status); } MeasureUnit MeasureUnit::getPoint() { - return MeasureUnit(12, 18); + return MeasureUnit(13, 18); } MeasureUnit *MeasureUnit::createSolarRadius(UErrorCode &status) { - return MeasureUnit::create(12, 19, status); + return MeasureUnit::create(13, 19, status); } MeasureUnit MeasureUnit::getSolarRadius() { - return MeasureUnit(12, 19); + return MeasureUnit(13, 19); } MeasureUnit *MeasureUnit::createYard(UErrorCode &status) { - return MeasureUnit::create(12, 20, status); + return MeasureUnit::create(13, 20, status); } MeasureUnit MeasureUnit::getYard() { - return MeasureUnit(12, 20); + return MeasureUnit(13, 20); } MeasureUnit *MeasureUnit::createLux(UErrorCode &status) { - return MeasureUnit::create(13, 0, status); + return MeasureUnit::create(14, 0, status); } MeasureUnit MeasureUnit::getLux() { - return MeasureUnit(13, 0); + return MeasureUnit(14, 0); } MeasureUnit *MeasureUnit::createSolarLuminosity(UErrorCode &status) { - return MeasureUnit::create(13, 1, status); + return MeasureUnit::create(14, 1, status); } MeasureUnit MeasureUnit::getSolarLuminosity() { - return MeasureUnit(13, 1); + return MeasureUnit(14, 1); } MeasureUnit *MeasureUnit::createCarat(UErrorCode &status) { - return MeasureUnit::create(14, 0, status); + return MeasureUnit::create(15, 0, status); } MeasureUnit MeasureUnit::getCarat() { - return MeasureUnit(14, 0); + return MeasureUnit(15, 0); } MeasureUnit *MeasureUnit::createDalton(UErrorCode &status) { - return MeasureUnit::create(14, 1, status); + return MeasureUnit::create(15, 1, status); } MeasureUnit MeasureUnit::getDalton() { - return MeasureUnit(14, 1); + return MeasureUnit(15, 1); } MeasureUnit *MeasureUnit::createEarthMass(UErrorCode &status) { - return MeasureUnit::create(14, 2, status); + return MeasureUnit::create(15, 2, status); } MeasureUnit MeasureUnit::getEarthMass() { - return MeasureUnit(14, 2); + return MeasureUnit(15, 2); } MeasureUnit *MeasureUnit::createGram(UErrorCode &status) { - return MeasureUnit::create(14, 3, status); + return MeasureUnit::create(15, 3, status); } MeasureUnit MeasureUnit::getGram() { - return MeasureUnit(14, 3); + return MeasureUnit(15, 3); } MeasureUnit *MeasureUnit::createKilogram(UErrorCode &status) { - return MeasureUnit::create(14, 4, status); + return MeasureUnit::create(15, 4, status); } MeasureUnit MeasureUnit::getKilogram() { - return MeasureUnit(14, 4); + return MeasureUnit(15, 4); } MeasureUnit *MeasureUnit::createMetricTon(UErrorCode &status) { - return MeasureUnit::create(14, 5, status); + return MeasureUnit::create(15, 5, status); } MeasureUnit MeasureUnit::getMetricTon() { - return MeasureUnit(14, 5); + return MeasureUnit(15, 5); } MeasureUnit *MeasureUnit::createMicrogram(UErrorCode &status) { - return MeasureUnit::create(14, 6, status); + return MeasureUnit::create(15, 6, status); } MeasureUnit MeasureUnit::getMicrogram() { - return MeasureUnit(14, 6); + return MeasureUnit(15, 6); } MeasureUnit *MeasureUnit::createMilligram(UErrorCode &status) { - return MeasureUnit::create(14, 7, status); + return MeasureUnit::create(15, 7, status); } MeasureUnit MeasureUnit::getMilligram() { - return MeasureUnit(14, 7); + return MeasureUnit(15, 7); } MeasureUnit *MeasureUnit::createOunce(UErrorCode &status) { - return MeasureUnit::create(14, 8, status); + return MeasureUnit::create(15, 8, status); } MeasureUnit MeasureUnit::getOunce() { - return MeasureUnit(14, 8); + return MeasureUnit(15, 8); } MeasureUnit *MeasureUnit::createOunceTroy(UErrorCode &status) { - return MeasureUnit::create(14, 9, status); + return MeasureUnit::create(15, 9, status); } MeasureUnit MeasureUnit::getOunceTroy() { - return MeasureUnit(14, 9); + return MeasureUnit(15, 9); } MeasureUnit *MeasureUnit::createPound(UErrorCode &status) { - return MeasureUnit::create(14, 10, status); + return MeasureUnit::create(15, 10, status); } MeasureUnit MeasureUnit::getPound() { - return MeasureUnit(14, 10); + return MeasureUnit(15, 10); } MeasureUnit *MeasureUnit::createSolarMass(UErrorCode &status) { - return MeasureUnit::create(14, 11, status); + return MeasureUnit::create(15, 11, status); } MeasureUnit MeasureUnit::getSolarMass() { - return MeasureUnit(14, 11); + return MeasureUnit(15, 11); } MeasureUnit *MeasureUnit::createStone(UErrorCode &status) { - return MeasureUnit::create(14, 12, status); + return MeasureUnit::create(15, 12, status); } MeasureUnit MeasureUnit::getStone() { - return MeasureUnit(14, 12); + return MeasureUnit(15, 12); } MeasureUnit *MeasureUnit::createTon(UErrorCode &status) { - return MeasureUnit::create(14, 13, status); + return MeasureUnit::create(15, 13, status); } MeasureUnit MeasureUnit::getTon() { - return MeasureUnit(14, 13); + return MeasureUnit(15, 13); } MeasureUnit *MeasureUnit::createGigawatt(UErrorCode &status) { - return MeasureUnit::create(16, 0, status); + return MeasureUnit::create(17, 0, status); } MeasureUnit MeasureUnit::getGigawatt() { - return MeasureUnit(16, 0); + return MeasureUnit(17, 0); } MeasureUnit *MeasureUnit::createHorsepower(UErrorCode &status) { - return MeasureUnit::create(16, 1, status); + return MeasureUnit::create(17, 1, status); } MeasureUnit MeasureUnit::getHorsepower() { - return MeasureUnit(16, 1); + return MeasureUnit(17, 1); } MeasureUnit *MeasureUnit::createKilowatt(UErrorCode &status) { - return MeasureUnit::create(16, 2, status); + return MeasureUnit::create(17, 2, status); } MeasureUnit MeasureUnit::getKilowatt() { - return MeasureUnit(16, 2); + return MeasureUnit(17, 2); } MeasureUnit *MeasureUnit::createMegawatt(UErrorCode &status) { - return MeasureUnit::create(16, 3, status); + return MeasureUnit::create(17, 3, status); } MeasureUnit MeasureUnit::getMegawatt() { - return MeasureUnit(16, 3); + return MeasureUnit(17, 3); } MeasureUnit *MeasureUnit::createMilliwatt(UErrorCode &status) { - return MeasureUnit::create(16, 4, status); + return MeasureUnit::create(17, 4, status); } MeasureUnit MeasureUnit::getMilliwatt() { - return MeasureUnit(16, 4); + return MeasureUnit(17, 4); } MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) { - return MeasureUnit::create(16, 5, status); + return MeasureUnit::create(17, 5, status); } MeasureUnit MeasureUnit::getWatt() { - return MeasureUnit(16, 5); + return MeasureUnit(17, 5); } MeasureUnit *MeasureUnit::createAtmosphere(UErrorCode &status) { - return MeasureUnit::create(17, 0, status); + return MeasureUnit::create(18, 0, status); } MeasureUnit MeasureUnit::getAtmosphere() { - return MeasureUnit(17, 0); + return MeasureUnit(18, 0); +} + +MeasureUnit *MeasureUnit::createBar(UErrorCode &status) { + return MeasureUnit::create(18, 1, status); +} + +MeasureUnit MeasureUnit::getBar() { + return MeasureUnit(18, 1); } MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) { - return MeasureUnit::create(17, 1, status); + return MeasureUnit::create(18, 2, status); } MeasureUnit MeasureUnit::getHectopascal() { - return MeasureUnit(17, 1); + return MeasureUnit(18, 2); } MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) { - return MeasureUnit::create(17, 2, status); + return MeasureUnit::create(18, 3, status); } MeasureUnit MeasureUnit::getInchHg() { - return MeasureUnit(17, 2); + return MeasureUnit(18, 3); } MeasureUnit *MeasureUnit::createKilopascal(UErrorCode &status) { - return MeasureUnit::create(17, 3, status); + return MeasureUnit::create(18, 4, status); } MeasureUnit MeasureUnit::getKilopascal() { - return MeasureUnit(17, 3); + return MeasureUnit(18, 4); } MeasureUnit *MeasureUnit::createMegapascal(UErrorCode &status) { - return MeasureUnit::create(17, 4, status); + return MeasureUnit::create(18, 5, status); } MeasureUnit MeasureUnit::getMegapascal() { - return MeasureUnit(17, 4); + return MeasureUnit(18, 5); } MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) { - return MeasureUnit::create(17, 5, status); + return MeasureUnit::create(18, 6, status); } MeasureUnit MeasureUnit::getMillibar() { - return MeasureUnit(17, 5); + return MeasureUnit(18, 6); } MeasureUnit *MeasureUnit::createMillimeterOfMercury(UErrorCode &status) { - return MeasureUnit::create(17, 6, status); + return MeasureUnit::create(18, 7, status); } MeasureUnit MeasureUnit::getMillimeterOfMercury() { - return MeasureUnit(17, 6); + return MeasureUnit(18, 7); +} + +MeasureUnit *MeasureUnit::createPascal(UErrorCode &status) { + return MeasureUnit::create(18, 8, status); +} + +MeasureUnit MeasureUnit::getPascal() { + return MeasureUnit(18, 8); } MeasureUnit *MeasureUnit::createPoundPerSquareInch(UErrorCode &status) { - return MeasureUnit::create(17, 7, status); + return MeasureUnit::create(18, 9, status); } MeasureUnit MeasureUnit::getPoundPerSquareInch() { - return MeasureUnit(17, 7); + return MeasureUnit(18, 9); } MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) { - return MeasureUnit::create(18, 0, status); + return MeasureUnit::create(19, 0, status); } MeasureUnit MeasureUnit::getKilometerPerHour() { - return MeasureUnit(18, 0); + return MeasureUnit(19, 0); } MeasureUnit *MeasureUnit::createKnot(UErrorCode &status) { - return MeasureUnit::create(18, 1, status); + return MeasureUnit::create(19, 1, status); } MeasureUnit MeasureUnit::getKnot() { - return MeasureUnit(18, 1); + return MeasureUnit(19, 1); } MeasureUnit *MeasureUnit::createMeterPerSecond(UErrorCode &status) { - return MeasureUnit::create(18, 2, status); + return MeasureUnit::create(19, 2, status); } MeasureUnit MeasureUnit::getMeterPerSecond() { - return MeasureUnit(18, 2); + return MeasureUnit(19, 2); } MeasureUnit *MeasureUnit::createMilePerHour(UErrorCode &status) { - return MeasureUnit::create(18, 3, status); + return MeasureUnit::create(19, 3, status); } MeasureUnit MeasureUnit::getMilePerHour() { - return MeasureUnit(18, 3); + return MeasureUnit(19, 3); } MeasureUnit *MeasureUnit::createCelsius(UErrorCode &status) { - return MeasureUnit::create(19, 0, status); + return MeasureUnit::create(20, 0, status); } MeasureUnit MeasureUnit::getCelsius() { - return MeasureUnit(19, 0); + return MeasureUnit(20, 0); } MeasureUnit *MeasureUnit::createFahrenheit(UErrorCode &status) { - return MeasureUnit::create(19, 1, status); + return MeasureUnit::create(20, 1, status); } MeasureUnit MeasureUnit::getFahrenheit() { - return MeasureUnit(19, 1); + return MeasureUnit(20, 1); } MeasureUnit *MeasureUnit::createGenericTemperature(UErrorCode &status) { - return MeasureUnit::create(19, 2, status); + return MeasureUnit::create(20, 2, status); } MeasureUnit MeasureUnit::getGenericTemperature() { - return MeasureUnit(19, 2); + return MeasureUnit(20, 2); } MeasureUnit *MeasureUnit::createKelvin(UErrorCode &status) { - return MeasureUnit::create(19, 3, status); + return MeasureUnit::create(20, 3, status); } MeasureUnit MeasureUnit::getKelvin() { - return MeasureUnit(19, 3); + return MeasureUnit(20, 3); } MeasureUnit *MeasureUnit::createNewtonMeter(UErrorCode &status) { - return MeasureUnit::create(20, 0, status); + return MeasureUnit::create(21, 0, status); } MeasureUnit MeasureUnit::getNewtonMeter() { - return MeasureUnit(20, 0); + return MeasureUnit(21, 0); } MeasureUnit *MeasureUnit::createPoundFoot(UErrorCode &status) { - return MeasureUnit::create(20, 1, status); + return MeasureUnit::create(21, 1, status); } MeasureUnit MeasureUnit::getPoundFoot() { - return MeasureUnit(20, 1); + return MeasureUnit(21, 1); } MeasureUnit *MeasureUnit::createAcreFoot(UErrorCode &status) { - return MeasureUnit::create(21, 0, status); + return MeasureUnit::create(22, 0, status); } MeasureUnit MeasureUnit::getAcreFoot() { - return MeasureUnit(21, 0); + return MeasureUnit(22, 0); } MeasureUnit *MeasureUnit::createBarrel(UErrorCode &status) { - return MeasureUnit::create(21, 1, status); + return MeasureUnit::create(22, 1, status); } MeasureUnit MeasureUnit::getBarrel() { - return MeasureUnit(21, 1); + return MeasureUnit(22, 1); } MeasureUnit *MeasureUnit::createBushel(UErrorCode &status) { - return MeasureUnit::create(21, 2, status); + return MeasureUnit::create(22, 2, status); } MeasureUnit MeasureUnit::getBushel() { - return MeasureUnit(21, 2); + return MeasureUnit(22, 2); } MeasureUnit *MeasureUnit::createCentiliter(UErrorCode &status) { - return MeasureUnit::create(21, 3, status); + return MeasureUnit::create(22, 3, status); } MeasureUnit MeasureUnit::getCentiliter() { - return MeasureUnit(21, 3); + return MeasureUnit(22, 3); } MeasureUnit *MeasureUnit::createCubicCentimeter(UErrorCode &status) { - return MeasureUnit::create(21, 4, status); + return MeasureUnit::create(22, 4, status); } MeasureUnit MeasureUnit::getCubicCentimeter() { - return MeasureUnit(21, 4); + return MeasureUnit(22, 4); } MeasureUnit *MeasureUnit::createCubicFoot(UErrorCode &status) { - return MeasureUnit::create(21, 5, status); + return MeasureUnit::create(22, 5, status); } MeasureUnit MeasureUnit::getCubicFoot() { - return MeasureUnit(21, 5); + return MeasureUnit(22, 5); } MeasureUnit *MeasureUnit::createCubicInch(UErrorCode &status) { - return MeasureUnit::create(21, 6, status); + return MeasureUnit::create(22, 6, status); } MeasureUnit MeasureUnit::getCubicInch() { - return MeasureUnit(21, 6); + return MeasureUnit(22, 6); } MeasureUnit *MeasureUnit::createCubicKilometer(UErrorCode &status) { - return MeasureUnit::create(21, 7, status); + return MeasureUnit::create(22, 7, status); } MeasureUnit MeasureUnit::getCubicKilometer() { - return MeasureUnit(21, 7); + return MeasureUnit(22, 7); } MeasureUnit *MeasureUnit::createCubicMeter(UErrorCode &status) { - return MeasureUnit::create(21, 8, status); + return MeasureUnit::create(22, 8, status); } MeasureUnit MeasureUnit::getCubicMeter() { - return MeasureUnit(21, 8); + return MeasureUnit(22, 8); } MeasureUnit *MeasureUnit::createCubicMile(UErrorCode &status) { - return MeasureUnit::create(21, 9, status); + return MeasureUnit::create(22, 9, status); } MeasureUnit MeasureUnit::getCubicMile() { - return MeasureUnit(21, 9); + return MeasureUnit(22, 9); } MeasureUnit *MeasureUnit::createCubicYard(UErrorCode &status) { - return MeasureUnit::create(21, 10, status); + return MeasureUnit::create(22, 10, status); } MeasureUnit MeasureUnit::getCubicYard() { - return MeasureUnit(21, 10); + return MeasureUnit(22, 10); } MeasureUnit *MeasureUnit::createCup(UErrorCode &status) { - return MeasureUnit::create(21, 11, status); + return MeasureUnit::create(22, 11, status); } MeasureUnit MeasureUnit::getCup() { - return MeasureUnit(21, 11); + return MeasureUnit(22, 11); } MeasureUnit *MeasureUnit::createCupMetric(UErrorCode &status) { - return MeasureUnit::create(21, 12, status); + return MeasureUnit::create(22, 12, status); } MeasureUnit MeasureUnit::getCupMetric() { - return MeasureUnit(21, 12); + return MeasureUnit(22, 12); } MeasureUnit *MeasureUnit::createDeciliter(UErrorCode &status) { - return MeasureUnit::create(21, 13, status); + return MeasureUnit::create(22, 13, status); } MeasureUnit MeasureUnit::getDeciliter() { - return MeasureUnit(21, 13); + return MeasureUnit(22, 13); } MeasureUnit *MeasureUnit::createFluidOunce(UErrorCode &status) { - return MeasureUnit::create(21, 14, status); + return MeasureUnit::create(22, 14, status); } MeasureUnit MeasureUnit::getFluidOunce() { - return MeasureUnit(21, 14); + return MeasureUnit(22, 14); } MeasureUnit *MeasureUnit::createFluidOunceImperial(UErrorCode &status) { - return MeasureUnit::create(21, 15, status); + return MeasureUnit::create(22, 15, status); } MeasureUnit MeasureUnit::getFluidOunceImperial() { - return MeasureUnit(21, 15); + return MeasureUnit(22, 15); } MeasureUnit *MeasureUnit::createGallon(UErrorCode &status) { - return MeasureUnit::create(21, 16, status); + return MeasureUnit::create(22, 16, status); } MeasureUnit MeasureUnit::getGallon() { - return MeasureUnit(21, 16); + return MeasureUnit(22, 16); } MeasureUnit *MeasureUnit::createGallonImperial(UErrorCode &status) { - return MeasureUnit::create(21, 17, status); + return MeasureUnit::create(22, 17, status); } MeasureUnit MeasureUnit::getGallonImperial() { - return MeasureUnit(21, 17); + return MeasureUnit(22, 17); } MeasureUnit *MeasureUnit::createHectoliter(UErrorCode &status) { - return MeasureUnit::create(21, 18, status); + return MeasureUnit::create(22, 18, status); } MeasureUnit MeasureUnit::getHectoliter() { - return MeasureUnit(21, 18); + return MeasureUnit(22, 18); } MeasureUnit *MeasureUnit::createLiter(UErrorCode &status) { - return MeasureUnit::create(21, 19, status); + return MeasureUnit::create(22, 19, status); } MeasureUnit MeasureUnit::getLiter() { - return MeasureUnit(21, 19); + return MeasureUnit(22, 19); } MeasureUnit *MeasureUnit::createMegaliter(UErrorCode &status) { - return MeasureUnit::create(21, 20, status); + return MeasureUnit::create(22, 20, status); } MeasureUnit MeasureUnit::getMegaliter() { - return MeasureUnit(21, 20); + return MeasureUnit(22, 20); } MeasureUnit *MeasureUnit::createMilliliter(UErrorCode &status) { - return MeasureUnit::create(21, 21, status); + return MeasureUnit::create(22, 21, status); } MeasureUnit MeasureUnit::getMilliliter() { - return MeasureUnit(21, 21); + return MeasureUnit(22, 21); } MeasureUnit *MeasureUnit::createPint(UErrorCode &status) { - return MeasureUnit::create(21, 22, status); + return MeasureUnit::create(22, 22, status); } MeasureUnit MeasureUnit::getPint() { - return MeasureUnit(21, 22); + return MeasureUnit(22, 22); } MeasureUnit *MeasureUnit::createPintMetric(UErrorCode &status) { - return MeasureUnit::create(21, 23, status); + return MeasureUnit::create(22, 23, status); } MeasureUnit MeasureUnit::getPintMetric() { - return MeasureUnit(21, 23); + return MeasureUnit(22, 23); } MeasureUnit *MeasureUnit::createQuart(UErrorCode &status) { - return MeasureUnit::create(21, 24, status); + return MeasureUnit::create(22, 24, status); } MeasureUnit MeasureUnit::getQuart() { - return MeasureUnit(21, 24); + return MeasureUnit(22, 24); } MeasureUnit *MeasureUnit::createTablespoon(UErrorCode &status) { - return MeasureUnit::create(21, 25, status); + return MeasureUnit::create(22, 25, status); } MeasureUnit MeasureUnit::getTablespoon() { - return MeasureUnit(21, 25); + return MeasureUnit(22, 25); } MeasureUnit *MeasureUnit::createTeaspoon(UErrorCode &status) { - return MeasureUnit::create(21, 26, status); + return MeasureUnit::create(22, 26, status); } MeasureUnit MeasureUnit::getTeaspoon() { - return MeasureUnit(21, 26); + return MeasureUnit(22, 26); } // End generated code @@ -1923,7 +2027,7 @@ return *this; } -UObject *MeasureUnit::clone() const { +MeasureUnit *MeasureUnit::clone() const { return new MeasureUnit(*this); } diff -Nru icu-64.2/source/i18n/measure.cpp icu-65.1/source/i18n/measure.cpp --- icu-64.2/source/i18n/measure.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/measure.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -43,12 +43,12 @@ if (this != &other) { delete unit; number = other.number; - unit = (MeasureUnit*) other.unit->clone(); + unit = other.unit->clone(); } return *this; } -UObject *Measure::clone() const { +Measure *Measure::clone() const { return new Measure(*this); } diff -Nru icu-64.2/source/i18n/msgfmt.cpp icu-65.1/source/i18n/msgfmt.cpp --- icu-64.2/source/i18n/msgfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/msgfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -436,7 +436,7 @@ // ------------------------------------- // Creates a copy of this MessageFormat, the caller owns the copy. -Format* +MessageFormat* MessageFormat::clone() const { return new MessageFormat(*this); @@ -813,7 +813,7 @@ // Get total required capacity first (it's refreshed on each call). int32_t totalCapacity = 0; - for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0; ++totalCapacity) {}; + for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0; ++totalCapacity) {} MessageFormat* t = const_cast (this); cnt = 0; @@ -1873,7 +1873,7 @@ return TRUE; } -Format* MessageFormat::DummyFormat::clone() const { +MessageFormat::DummyFormat* MessageFormat::DummyFormat::clone() const { return new DummyFormat(); } diff -Nru icu-64.2/source/i18n/name2uni.cpp icu-65.1/source/i18n/name2uni.cpp --- icu-64.2/source/i18n/name2uni.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/name2uni.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -100,7 +100,7 @@ /** * Transliterator API. */ -Transliterator* NameUnicodeTransliterator::clone(void) const { +NameUnicodeTransliterator* NameUnicodeTransliterator::clone() const { return new NameUnicodeTransliterator(*this); } diff -Nru icu-64.2/source/i18n/name2uni.h icu-65.1/source/i18n/name2uni.h --- icu-64.2/source/i18n/name2uni.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/name2uni.h 2019-10-03 11:16:41.000000000 +0000 @@ -49,7 +49,7 @@ * Transliterator API. * @return A copy of the object. */ - virtual Transliterator* clone(void) const; + virtual NameUnicodeTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/nortrans.cpp icu-65.1/source/i18n/nortrans.cpp --- icu-64.2/source/i18n/nortrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/nortrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -92,7 +92,7 @@ /** * Transliterator API. */ -Transliterator* NormalizationTransliterator::clone(void) const { +NormalizationTransliterator* NormalizationTransliterator::clone() const { return new NormalizationTransliterator(*this); } diff -Nru icu-64.2/source/i18n/nortrans.h icu-65.1/source/i18n/nortrans.h --- icu-64.2/source/i18n/nortrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/nortrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -44,7 +44,7 @@ * Transliterator API. * @return A copy of the object. */ - virtual Transliterator* clone(void) const; + virtual NormalizationTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/nounit.cpp icu-65.1/source/i18n/nounit.cpp --- icu-64.2/source/i18n/nounit.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/nounit.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -29,7 +29,7 @@ NoUnit::NoUnit(const NoUnit& other) : MeasureUnit(other) { } -UObject* NoUnit::clone() const { +NoUnit* NoUnit::clone() const { return new NoUnit(*this); } diff -Nru icu-64.2/source/i18n/nultrans.cpp icu-65.1/source/i18n/nultrans.cpp --- icu-64.2/source/i18n/nultrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/nultrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -24,7 +24,7 @@ NullTransliterator::~NullTransliterator() {} -Transliterator* NullTransliterator::clone(void) const { +NullTransliterator* NullTransliterator::clone() const { return new NullTransliterator(); } diff -Nru icu-64.2/source/i18n/nultrans.h icu-65.1/source/i18n/nultrans.h --- icu-64.2/source/i18n/nultrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/nultrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -45,7 +45,7 @@ * Transliterator API. * @internal Use transliterator factory methods instead since this class will be removed in that release. */ - virtual Transliterator* clone(void) const; + virtual NullTransliterator* clone() const; /** * Implements {@link Transliterator#handleTransliterate}. diff -Nru icu-64.2/source/i18n/number_affixutils.cpp icu-65.1/source/i18n/number_affixutils.cpp --- icu-64.2/source/i18n/number_affixutils.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_affixutils.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -156,7 +156,7 @@ } int32_t -AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &output, int32_t position, +AffixUtils::unescape(const UnicodeString &affixPattern, FormattedStringBuilder &output, int32_t position, const SymbolProvider &provider, Field field, UErrorCode &status) { int32_t length = 0; AffixTag tag; @@ -230,7 +230,7 @@ UnicodeString output(affixPattern); // copy if (affixPattern.length() == 0) { return output; - }; + } AffixTag tag; while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern, status); @@ -246,7 +246,7 @@ const UnicodeSet& ignorables, UErrorCode& status) { if (affixPattern.length() == 0) { return true; - }; + } AffixTag tag; while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern, status); @@ -262,7 +262,7 @@ UErrorCode& status) { if (affixPattern.length() == 0) { return; - }; + } AffixTag tag; while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern, status); diff -Nru icu-64.2/source/i18n/number_affixutils.h icu-65.1/source/i18n/number_affixutils.h --- icu-64.2/source/i18n/number_affixutils.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_affixutils.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,7 +11,7 @@ #include "number_types.h" #include "unicode/stringpiece.h" #include "unicode/unistr.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "unicode/uniset.h" U_NAMESPACE_BEGIN namespace number { @@ -134,16 +134,16 @@ /** * Executes the unescape state machine. Replaces the unquoted characters "-", "+", "%", "‰", and * "¤" with the corresponding symbols provided by the {@link SymbolProvider}, and inserts the - * result into the NumberStringBuilder at the requested location. + * result into the FormattedStringBuilder at the requested location. * *

    Example input: "'-'¤x"; example output: "-$x" * * @param affixPattern The original string to be unescaped. - * @param output The NumberStringBuilder to mutate with the result. - * @param position The index into the NumberStringBuilder to insert the string. + * @param output The FormattedStringBuilder to mutate with the result. + * @param position The index into the FormattedStringBuilder to insert the string. * @param provider An object to generate locale symbols. */ - static int32_t unescape(const UnicodeString& affixPattern, NumberStringBuilder& output, + static int32_t unescape(const UnicodeString& affixPattern, FormattedStringBuilder& output, int32_t position, const SymbolProvider& provider, Field field, UErrorCode& status); diff -Nru icu-64.2/source/i18n/number_asformat.cpp icu-65.1/source/i18n/number_asformat.cpp --- icu-64.2/source/i18n/number_asformat.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_asformat.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -43,7 +43,7 @@ return fFormatter.toSkeleton(localStatus) == _other->fFormatter.toSkeleton(localStatus); } -Format* LocalizedNumberFormatterAsFormat::clone() const { +LocalizedNumberFormatterAsFormat* LocalizedNumberFormatterAsFormat::clone() const { return new LocalizedNumberFormatterAsFormat(*this); } @@ -62,12 +62,12 @@ // always return first occurrence: pos.setBeginIndex(0); pos.setEndIndex(0); - bool found = data.getStringRef().nextFieldPosition(pos, status); + bool found = data.nextFieldPosition(pos, status); if (found && appendTo.length() != 0) { pos.setBeginIndex(pos.getBeginIndex() + appendTo.length()); pos.setEndIndex(pos.getEndIndex() + appendTo.length()); } - appendTo.append(data.getStringRef().toTempUnicodeString()); + appendTo.append(data.toTempString(status)); return appendTo; } @@ -84,10 +84,10 @@ if (U_FAILURE(status)) { return appendTo; } - appendTo.append(data.getStringRef().toTempUnicodeString()); + appendTo.append(data.toTempString(status)); if (posIter != nullptr) { FieldPositionIteratorHandler fpih(posIter, status); - data.getStringRef().getAllFieldPositions(fpih, status); + data.getAllFieldPositions(fpih, status); } return appendTo; } diff -Nru icu-64.2/source/i18n/number_asformat.h icu-65.1/source/i18n/number_asformat.h --- icu-64.2/source/i18n/number_asformat.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_asformat.h 2019-10-03 11:16:41.000000000 +0000 @@ -45,7 +45,7 @@ /** * Creates a copy of this object. */ - Format* clone() const U_OVERRIDE; + LocalizedNumberFormatterAsFormat* clone() const U_OVERRIDE; /** * Formats a Number using the wrapped LocalizedNumberFormatter. The provided formattable must be a diff -Nru icu-64.2/source/i18n/number_compact.cpp icu-65.1/source/i18n/number_compact.cpp --- icu-64.2/source/i18n/number_compact.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_compact.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -272,15 +272,15 @@ parent->processQuantity(quantity, micros, status); if (U_FAILURE(status)) { return; } - // Treat zero as if it had magnitude 0 + // Treat zero, NaN, and infinity as if they had magnitude 0 int32_t magnitude; - if (quantity.isZero()) { + if (quantity.isZeroish()) { magnitude = 0; micros.rounder.apply(quantity, status); } else { // TODO: Revisit chooseMultiplierAndApply int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); - magnitude = quantity.isZero() ? 0 : quantity.getMagnitude(); + magnitude = quantity.isZeroish() ? 0 : quantity.getMagnitude(); magnitude -= multiplier; } diff -Nru icu-64.2/source/i18n/number_currencysymbols.cpp icu-65.1/source/i18n/number_currencysymbols.cpp --- icu-64.2/source/i18n/number_currencysymbols.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_currencysymbols.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -53,13 +53,12 @@ UnicodeString CurrencySymbols::loadSymbol(UCurrNameStyle selector, UErrorCode& status) const { const char16_t* isoCode = fCurrency.getISOCurrency(); - UBool ignoredIsChoiceFormatFillIn = FALSE; int32_t symbolLen = 0; const char16_t* symbol = ucurr_getName( isoCode, fLocaleName.data(), selector, - &ignoredIsChoiceFormatFillIn, + nullptr /* isChoiceFormat */, &symbolLen, &status); // If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely! @@ -82,12 +81,11 @@ UnicodeString CurrencySymbols::getPluralName(StandardPlural::Form plural, UErrorCode& status) const { const char16_t* isoCode = fCurrency.getISOCurrency(); - UBool isChoiceFormat = FALSE; int32_t symbolLen = 0; const char16_t* symbol = ucurr_getPluralName( isoCode, fLocaleName.data(), - &isChoiceFormat, + nullptr /* isChoiceFormat */, StandardPlural::getKeyword(plural), &symbolLen, &status); diff -Nru icu-64.2/source/i18n/number_decimalquantity.cpp icu-65.1/source/i18n/number_decimalquantity.cpp --- icu-64.2/source/i18n/number_decimalquantity.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_decimalquantity.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -205,7 +205,7 @@ } void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status) { - if (isInfinite() || isZero() || isNaN()) { + if (isZeroish()) { return; } // Convert to DecNum, multiply, and convert back. @@ -218,7 +218,7 @@ } void DecimalQuantity::divideBy(const DecNum& divisor, UErrorCode& status) { - if (isInfinite() || isZero() || isNaN()) { + if (isZeroish()) { return; } // Convert to DecNum, multiply, and convert back. @@ -318,8 +318,14 @@ return (flags & NEGATIVE_FLAG) != 0; } -int8_t DecimalQuantity::signum() const { - return isNegative() ? -1 : isZero() ? 0 : 1; +Signum DecimalQuantity::signum() const { + if (isNegative()) { + return SIGNUM_NEG; + } else if (isZeroish() && !isInfinite()) { + return SIGNUM_ZERO; + } else { + return SIGNUM_POS; + } } bool DecimalQuantity::isInfinite() const { @@ -330,7 +336,7 @@ return (flags & NAN_FLAG) != 0; } -bool DecimalQuantity::isZero() const { +bool DecimalQuantity::isZeroish() const { return precision == 0; } @@ -548,7 +554,10 @@ } bool DecimalQuantity::fitsInLong(bool ignoreFraction) const { - if (isZero()) { + if (isInfinite() || isNaN()) { + return false; + } + if (isZeroish()) { return true; } if (scale < 0 && !ignoreFraction) { diff -Nru icu-64.2/source/i18n/number_decimalquantity.h icu-65.1/source/i18n/number_decimalquantity.h --- icu-64.2/source/i18n/number_decimalquantity.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_decimalquantity.h 2019-10-03 11:16:41.000000000 +0000 @@ -146,14 +146,17 @@ */ int32_t getMagnitude() const; - /** @return Whether the value represented by this {@link DecimalQuantity} is zero. */ - bool isZero() const; + /** + * @return Whether the value represented by this {@link DecimalQuantity} is + * zero, infinity, or NaN. + */ + bool isZeroish() const; /** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */ bool isNegative() const; - /** @return -1 if the value is negative; 1 if positive; or 0 if zero. */ - int8_t signum() const; + /** @return The appropriate value from the Signum enum. */ + Signum signum() const; /** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */ bool isInfinite() const U_OVERRIDE; diff -Nru icu-64.2/source/i18n/number_decnum.h icu-65.1/source/i18n/number_decnum.h --- icu-64.2/source/i18n/number_decnum.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_decnum.h 2019-10-03 11:16:41.000000000 +0000 @@ -55,6 +55,8 @@ bool isZero() const; + void toString(ByteSink& output, UErrorCode& status) const; + inline const decNumber* getRawDecNumber() const { return fData.getAlias(); } diff -Nru icu-64.2/source/i18n/number_fluent.cpp icu-65.1/source/i18n/number_fluent.cpp --- icu-64.2/source/i18n/number_fluent.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_fluent.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -696,8 +696,8 @@ void LocalizedNumberFormatter::getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result, UErrorCode& status) const { - NumberStringBuilder string; - auto signum = static_cast(isNegative ? -1 : 1); + FormattedStringBuilder string; + auto signum = static_cast(isNegative ? SIGNUM_NEG : SIGNUM_POS); // Always return affixes for plural form OTHER. static const StandardPlural::Form plural = StandardPlural::OTHER; int32_t prefixLength; diff -Nru icu-64.2/source/i18n/number_formatimpl.cpp icu-65.1/source/i18n/number_formatimpl.cpp --- icu-64.2/source/i18n/number_formatimpl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_formatimpl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -72,7 +72,7 @@ } int32_t NumberFormatterImpl::formatStatic(const MacroProps& macros, DecimalQuantity& inValue, - NumberStringBuilder& outString, UErrorCode& status) { + FormattedStringBuilder& outString, UErrorCode& status) { NumberFormatterImpl impl(macros, false, status); MicroProps& micros = impl.preProcessUnsafe(inValue, status); if (U_FAILURE(status)) { return 0; } @@ -81,9 +81,9 @@ return length; } -int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int8_t signum, +int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, Signum signum, StandardPlural::Form plural, - NumberStringBuilder& outString, UErrorCode& status) { + FormattedStringBuilder& outString, UErrorCode& status) { NumberFormatterImpl impl(macros, false, status); return impl.getPrefixSuffixUnsafe(signum, plural, outString, status); } @@ -93,7 +93,7 @@ // The "unsafe" method simply re-uses fMicros, eliminating the extra copy operation. // See MicroProps::processQuantity() for details. -int32_t NumberFormatterImpl::format(DecimalQuantity& inValue, NumberStringBuilder& outString, +int32_t NumberFormatterImpl::format(DecimalQuantity& inValue, FormattedStringBuilder& outString, UErrorCode& status) const { MicroProps micros; preProcess(inValue, micros, status); @@ -129,8 +129,8 @@ return fMicros; } -int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form plural, - NumberStringBuilder& outString, UErrorCode& status) const { +int32_t NumberFormatterImpl::getPrefixSuffix(Signum signum, StandardPlural::Form plural, + FormattedStringBuilder& outString, UErrorCode& status) const { if (U_FAILURE(status)) { return 0; } // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier). // Safe path: use fImmutablePatternModifier. @@ -140,8 +140,8 @@ return modifier->getPrefixLength(); } -int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural, - NumberStringBuilder& outString, UErrorCode& status) { +int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(Signum signum, StandardPlural::Form plural, + FormattedStringBuilder& outString, UErrorCode& status) { if (U_FAILURE(status)) { return 0; } // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier). // Unsafe path: use fPatternModifier. @@ -215,7 +215,12 @@ if (macros.symbols.isDecimalFormatSymbols()) { fMicros.symbols = macros.symbols.getDecimalFormatSymbols(); } else { - fMicros.symbols = new DecimalFormatSymbols(macros.locale, *ns, status); + auto newSymbols = new DecimalFormatSymbols(macros.locale, *ns, status); + if (newSymbols == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + fMicros.symbols = newSymbols; // Give ownership to the NumberFormatterImpl. fSymbols.adoptInstead(fMicros.symbols); } @@ -229,7 +234,11 @@ if (info.exists) { pattern = info.pattern; // It's clunky to clone an object here, but this code is not frequently executed. - auto* symbols = new DecimalFormatSymbols(*fMicros.symbols); + auto symbols = new DecimalFormatSymbols(*fMicros.symbols); + if (symbols == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } fMicros.symbols = symbols; fSymbols.adoptInstead(symbols); symbols->setSymbol( @@ -260,6 +269,10 @@ pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status); } auto patternInfo = new ParsedPatternInfo(); + if (patternInfo == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } fPatternInfo.adoptInstead(patternInfo); PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status); @@ -337,7 +350,12 @@ // Inner modifier (scientific notation) if (macros.notation.fType == Notation::NTN_SCIENTIFIC) { - fScientificHandler.adoptInstead(new ScientificHandler(¯os.notation, fMicros.symbols, chain)); + auto newScientificHandler = new ScientificHandler(¯os.notation, fMicros.symbols, chain); + if (newScientificHandler == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + fScientificHandler.adoptInstead(newScientificHandler); chain = fScientificHandler.getAlias(); } else { // No inner modifier required @@ -346,6 +364,10 @@ // Middle modifier (patterns, positive/negative, currency symbols, percent) auto patternModifier = new MutablePatternModifier(false); + if (patternModifier == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } fPatternModifier.adoptInstead(patternModifier); patternModifier->setPatternInfo( macros.affixProvider != nullptr ? macros.affixProvider @@ -401,16 +423,20 @@ if (macros.notation.fType == Notation::NTN_COMPACT) { CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME) ? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL; - fCompactHandler.adoptInstead( - new CompactHandler( - macros.notation.fUnion.compactStyle, - macros.locale, - nsName, - compactType, - resolvePluralRules(macros.rules, macros.locale, status), - safe ? patternModifier : nullptr, - chain, - status)); + auto newCompactHandler = new CompactHandler( + macros.notation.fUnion.compactStyle, + macros.locale, + nsName, + compactType, + resolvePluralRules(macros.rules, macros.locale, status), + safe ? patternModifier : nullptr, + chain, + status); + if (newCompactHandler == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + fCompactHandler.adoptInstead(newCompactHandler); chain = fCompactHandler.getAlias(); } @@ -430,7 +456,7 @@ return fRules.getAlias(); } -int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, NumberStringBuilder& string, +int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, FormattedStringBuilder& string, int32_t start, int32_t end, UErrorCode& status) { // Always apply the inner modifier (which is "strong"). int32_t length = micros.modInner->apply(string, start, end, status); @@ -445,7 +471,7 @@ } int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, int32_t index, + FormattedStringBuilder& string, int32_t index, UErrorCode& status) { int32_t length = 0; if (quantity.isInfinite()) { @@ -487,7 +513,7 @@ } int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, int32_t index, + FormattedStringBuilder& string, int32_t index, UErrorCode& status) { int length = 0; int integerCount = quantity.getUpperDisplayMagnitude() + 1; @@ -513,7 +539,7 @@ } int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, int32_t index, + FormattedStringBuilder& string, int32_t index, UErrorCode& status) { int length = 0; int fractionCount = -quantity.getLowerDisplayMagnitude(); diff -Nru icu-64.2/source/i18n/number_formatimpl.h icu-65.1/source/i18n/number_formatimpl.h --- icu-64.2/source/i18n/number_formatimpl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_formatimpl.h 2019-10-03 11:16:41.000000000 +0000 @@ -8,7 +8,7 @@ #define __NUMBER_FORMATIMPL_H__ #include "number_types.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "number_patternstring.h" #include "number_utils.h" #include "number_patternmodifier.h" @@ -35,7 +35,7 @@ * Builds and evaluates an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once. */ static int32_t - formatStatic(const MacroProps ¯os, DecimalQuantity &inValue, NumberStringBuilder &outString, + formatStatic(const MacroProps ¯os, DecimalQuantity &inValue, FormattedStringBuilder &outString, UErrorCode &status); /** @@ -44,14 +44,14 @@ * @return The index into the output at which the prefix ends and the suffix starts; in other words, * the prefix length. */ - static int32_t getPrefixSuffixStatic(const MacroProps& macros, int8_t signum, - StandardPlural::Form plural, NumberStringBuilder& outString, + static int32_t getPrefixSuffixStatic(const MacroProps& macros, Signum signum, + StandardPlural::Form plural, FormattedStringBuilder& outString, UErrorCode& status); /** * Evaluates the "safe" MicroPropsGenerator created by "fromMacros". */ - int32_t format(DecimalQuantity& inValue, NumberStringBuilder& outString, UErrorCode& status) const; + int32_t format(DecimalQuantity& inValue, FormattedStringBuilder& outString, UErrorCode& status) const; /** * Like format(), but saves the result into an output MicroProps without additional processing. @@ -61,7 +61,7 @@ /** * Like getPrefixSuffixStatic() but uses the safe compiled object. */ - int32_t getPrefixSuffix(int8_t signum, StandardPlural::Form plural, NumberStringBuilder& outString, + int32_t getPrefixSuffix(Signum signum, StandardPlural::Form plural, FormattedStringBuilder& outString, UErrorCode& status) const; const MicroProps& getRawMicroProps() const { @@ -73,12 +73,12 @@ * This method formats only the main number, not affixes. */ static int32_t writeNumber(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, int32_t index, UErrorCode& status); + FormattedStringBuilder& string, int32_t index, UErrorCode& status); /** * Adds the affixes. Intended to be called immediately after formatNumber. */ - static int32_t writeAffixes(const MicroProps& micros, NumberStringBuilder& string, int32_t start, + static int32_t writeAffixes(const MicroProps& micros, FormattedStringBuilder& string, int32_t start, int32_t end, UErrorCode& status); private: @@ -109,8 +109,8 @@ MicroProps& preProcessUnsafe(DecimalQuantity &inValue, UErrorCode &status); - int32_t getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural, - NumberStringBuilder& outString, UErrorCode& status); + int32_t getPrefixSuffixUnsafe(Signum signum, StandardPlural::Form plural, + FormattedStringBuilder& outString, UErrorCode& status); /** * If rulesPtr is non-null, return it. Otherwise, return a PluralRules owned by this object for the @@ -136,11 +136,11 @@ macrosToMicroGenerator(const MacroProps ¯os, bool safe, UErrorCode &status); static int32_t - writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string, + writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, FormattedStringBuilder &string, int32_t index, UErrorCode &status); static int32_t - writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string, + writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, FormattedStringBuilder &string, int32_t index, UErrorCode &status); }; diff -Nru icu-64.2/source/i18n/number_longnames.cpp icu-65.1/source/i18n/number_longnames.cpp --- icu-64.2/source/i18n/number_longnames.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_longnames.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -148,12 +148,11 @@ if (pattern.isBogus()) { continue; } - UBool isChoiceFormat = FALSE; int32_t longNameLen = 0; const char16_t *longName = ucurr_getPluralName( currency.getISOCurrency(), locale.getName(), - &isChoiceFormat, + nullptr /* isChoiceFormat */, StandardPlural::getKeyword(static_cast(i)), &longNameLen, &status); @@ -265,6 +264,26 @@ return simpleFormats[DNAM_INDEX]; } +UnicodeString LongNameHandler::getUnitPattern( + const Locale& loc, + const MeasureUnit& unit, + UNumberUnitWidth width, + StandardPlural::Form pluralForm, + UErrorCode& status) { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + UnicodeString simpleFormats[ARRAY_LENGTH]; + getMeasureData(loc, unit, width, simpleFormats, status); + // The above already handles fallback from other widths to short + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + // Now handle fallback from other plural forms to OTHER + return (!(simpleFormats[pluralForm]).isBogus())? simpleFormats[pluralForm]: + simpleFormats[StandardPlural::Form::OTHER]; +} + LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, const MicroPropsGenerator *parent, @@ -289,7 +308,7 @@ if (U_FAILURE(status)) { return; } SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, 0, plural}); + fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_ZERO, plural}); } } @@ -306,7 +325,7 @@ if (U_FAILURE(status)) { return; } SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, 0, plural}); + fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_ZERO, plural}); } } @@ -317,7 +336,7 @@ micros.modOuter = &fModifiers[pluralForm]; } -const Modifier* LongNameHandler::getModifier(int8_t /*signum*/, StandardPlural::Form plural) const { +const Modifier* LongNameHandler::getModifier(Signum /*signum*/, StandardPlural::Form plural) const { return &fModifiers[plural]; } diff -Nru icu-64.2/source/i18n/number_longnames.h icu-65.1/source/i18n/number_longnames.h --- icu-64.2/source/i18n/number_longnames.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_longnames.h 2019-10-03 11:16:41.000000000 +0000 @@ -22,6 +22,13 @@ UNumberUnitWidth width, UErrorCode& status); + static UnicodeString getUnitPattern( + const Locale& loc, + const MeasureUnit& unit, + UNumberUnitWidth width, + StandardPlural::Form pluralForm, + UErrorCode& status); + static LongNameHandler* forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status); @@ -34,7 +41,7 @@ void processQuantity(DecimalQuantity &quantity, MicroProps µs, UErrorCode &status) const U_OVERRIDE; - const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE; + const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE; private: SimpleModifier fModifiers[StandardPlural::Form::COUNT]; diff -Nru icu-64.2/source/i18n/number_mapper.h icu-65.1/source/i18n/number_mapper.h --- icu-64.2/source/i18n/number_mapper.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_mapper.h 2019-10-03 11:16:41.000000000 +0000 @@ -126,8 +126,14 @@ * TODO: Make some of these fields by value instead of by LocalPointer? */ struct DecimalFormatFields : public UMemory { + + DecimalFormatFields() {} + + DecimalFormatFields(const DecimalFormatProperties& propsToCopy) + : properties(propsToCopy) {} + /** The property bag corresponding to user-specified settings and settings from the pattern string. */ - LocalPointer properties; + DecimalFormatProperties properties; /** The symbols for the current locale. */ LocalPointer symbols; @@ -136,7 +142,7 @@ * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link * #format} method uses the formatter directly without needing to synchronize. */ - LocalPointer formatter; + LocalizedNumberFormatter formatter; /** The lazy-computed parser for .parse() */ std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {}; @@ -148,7 +154,7 @@ DecimalFormatWarehouse warehouse; /** The effective properties as exported from the formatter object. Used by some getters. */ - LocalPointer exportedProperties; + DecimalFormatProperties exportedProperties; // Data for fastpath bool canUseFastFormat = false; diff -Nru icu-64.2/source/i18n/number_modifiers.cpp icu-65.1/source/i18n/number_modifiers.cpp --- icu-64.2/source/i18n/number_modifiers.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_modifiers.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -57,7 +57,7 @@ : obj(nullptr) {} Modifier::Parameters::Parameters( - const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural) + const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural) : obj(_obj), signum(_signum), plural(_plural) {} ModifierStore::~ModifierStore() = default; @@ -69,7 +69,7 @@ } -int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, +int32_t ConstantAffixModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { // Insert the suffix first since inserting the prefix will change the rightIndex int length = output.insert(rightIndex, fSuffix, fField, status); @@ -154,7 +154,7 @@ : fField(UNUM_FIELD_COUNT), fStrong(false), fPrefixLength(0), fSuffixLength(0) { } -int32_t SimpleModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, +int32_t SimpleModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { return formatAsPrefixSuffix(output, leftIndex, rightIndex, status); } @@ -203,7 +203,7 @@ int32_t -SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex, +SimpleModifier::formatAsPrefixSuffix(FormattedStringBuilder &result, int32_t startIndex, int32_t endIndex, UErrorCode &status) const { if (fSuffixOffset == -1 && fPrefixLength + fSuffixLength > 0) { // There is no argument for the inner number; overwrite the entire segment with our string. @@ -227,7 +227,7 @@ int32_t -SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result, +SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result, int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength, Field field, UErrorCode& status) { const UnicodeString& compiledPattern = compiled.compiledPattern; @@ -284,7 +284,7 @@ } -int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, +int32_t ConstantMultiFieldModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { int32_t length = output.insert(leftIndex, fPrefix, status); if (fOverwrite) { @@ -333,8 +333,8 @@ } -CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const NumberStringBuilder &prefix, - const NumberStringBuilder &suffix, +CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const FormattedStringBuilder &prefix, + const FormattedStringBuilder &suffix, bool overwrite, bool strong, const DecimalFormatSymbols &symbols, @@ -374,7 +374,7 @@ } } -int32_t CurrencySpacingEnabledModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, +int32_t CurrencySpacingEnabledModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { // Currency spacing logic int length = 0; @@ -395,7 +395,7 @@ } int32_t -CurrencySpacingEnabledModifier::applyCurrencySpacing(NumberStringBuilder &output, int32_t prefixStart, +CurrencySpacingEnabledModifier::applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen, int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols, @@ -414,7 +414,7 @@ } int32_t -CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(NumberStringBuilder &output, int32_t index, +CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix, const DecimalFormatSymbols &symbols, UErrorCode &status) { diff -Nru icu-64.2/source/i18n/number_modifiers.h icu-65.1/source/i18n/number_modifiers.h --- icu-64.2/source/i18n/number_modifiers.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_modifiers.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,7 +12,7 @@ #include "unicode/uniset.h" #include "unicode/simpleformatter.h" #include "standardplural.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "number_types.h" U_NAMESPACE_BEGIN namespace number { @@ -28,7 +28,7 @@ bool strong) : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {} - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; int32_t getPrefixLength() const U_OVERRIDE; @@ -64,7 +64,7 @@ // Default constructor for LongNameHandler.h SimpleModifier(); - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; int32_t getPrefixLength() const U_OVERRIDE; @@ -81,7 +81,7 @@ /** * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because - * NumberStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. + * FormattedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. * *

    * Formats a value that is already stored inside the StringBuilder result between the indices @@ -100,22 +100,22 @@ * @return The number of characters (UTF-16 code points) that were added to the StringBuilder. */ int32_t - formatAsPrefixSuffix(NumberStringBuilder& result, int32_t startIndex, int32_t endIndex, + formatAsPrefixSuffix(FormattedStringBuilder& result, int32_t startIndex, int32_t endIndex, UErrorCode& status) const; /** * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code. - * I put it here so that the SimpleFormatter uses in NumberStringBuilder are near each other. + * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other. * *

    - * Applies the compiled two-argument pattern to the NumberStringBuilder. + * Applies the compiled two-argument pattern to the FormattedStringBuilder. * *

    * This method is optimized for the case where the prefix and suffix are often empty, such as * in the range pattern like "{0}-{1}". */ static int32_t - formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result, + formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result, int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength, Field field, UErrorCode& status); @@ -131,13 +131,13 @@ /** * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed - * based on the contents of two {@link NumberStringBuilder} instances (one for the prefix, one for the suffix). + * based on the contents of two {@link FormattedStringBuilder} instances (one for the prefix, one for the suffix). */ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { public: ConstantMultiFieldModifier( - const NumberStringBuilder &prefix, - const NumberStringBuilder &suffix, + const FormattedStringBuilder &prefix, + const FormattedStringBuilder &suffix, bool overwrite, bool strong, const Modifier::Parameters parameters) @@ -148,8 +148,8 @@ fParameters(parameters) {} ConstantMultiFieldModifier( - const NumberStringBuilder &prefix, - const NumberStringBuilder &suffix, + const FormattedStringBuilder &prefix, + const FormattedStringBuilder &suffix, bool overwrite, bool strong) : fPrefix(prefix), @@ -157,7 +157,7 @@ fOverwrite(overwrite), fStrong(strong) {} - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; int32_t getPrefixLength() const U_OVERRIDE; @@ -173,10 +173,10 @@ bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; protected: - // NOTE: In Java, these are stored as array pointers. In C++, the NumberStringBuilder is stored by + // NOTE: In Java, these are stored as array pointers. In C++, the FormattedStringBuilder is stored by // value and is treated internally as immutable. - NumberStringBuilder fPrefix; - NumberStringBuilder fSuffix; + FormattedStringBuilder fPrefix; + FormattedStringBuilder fSuffix; bool fOverwrite; bool fStrong; Modifier::Parameters fParameters; @@ -187,19 +187,19 @@ public: /** Safe code path */ CurrencySpacingEnabledModifier( - const NumberStringBuilder &prefix, - const NumberStringBuilder &suffix, + const FormattedStringBuilder &prefix, + const FormattedStringBuilder &suffix, bool overwrite, bool strong, const DecimalFormatSymbols &symbols, UErrorCode &status); - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; /** Unsafe code path */ static int32_t - applyCurrencySpacing(NumberStringBuilder &output, int32_t prefixStart, int32_t prefixLen, + applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen, int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols, UErrorCode &status); @@ -218,7 +218,7 @@ }; /** Unsafe code path */ - static int32_t applyCurrencySpacingAffix(NumberStringBuilder &output, int32_t index, EAffix affix, + static int32_t applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix, const DecimalFormatSymbols &symbols, UErrorCode &status); static UnicodeSet @@ -234,7 +234,7 @@ public: explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {} - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE { (void)output; (void)leftIndex; @@ -289,7 +289,7 @@ /** * Sets the Modifier with the specified signum and plural form. */ - void adoptModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) { + void adoptModifier(Signum signum, StandardPlural::Form plural, const Modifier *mod) { U_ASSERT(mods[getModIndex(signum, plural)] == nullptr); mods[getModIndex(signum, plural)] = mod; } @@ -298,13 +298,13 @@ * Sets the Modifier with the specified signum. * The modifier will apply to all plural forms. */ - void adoptModifierWithoutPlural(int8_t signum, const Modifier *mod) { + void adoptModifierWithoutPlural(Signum signum, const Modifier *mod) { U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr); mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod; } /** Returns a reference to the modifier; no ownership change. */ - const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE { + const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE { const Modifier* modifier = mods[getModIndex(signum, plural)]; if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) { modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)]; @@ -313,7 +313,7 @@ } /** Returns a reference to the modifier; no ownership change. */ - const Modifier *getModifierWithoutPlural(int8_t signum) const { + const Modifier *getModifierWithoutPlural(Signum signum) const { return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)]; } @@ -321,7 +321,7 @@ // NOTE: mods is zero-initialized (to nullptr) const Modifier *mods[3 * StandardPlural::COUNT] = {}; - inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) { + inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) { U_ASSERT(signum >= -1 && signum <= 1); U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT); return static_cast(plural) * 3 + (signum + 1); diff -Nru icu-64.2/source/i18n/number_output.cpp icu-65.1/source/i18n/number_output.cpp --- icu-64.2/source/i18n/number_output.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_output.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -9,6 +9,7 @@ #include "number_utypes.h" #include "util.h" #include "number_decimalquantity.h" +#include "number_decnum.h" U_NAMESPACE_BEGIN namespace number { @@ -20,8 +21,7 @@ UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) - // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool - return fData->getStringRef().nextFieldPosition(fieldPosition, status) ? TRUE : FALSE; + return fData->nextFieldPosition(fieldPosition, status); } void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { @@ -29,10 +29,17 @@ getAllFieldPositionsImpl(fpih, status); } +void FormattedNumber::toDecimalNumber(ByteSink& sink, UErrorCode& status) const { + UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) + impl::DecNum decnum; + fData->quantity.toDecNum(decnum, status); + decnum.toString(sink, status); +} + void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) - fData->getStringRef().getAllFieldPositions(fpih, status); + fData->getAllFieldPositions(fpih, status); } void FormattedNumber::getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const { diff -Nru icu-64.2/source/i18n/number_padding.cpp icu-65.1/source/i18n/number_padding.cpp --- icu-64.2/source/i18n/number_padding.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_padding.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -7,7 +7,7 @@ #include "unicode/numberformatter.h" #include "number_types.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "number_decimfmtprops.h" using namespace icu; @@ -17,7 +17,7 @@ namespace { int32_t -addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, NumberStringBuilder &string, int32_t index, +addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, FormattedStringBuilder &string, int32_t index, UErrorCode &status) { for (int32_t i = 0; i < requiredPadding; i++) { // TODO: If appending to the end, this will cause actual insertion operations. Improve. @@ -60,7 +60,7 @@ } int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2, - NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex, + FormattedStringBuilder &string, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const { int32_t modLength = mod1.getCodePointCount() + mod2.getCodePointCount(); int32_t requiredPadding = fWidth - modLength - string.codePointCount(); diff -Nru icu-64.2/source/i18n/number_patternmodifier.cpp icu-65.1/source/i18n/number_patternmodifier.cpp --- icu-64.2/source/i18n/number_patternmodifier.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_patternmodifier.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -43,7 +43,7 @@ fRules = rules; } -void MutablePatternModifier::setNumberProperties(int8_t signum, StandardPlural::Form plural) { +void MutablePatternModifier::setNumberProperties(Signum signum, StandardPlural::Form plural) { fSignum = signum; fPlural = plural; } @@ -79,12 +79,12 @@ if (needsPlurals()) { // Slower path when we require the plural keyword. for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) { - setNumberProperties(1, plural); - pm->adoptModifier(1, plural, createConstantModifier(status)); - setNumberProperties(0, plural); - pm->adoptModifier(0, plural, createConstantModifier(status)); - setNumberProperties(-1, plural); - pm->adoptModifier(-1, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_POS, plural); + pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_ZERO, plural); + pm->adoptModifier(SIGNUM_ZERO, plural, createConstantModifier(status)); + setNumberProperties(SIGNUM_NEG, plural); + pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status)); } if (U_FAILURE(status)) { delete pm; @@ -93,12 +93,12 @@ return new ImmutablePatternModifier(pm, fRules, parent); // adopts pm } else { // Faster path when plural keyword is not needed. - setNumberProperties(1, StandardPlural::Form::COUNT); - pm->adoptModifierWithoutPlural(1, createConstantModifier(status)); - setNumberProperties(0, StandardPlural::Form::COUNT); - pm->adoptModifierWithoutPlural(0, createConstantModifier(status)); - setNumberProperties(-1, StandardPlural::Form::COUNT); - pm->adoptModifierWithoutPlural(-1, createConstantModifier(status)); + setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status)); + setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_ZERO, createConstantModifier(status)); + setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT); + pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status)); if (U_FAILURE(status)) { delete pm; return nullptr; @@ -108,8 +108,8 @@ } ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErrorCode& status) { - NumberStringBuilder a; - NumberStringBuilder b; + FormattedStringBuilder a; + FormattedStringBuilder b; insertPrefix(a, 0, status); insertSuffix(b, 0, status); if (fPatternInfo->hasCurrencySign()) { @@ -140,7 +140,7 @@ } } -const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlural::Form plural) const { +const Modifier* ImmutablePatternModifier::getModifier(Signum signum, StandardPlural::Form plural) const { if (rules == nullptr) { return pm->getModifierWithoutPlural(signum); } else { @@ -170,7 +170,7 @@ micros.modMiddle = this; } -int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftIndex, int32_t rightIndex, +int32_t MutablePatternModifier::apply(FormattedStringBuilder& output, int32_t leftIndex, int32_t rightIndex, UErrorCode& status) const { // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. @@ -248,13 +248,13 @@ UPRV_UNREACHABLE; } -int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) { +int32_t MutablePatternModifier::insertPrefix(FormattedStringBuilder& sb, int position, UErrorCode& status) { prepareAffix(true); int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status); return length; } -int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int position, UErrorCode& status) { +int32_t MutablePatternModifier::insertSuffix(FormattedStringBuilder& sb, int position, UErrorCode& status) { prepareAffix(false); int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status); return length; diff -Nru icu-64.2/source/i18n/number_patternmodifier.h icu-65.1/source/i18n/number_patternmodifier.h --- icu-64.2/source/i18n/number_patternmodifier.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_patternmodifier.h 2019-10-03 11:16:41.000000000 +0000 @@ -48,7 +48,7 @@ void applyToMicros(MicroProps& micros, const DecimalQuantity& quantity, UErrorCode& status) const; - const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const; + const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const; private: ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, @@ -142,7 +142,7 @@ * The plural form of the number, required only if the pattern contains the triple * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}). */ - void setNumberProperties(int8_t signum, StandardPlural::Form plural); + void setNumberProperties(Signum signum, StandardPlural::Form plural); /** * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize. @@ -184,7 +184,7 @@ void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE; - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; int32_t getPrefixLength() const U_OVERRIDE; @@ -223,7 +223,7 @@ const PluralRules *fRules; // Number details (initialized in setNumberProperties) - int8_t fSignum; + Signum fSignum; StandardPlural::Form fPlural; // QuantityChain details (initialized in addToChain) @@ -240,17 +240,17 @@ * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. * * @param a - * A working NumberStringBuilder object; passed from the outside to prevent the need to create many new + * A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new * instances if this method is called in a loop. * @param b - * Another working NumberStringBuilder object. + * Another working FormattedStringBuilder object. * @return The constant modifier object. */ ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status); - int32_t insertPrefix(NumberStringBuilder &sb, int position, UErrorCode &status); + int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status); - int32_t insertSuffix(NumberStringBuilder &sb, int position, UErrorCode &status); + int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status); void prepareAffix(bool isPrefix); }; diff -Nru icu-64.2/source/i18n/number_patternstring.cpp icu-65.1/source/i18n/number_patternstring.cpp --- icu-64.2/source/i18n/number_patternstring.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_patternstring.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -352,7 +352,7 @@ result.groupingSizes += 1; result.integerNumerals += 1; result.integerTotal += 1; - if (!result.rounding.isZero() || state.peek() != u'0') { + if (!result.rounding.isZeroish() || state.peek() != u'0') { result.rounding.appendDigit(static_cast(state.peek() - u'0'), 0, true); } break; @@ -532,7 +532,7 @@ properties.roundingIncrement = 0.0; properties.minimumSignificantDigits = positive.integerAtSigns; properties.maximumSignificantDigits = positive.integerAtSigns + positive.integerTrailingHashSigns; - } else if (!positive.rounding.isZero()) { + } else if (!positive.rounding.isZeroish()) { if (!ignoreRounding) { properties.minimumFractionDigits = minFrac; properties.maximumFractionDigits = positive.fractionTotal; @@ -1000,7 +1000,7 @@ } void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, - int8_t signum, UNumberSignDisplay signDisplay, + Signum signum, UNumberSignDisplay signDisplay, StandardPlural::Form plural, bool perMilleReplacesPercent, UnicodeString& output) { @@ -1014,6 +1014,7 @@ // Should we use the affix from the negative subpattern? (If not, we will use the positive // subpattern.) + // TODO: Deal with signum bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && ( signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); diff -Nru icu-64.2/source/i18n/number_patternstring.h icu-65.1/source/i18n/number_patternstring.h --- icu-64.2/source/i18n/number_patternstring.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_patternstring.h 2019-10-03 11:16:41.000000000 +0000 @@ -295,7 +295,7 @@ * substitution, and plural forms for CurrencyPluralInfo. */ static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, - int8_t signum, UNumberSignDisplay signDisplay, + Signum signum, UNumberSignDisplay signDisplay, StandardPlural::Form plural, bool perMilleReplacesPercent, UnicodeString& output); diff -Nru icu-64.2/source/i18n/number_rounding.cpp icu-65.1/source/i18n/number_rounding.cpp --- icu-64.2/source/i18n/number_rounding.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_rounding.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -33,7 +33,7 @@ if (maxSig == -1) { return INT32_MIN; } - int magnitude = value.isZero() ? 0 : value.getMagnitude(); + int magnitude = value.isZeroish() ? 0 : value.getMagnitude(); return magnitude - maxSig + 1; } @@ -45,7 +45,7 @@ } int32_t getDisplayMagnitudeSignificant(const DecimalQuantity &value, int minSig) { - int magnitude = value.isZero() ? 0 : value.getMagnitude(); + int magnitude = value.isZeroish() ? 0 : value.getMagnitude(); return magnitude - minSig + 1; } @@ -306,8 +306,8 @@ int32_t RoundingImpl::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, UErrorCode &status) { - // Do not call this method with zero. - U_ASSERT(!input.isZero()); + // Do not call this method with zero, NaN, or infinity. + U_ASSERT(!input.isZeroish()); // Perform the first attempt at rounding. int magnitude = input.getMagnitude(); @@ -316,7 +316,7 @@ apply(input, status); // If the number rounded to zero, exit. - if (input.isZero() || U_FAILURE(status)) { + if (input.isZeroish() || U_FAILURE(status)) { return multiplier; } @@ -374,7 +374,7 @@ value.setMinFraction( uprv_max(0, -getDisplayMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMinSig))); // Make sure that digits are displayed on zero. - if (value.isZero() && fPrecision.fUnion.fracSig.fMinSig > 0) { + if (value.isZeroish() && fPrecision.fUnion.fracSig.fMinSig > 0) { value.setMinInteger(1); } break; @@ -436,7 +436,7 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode /*status*/) { // This method is intended for the one specific purpose of helping print "00.000E0". U_ASSERT(isSignificantDigits()); - U_ASSERT(value.isZero()); + U_ASSERT(value.isZeroish()); value.setMinFraction(fPrecision.fUnion.fracSig.fMinSig - minInt); } diff -Nru icu-64.2/source/i18n/number_scientific.cpp icu-65.1/source/i18n/number_scientific.cpp --- icu-64.2/source/i18n/number_scientific.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_scientific.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -8,7 +8,7 @@ #include #include "number_scientific.h" #include "number_utils.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "unicode/unum.h" #include "number_microprops.h" @@ -36,7 +36,7 @@ fHandler = handler; } -int32_t ScientificModifier::apply(NumberStringBuilder &output, int32_t /*leftIndex*/, int32_t rightIndex, +int32_t ScientificModifier::apply(FormattedStringBuilder &output, int32_t /*leftIndex*/, int32_t rightIndex, UErrorCode &status) const { // FIXME: Localized exponent separator location. int i = rightIndex; @@ -123,9 +123,15 @@ fParent->processQuantity(quantity, micros, status); if (U_FAILURE(status)) { return; } + // Do not apply scientific notation to special doubles + if (quantity.isInfinite() || quantity.isNaN()) { + micros.modInner = µs.helpers.emptyStrongModifier; + return; + } + // Treat zero as if it had magnitude 0 int32_t exponent; - if (quantity.isZero()) { + if (quantity.isZeroish()) { if (fSettings.fRequireMinInt && micros.rounder.isSignificantDigits()) { // Show "00.000E0" on pattern "00.000E0" micros.rounder.apply(quantity, fSettings.fEngineeringInterval, status); diff -Nru icu-64.2/source/i18n/number_scientific.h icu-65.1/source/i18n/number_scientific.h --- icu-64.2/source/i18n/number_scientific.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_scientific.h 2019-10-03 11:16:41.000000000 +0000 @@ -21,7 +21,7 @@ void set(int32_t exponent, const ScientificHandler *handler); - int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, + int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; int32_t getPrefixLength() const U_OVERRIDE; diff -Nru icu-64.2/source/i18n/number_skeletons.cpp icu-65.1/source/i18n/number_skeletons.cpp --- icu-64.2/source/i18n/number_skeletons.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_skeletons.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -20,6 +20,7 @@ #include "unicode/numberformatter.h" #include "uinvchar.h" #include "charstr.h" +#include "string_segment.h" using namespace icu; using namespace icu::number; @@ -119,17 +120,17 @@ #define CHECK_NULL(seen, field, status) (void)(seen); /* for auto-format line wrapping */ \ -{ \ +UPRV_BLOCK_MACRO_BEGIN { \ if ((seen).field) { \ (status) = U_NUMBER_SKELETON_SYNTAX_ERROR; \ return STATE_NULL; \ } \ (seen).field = true; \ -} +} UPRV_BLOCK_MACRO_END #define SKELETON_UCHAR_TO_CHAR(dest, src, start, end, status) (void)(dest); \ -{ \ +UPRV_BLOCK_MACRO_BEGIN { \ UErrorCode conversionStatus = U_ZERO_ERROR; \ (dest).appendInvariantChars({FALSE, (src).getBuffer() + (start), (end) - (start)}, conversionStatus); \ if (conversionStatus == U_INVARIANT_CONVERSION_ERROR) { \ @@ -140,7 +141,7 @@ (status) = conversionStatus; \ return; \ } \ -} +} UPRV_BLOCK_MACRO_END } // anonymous namespace @@ -1217,7 +1218,7 @@ maxInt = 0; } for (; offset < segment.length(); offset++) { - if (segment.charAt(offset) == u'#') { + if (maxInt != -1 && segment.charAt(offset) == u'#') { maxInt++; } else { break; diff -Nru icu-64.2/source/i18n/number_skeletons.h icu-65.1/source/i18n/number_skeletons.h --- icu-64.2/source/i18n/number_skeletons.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_skeletons.h 2019-10-03 11:16:41.000000000 +0000 @@ -10,10 +10,10 @@ #include "number_types.h" #include "numparse_types.h" #include "unicode/ucharstrie.h" +#include "string_segment.h" -using icu::numparse::impl::StringSegment; - -U_NAMESPACE_BEGIN namespace number { +U_NAMESPACE_BEGIN +namespace number { namespace impl { // Forward-declaration diff -Nru icu-64.2/source/i18n/number_stringbuilder.cpp icu-65.1/source/i18n/number_stringbuilder.cpp --- icu-64.2/source/i18n/number_stringbuilder.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_stringbuilder.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,599 +0,0 @@ -// © 2017 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "number_stringbuilder.h" -#include "static_unicode_sets.h" -#include "unicode/utf16.h" -#include "number_utils.h" - -using namespace icu; -using namespace icu::number; -using namespace icu::number::impl; - -namespace { - -// A version of uprv_memcpy that checks for length 0. -// By default, uprv_memcpy requires a length of at least 1. -inline void uprv_memcpy2(void* dest, const void* src, size_t len) { - if (len > 0) { - uprv_memcpy(dest, src, len); - } -} - -// A version of uprv_memmove that checks for length 0. -// By default, uprv_memmove requires a length of at least 1. -inline void uprv_memmove2(void* dest, const void* src, size_t len) { - if (len > 0) { - uprv_memmove(dest, src, len); - } -} - -} // namespace - -NumberStringBuilder::NumberStringBuilder() { -#if U_DEBUG - // Initializing the memory to non-zero helps catch some bugs that involve - // reading from an improperly terminated string. - for (int32_t i=0; i DEFAULT_CAPACITY) { - // FIXME: uprv_malloc - // C++ note: malloc appears in two places: here and in prepareForInsertHelper. - auto newChars = static_cast (uprv_malloc(sizeof(char16_t) * capacity)); - auto newFields = static_cast(uprv_malloc(sizeof(Field) * capacity)); - if (newChars == nullptr || newFields == nullptr) { - // UErrorCode is not available; fail silently. - uprv_free(newChars); - uprv_free(newFields); - *this = NumberStringBuilder(); // can't fail - return *this; - } - - fUsingHeap = true; - fChars.heap.capacity = capacity; - fChars.heap.ptr = newChars; - fFields.heap.capacity = capacity; - fFields.heap.ptr = newFields; - } - - uprv_memcpy2(getCharPtr(), other.getCharPtr(), sizeof(char16_t) * capacity); - uprv_memcpy2(getFieldPtr(), other.getFieldPtr(), sizeof(Field) * capacity); - - fZero = other.fZero; - fLength = other.fLength; - return *this; -} - -int32_t NumberStringBuilder::length() const { - return fLength; -} - -int32_t NumberStringBuilder::codePointCount() const { - return u_countChar32(getCharPtr() + fZero, fLength); -} - -UChar32 NumberStringBuilder::getFirstCodePoint() const { - if (fLength == 0) { - return -1; - } - UChar32 cp; - U16_GET(getCharPtr() + fZero, 0, 0, fLength, cp); - return cp; -} - -UChar32 NumberStringBuilder::getLastCodePoint() const { - if (fLength == 0) { - return -1; - } - int32_t offset = fLength; - U16_BACK_1(getCharPtr() + fZero, 0, offset); - UChar32 cp; - U16_GET(getCharPtr() + fZero, 0, offset, fLength, cp); - return cp; -} - -UChar32 NumberStringBuilder::codePointAt(int32_t index) const { - UChar32 cp; - U16_GET(getCharPtr() + fZero, 0, index, fLength, cp); - return cp; -} - -UChar32 NumberStringBuilder::codePointBefore(int32_t index) const { - int32_t offset = index; - U16_BACK_1(getCharPtr() + fZero, 0, offset); - UChar32 cp; - U16_GET(getCharPtr() + fZero, 0, offset, fLength, cp); - return cp; -} - -NumberStringBuilder &NumberStringBuilder::clear() { - // TODO: Reset the heap here? - fZero = getCapacity() / 2; - fLength = 0; - return *this; -} - -int32_t NumberStringBuilder::appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status) { - return insertCodePoint(fLength, codePoint, field, status); -} - -int32_t -NumberStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status) { - int32_t count = U16_LENGTH(codePoint); - int32_t position = prepareForInsert(index, count, status); - if (U_FAILURE(status)) { - return count; - } - if (count == 1) { - getCharPtr()[position] = (char16_t) codePoint; - getFieldPtr()[position] = field; - } else { - getCharPtr()[position] = U16_LEAD(codePoint); - getCharPtr()[position + 1] = U16_TRAIL(codePoint); - getFieldPtr()[position] = getFieldPtr()[position + 1] = field; - } - return count; -} - -int32_t NumberStringBuilder::append(const UnicodeString &unistr, Field field, UErrorCode &status) { - return insert(fLength, unistr, field, status); -} - -int32_t NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, Field field, - UErrorCode &status) { - if (unistr.length() == 0) { - // Nothing to insert. - return 0; - } else if (unistr.length() == 1) { - // Fast path: insert using insertCodePoint. - return insertCodePoint(index, unistr.charAt(0), field, status); - } else { - return insert(index, unistr, 0, unistr.length(), field, status); - } -} - -int32_t -NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, - Field field, UErrorCode &status) { - int32_t count = end - start; - int32_t position = prepareForInsert(index, count, status); - if (U_FAILURE(status)) { - return count; - } - for (int32_t i = 0; i < count; i++) { - getCharPtr()[position + i] = unistr.charAt(start + i); - getFieldPtr()[position + i] = field; - } - return count; -} - -int32_t -NumberStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr, - int32_t startOther, int32_t endOther, Field field, UErrorCode& status) { - int32_t thisLength = endThis - startThis; - int32_t otherLength = endOther - startOther; - int32_t count = otherLength - thisLength; - int32_t position; - if (count > 0) { - // Overall, chars need to be added. - position = prepareForInsert(startThis, count, status); - } else { - // Overall, chars need to be removed or kept the same. - position = remove(startThis, -count); - } - if (U_FAILURE(status)) { - return count; - } - for (int32_t i = 0; i < otherLength; i++) { - getCharPtr()[position + i] = unistr.charAt(startOther + i); - getFieldPtr()[position + i] = field; - } - return count; -} - -int32_t NumberStringBuilder::append(const NumberStringBuilder &other, UErrorCode &status) { - return insert(fLength, other, status); -} - -int32_t -NumberStringBuilder::insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status) { - if (this == &other) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } - int32_t count = other.fLength; - if (count == 0) { - // Nothing to insert. - return 0; - } - int32_t position = prepareForInsert(index, count, status); - if (U_FAILURE(status)) { - return count; - } - for (int32_t i = 0; i < count; i++) { - getCharPtr()[position + i] = other.charAt(i); - getFieldPtr()[position + i] = other.fieldAt(i); - } - return count; -} - -void NumberStringBuilder::writeTerminator(UErrorCode& status) { - int32_t position = prepareForInsert(fLength, 1, status); - if (U_FAILURE(status)) { - return; - } - getCharPtr()[position] = 0; - getFieldPtr()[position] = UNUM_FIELD_COUNT; - fLength--; -} - -int32_t NumberStringBuilder::prepareForInsert(int32_t index, int32_t count, UErrorCode &status) { - U_ASSERT(index >= 0); - U_ASSERT(index <= fLength); - U_ASSERT(count >= 0); - if (index == 0 && fZero - count >= 0) { - // Append to start - fZero -= count; - fLength += count; - return fZero; - } else if (index == fLength && fZero + fLength + count < getCapacity()) { - // Append to end - fLength += count; - return fZero + fLength - count; - } else { - // Move chars around and/or allocate more space - return prepareForInsertHelper(index, count, status); - } -} - -int32_t NumberStringBuilder::prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status) { - int32_t oldCapacity = getCapacity(); - int32_t oldZero = fZero; - char16_t *oldChars = getCharPtr(); - Field *oldFields = getFieldPtr(); - if (fLength + count > oldCapacity) { - int32_t newCapacity = (fLength + count) * 2; - int32_t newZero = newCapacity / 2 - (fLength + count) / 2; - - // C++ note: malloc appears in two places: here and in the assignment operator. - auto newChars = static_cast (uprv_malloc(sizeof(char16_t) * newCapacity)); - auto newFields = static_cast(uprv_malloc(sizeof(Field) * newCapacity)); - if (newChars == nullptr || newFields == nullptr) { - uprv_free(newChars); - uprv_free(newFields); - status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } - - // First copy the prefix and then the suffix, leaving room for the new chars that the - // caller wants to insert. - // C++ note: memcpy is OK because the src and dest do not overlap. - uprv_memcpy2(newChars + newZero, oldChars + oldZero, sizeof(char16_t) * index); - uprv_memcpy2(newChars + newZero + index + count, - oldChars + oldZero + index, - sizeof(char16_t) * (fLength - index)); - uprv_memcpy2(newFields + newZero, oldFields + oldZero, sizeof(Field) * index); - uprv_memcpy2(newFields + newZero + index + count, - oldFields + oldZero + index, - sizeof(Field) * (fLength - index)); - - if (fUsingHeap) { - uprv_free(oldChars); - uprv_free(oldFields); - } - fUsingHeap = true; - fChars.heap.ptr = newChars; - fChars.heap.capacity = newCapacity; - fFields.heap.ptr = newFields; - fFields.heap.capacity = newCapacity; - fZero = newZero; - fLength += count; - } else { - int32_t newZero = oldCapacity / 2 - (fLength + count) / 2; - - // C++ note: memmove is required because src and dest may overlap. - // First copy the entire string to the location of the prefix, and then move the suffix - // to make room for the new chars that the caller wants to insert. - uprv_memmove2(oldChars + newZero, oldChars + oldZero, sizeof(char16_t) * fLength); - uprv_memmove2(oldChars + newZero + index + count, - oldChars + newZero + index, - sizeof(char16_t) * (fLength - index)); - uprv_memmove2(oldFields + newZero, oldFields + oldZero, sizeof(Field) * fLength); - uprv_memmove2(oldFields + newZero + index + count, - oldFields + newZero + index, - sizeof(Field) * (fLength - index)); - - fZero = newZero; - fLength += count; - } - return fZero + index; -} - -int32_t NumberStringBuilder::remove(int32_t index, int32_t count) { - // TODO: Reset the heap here? (If the string after removal can fit on stack?) - int32_t position = index + fZero; - uprv_memmove2(getCharPtr() + position, - getCharPtr() + position + count, - sizeof(char16_t) * (fLength - index - count)); - uprv_memmove2(getFieldPtr() + position, - getFieldPtr() + position + count, - sizeof(Field) * (fLength - index - count)); - fLength -= count; - return position; -} - -UnicodeString NumberStringBuilder::toUnicodeString() const { - return UnicodeString(getCharPtr() + fZero, fLength); -} - -const UnicodeString NumberStringBuilder::toTempUnicodeString() const { - // Readonly-alias constructor: - return UnicodeString(FALSE, getCharPtr() + fZero, fLength); -} - -UnicodeString NumberStringBuilder::toDebugString() const { - UnicodeString sb; - sb.append(u"", -1); - return sb; -} - -const char16_t *NumberStringBuilder::chars() const { - return getCharPtr() + fZero; -} - -bool NumberStringBuilder::contentEquals(const NumberStringBuilder &other) const { - if (fLength != other.fLength) { - return false; - } - for (int32_t i = 0; i < fLength; i++) { - if (charAt(i) != other.charAt(i) || fieldAt(i) != other.fieldAt(i)) { - return false; - } - } - return true; -} - -bool NumberStringBuilder::nextFieldPosition(FieldPosition& fp, UErrorCode& status) const { - int32_t rawField = fp.getField(); - - if (rawField == FieldPosition::DONT_CARE) { - return FALSE; - } - - if (rawField < 0 || rawField >= UNUM_FIELD_COUNT) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - - ConstrainedFieldPosition cfpos; - cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField); - cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex()); - if (nextPosition(cfpos, 0, status)) { - fp.setBeginIndex(cfpos.getStart()); - fp.setEndIndex(cfpos.getLimit()); - return true; - } - - // Special case: fraction should start after integer if fraction is not present - if (rawField == UNUM_FRACTION_FIELD && fp.getEndIndex() == 0) { - bool inside = false; - int32_t i = fZero; - for (; i < fZero + fLength; i++) { - if (isIntOrGroup(getFieldPtr()[i]) || getFieldPtr()[i] == UNUM_DECIMAL_SEPARATOR_FIELD) { - inside = true; - } else if (inside) { - break; - } - } - fp.setBeginIndex(i - fZero); - fp.setEndIndex(i - fZero); - } - - return false; -} - -void NumberStringBuilder::getAllFieldPositions(FieldPositionIteratorHandler& fpih, - UErrorCode& status) const { - ConstrainedFieldPosition cfpos; - while (nextPosition(cfpos, 0, status)) { - fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit()); - } -} - -// Signal the end of the string using a field that doesn't exist and that is -// different from UNUM_FIELD_COUNT, which is used for "null number field". -static constexpr Field kEndField = 0xff; - -bool NumberStringBuilder::nextPosition(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const { - auto numericCAF = NumFieldUtils::expand(numericField); - int32_t fieldStart = -1; - Field currField = UNUM_FIELD_COUNT; - for (int32_t i = fZero + cfpos.getLimit(); i <= fZero + fLength; i++) { - Field _field = (i < fZero + fLength) ? getFieldPtr()[i] : kEndField; - // Case 1: currently scanning a field. - if (currField != UNUM_FIELD_COUNT) { - if (currField != _field) { - int32_t end = i - fZero; - // Grouping separators can be whitespace; don't throw them out! - if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { - end = trimBack(i - fZero); - } - if (end <= fieldStart) { - // Entire field position is ignorable; skip. - fieldStart = -1; - currField = UNUM_FIELD_COUNT; - i--; // look at this index again - continue; - } - int32_t start = fieldStart; - if (currField != UNUM_GROUPING_SEPARATOR_FIELD) { - start = trimFront(start); - } - auto caf = NumFieldUtils::expand(currField); - cfpos.setState(caf.category, caf.field, start, end); - return true; - } - continue; - } - // Special case: coalesce the INTEGER if we are pointing at the end of the INTEGER. - if (cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD) - && i > fZero - // don't return the same field twice in a row: - && i - fZero > cfpos.getLimit() - && isIntOrGroup(getFieldPtr()[i - 1]) - && !isIntOrGroup(_field)) { - int j = i - 1; - for (; j >= fZero && isIntOrGroup(getFieldPtr()[j]); j--) {} - cfpos.setState(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, j - fZero + 1, i - fZero); - return true; - } - // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC. - if (numericField != 0 - && cfpos.matchesField(numericCAF.category, numericCAF.field) - && i > fZero - // don't return the same field twice in a row: - && (i - fZero > cfpos.getLimit() - || cfpos.getCategory() != numericCAF.category - || cfpos.getField() != numericCAF.field) - && isNumericField(getFieldPtr()[i - 1]) - && !isNumericField(_field)) { - int j = i - 1; - for (; j >= fZero && isNumericField(getFieldPtr()[j]); j--) {} - cfpos.setState(numericCAF.category, numericCAF.field, j - fZero + 1, i - fZero); - return true; - } - // Special case: skip over INTEGER; will be coalesced later. - if (_field == UNUM_INTEGER_FIELD) { - _field = UNUM_FIELD_COUNT; - } - // Case 2: no field starting at this position. - if (_field == UNUM_FIELD_COUNT || _field == kEndField) { - continue; - } - // Case 3: check for field starting at this position - auto caf = NumFieldUtils::expand(_field); - if (cfpos.matchesField(caf.category, caf.field)) { - fieldStart = i - fZero; - currField = _field; - } - } - - U_ASSERT(currField == UNUM_FIELD_COUNT); - return false; -} - -bool NumberStringBuilder::containsField(Field field) const { - for (int32_t i = 0; i < fLength; i++) { - if (field == fieldAt(i)) { - return true; - } - } - return false; -} - -bool NumberStringBuilder::isIntOrGroup(Field field) { - return field == UNUM_INTEGER_FIELD - || field == UNUM_GROUPING_SEPARATOR_FIELD; -} - -bool NumberStringBuilder::isNumericField(Field field) { - return NumFieldUtils::isNumericField(field); -} - -int32_t NumberStringBuilder::trimBack(int32_t limit) const { - return unisets::get(unisets::DEFAULT_IGNORABLES)->spanBack( - getCharPtr() + fZero, - limit, - USET_SPAN_CONTAINED); -} - -int32_t NumberStringBuilder::trimFront(int32_t start) const { - return start + unisets::get(unisets::DEFAULT_IGNORABLES)->span( - getCharPtr() + fZero + start, - fLength - start, - USET_SPAN_CONTAINED); -} - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/number_stringbuilder.h icu-65.1/source/i18n/number_stringbuilder.h --- icu-64.2/source/i18n/number_stringbuilder.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_stringbuilder.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ -// © 2017 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING -#ifndef __NUMBER_STRINGBUILDER_H__ -#define __NUMBER_STRINGBUILDER_H__ - - -#include -#include "unicode/numfmt.h" -#include "unicode/ustring.h" -#include "cstring.h" -#include "uassert.h" -#include "number_types.h" -#include "fphdlimp.h" - -U_NAMESPACE_BEGIN namespace number { -namespace impl { - -class U_I18N_API NumberStringBuilder : public UMemory { - private: - static const int32_t DEFAULT_CAPACITY = 40; - - template - union ValueOrHeapArray { - T value[DEFAULT_CAPACITY]; - struct { - T *ptr; - int32_t capacity; - } heap; - }; - - public: - NumberStringBuilder(); - - ~NumberStringBuilder(); - - NumberStringBuilder(const NumberStringBuilder &other); - - NumberStringBuilder &operator=(const NumberStringBuilder &other); - - int32_t length() const; - - int32_t codePointCount() const; - - inline char16_t charAt(int32_t index) const { - U_ASSERT(index >= 0); - U_ASSERT(index < fLength); - return getCharPtr()[fZero + index]; - } - - inline Field fieldAt(int32_t index) const { - U_ASSERT(index >= 0); - U_ASSERT(index < fLength); - return getFieldPtr()[fZero + index]; - } - - UChar32 getFirstCodePoint() const; - - UChar32 getLastCodePoint() const; - - UChar32 codePointAt(int32_t index) const; - - UChar32 codePointBefore(int32_t index) const; - - NumberStringBuilder &clear(); - - int32_t appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status); - - int32_t insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status); - - int32_t append(const UnicodeString &unistr, Field field, UErrorCode &status); - - int32_t insert(int32_t index, const UnicodeString &unistr, Field field, UErrorCode &status); - - int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field, - UErrorCode &status); - - int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr, - int32_t startOther, int32_t endOther, Field field, UErrorCode& status); - - int32_t append(const NumberStringBuilder &other, UErrorCode &status); - - int32_t insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status); - - void writeTerminator(UErrorCode& status); - - /** - * Gets a "safe" UnicodeString that can be used even after the NumberStringBuilder is destructed. - * */ - UnicodeString toUnicodeString() const; - - /** - * Gets an "unsafe" UnicodeString that is valid only as long as the NumberStringBuilder is alive and - * unchanged. Slightly faster than toUnicodeString(). - */ - const UnicodeString toTempUnicodeString() const; - - UnicodeString toDebugString() const; - - const char16_t *chars() const; - - bool contentEquals(const NumberStringBuilder &other) const; - - bool nextFieldPosition(FieldPosition& fp, UErrorCode& status) const; - - void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; - - bool nextPosition(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& status) const; - - bool containsField(Field field) const; - - private: - bool fUsingHeap = false; - ValueOrHeapArray fChars; - ValueOrHeapArray fFields; - int32_t fZero = DEFAULT_CAPACITY / 2; - int32_t fLength = 0; - - inline char16_t *getCharPtr() { - return fUsingHeap ? fChars.heap.ptr : fChars.value; - } - - inline const char16_t *getCharPtr() const { - return fUsingHeap ? fChars.heap.ptr : fChars.value; - } - - inline Field *getFieldPtr() { - return fUsingHeap ? fFields.heap.ptr : fFields.value; - } - - inline const Field *getFieldPtr() const { - return fUsingHeap ? fFields.heap.ptr : fFields.value; - } - - inline int32_t getCapacity() const { - return fUsingHeap ? fChars.heap.capacity : DEFAULT_CAPACITY; - } - - int32_t prepareForInsert(int32_t index, int32_t count, UErrorCode &status); - - int32_t prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status); - - int32_t remove(int32_t index, int32_t count); - - static bool isIntOrGroup(Field field); - - static bool isNumericField(Field field); - - int32_t trimBack(int32_t limit) const; - - int32_t trimFront(int32_t start) const; -}; - -} // namespace impl -} // namespace number -U_NAMESPACE_END - - -#endif //__NUMBER_STRINGBUILDER_H__ - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/number_types.h icu-65.1/source/i18n/number_types.h --- icu-64.2/source/i18n/number_types.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_types.h 2019-10-03 11:16:41.000000000 +0000 @@ -17,17 +17,16 @@ #include "unicode/platform.h" #include "unicode/uniset.h" #include "standardplural.h" +#include "formatted_string_builder.h" -U_NAMESPACE_BEGIN namespace number { +U_NAMESPACE_BEGIN +namespace number { namespace impl { -// Typedef several enums for brevity and for easier comparison to Java. +// For convenience and historical reasons, import the Field typedef to the namespace. +typedef FormattedStringBuilder::Field Field; -// Convention: bottom 4 bits for field, top 4 bits for field category. -// Field category 0 implies the number category so that the number field -// literals can be directly passed as a Field type. -// See the helper functions in "NumFieldUtils" in number_utils.h -typedef uint8_t Field; +// Typedef several enums for brevity and for easier comparison to Java. typedef UNumberFormatRoundingMode RoundingMode; @@ -49,7 +48,6 @@ class Modifier; class MutablePatternModifier; class DecimalQuantity; -class NumberStringBuilder; class ModifierStore; struct MicroProps; @@ -93,6 +91,12 @@ TYPE_DECIMAL, TYPE_CURRENCY }; +enum Signum { + SIGNUM_NEG = -1, + SIGNUM_ZERO = 0, + SIGNUM_POS = 1 +}; + class U_I18N_API AffixPatternProvider { public: @@ -160,7 +164,7 @@ * formatted. * @return The number of characters (UTF-16 code units) that were added to the string builder. */ - virtual int32_t apply(NumberStringBuilder& output, int leftIndex, int rightIndex, + virtual int32_t apply(FormattedStringBuilder& output, int leftIndex, int rightIndex, UErrorCode& status) const = 0; /** @@ -196,11 +200,11 @@ */ struct U_I18N_API Parameters { const ModifierStore* obj = nullptr; - int8_t signum; + Signum signum; StandardPlural::Form plural; Parameters(); - Parameters(const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural); + Parameters(const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural); }; /** @@ -231,7 +235,7 @@ /** * Returns a Modifier with the given parameters (best-effort). */ - virtual const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const = 0; + virtual const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const = 0; }; diff -Nru icu-64.2/source/i18n/number_utils.cpp icu-65.1/source/i18n/number_utils.cpp --- icu-64.2/source/i18n/number_utils.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_utils.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -252,4 +252,15 @@ return decNumberIsZero(fData.getAlias()); } +void DecNum::toString(ByteSink& output, UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + // "string must be at least dn->digits+14 characters long" + int32_t minCapacity = fData.getAlias()->digits + 14; + MaybeStackArray buffer(minCapacity); + uprv_decNumberToString(fData, buffer.getAlias()); + output.Append(buffer.getAlias(), static_cast(uprv_strlen(buffer.getAlias()))); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/number_utils.h icu-65.1/source/i18n/number_utils.h --- icu-64.2/source/i18n/number_utils.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_utils.h 2019-10-03 11:16:41.000000000 +0000 @@ -17,6 +17,7 @@ #include "number_roundingutils.h" #include "decNumber.h" #include "charstr.h" +#include "formatted_string_builder.h" U_NAMESPACE_BEGIN @@ -32,52 +33,10 @@ CLDR_PATTERN_STYLE_COUNT, }; - -/** - * Helper functions for dealing with the Field typedef, which stores fields - * in a compressed format. - */ -class NumFieldUtils { -public: - struct CategoryFieldPair { - int32_t category; - int32_t field; - }; - - /** Compile-time function to construct a Field from a category and a field */ - template - static constexpr Field compress() { - static_assert(category != 0, "cannot use Undefined category in NumFieldUtils"); - static_assert(category <= 0xf, "only 4 bits for category"); - static_assert(field <= 0xf, "only 4 bits for field"); - return static_cast((category << 4) | field); - } - - /** Runtime inline function to unpack the category and field from the Field */ - static inline CategoryFieldPair expand(Field field) { - if (field == UNUM_FIELD_COUNT) { - return {UFIELD_CATEGORY_UNDEFINED, 0}; - } - CategoryFieldPair ret = { - (field >> 4), - (field & 0xf) - }; - if (ret.category == 0) { - ret.category = UFIELD_CATEGORY_NUMBER; - } - return ret; - } - - static inline bool isNumericField(Field field) { - int8_t category = field >> 4; - return category == 0 || category == UFIELD_CATEGORY_NUMBER; - } -}; - // Namespace for naked functions namespace utils { -inline int32_t insertDigitFromSymbols(NumberStringBuilder& output, int32_t index, int8_t digit, +inline int32_t insertDigitFromSymbols(FormattedStringBuilder& output, int32_t index, int8_t digit, const DecimalFormatSymbols& symbols, Field field, UErrorCode& status) { if (symbols.getCodePointZero() != -1) { diff -Nru icu-64.2/source/i18n/number_utypes.h icu-65.1/source/i18n/number_utypes.h --- icu-64.2/source/i18n/number_utypes.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/number_utypes.h 2019-10-03 11:16:41.000000000 +0000 @@ -10,7 +10,7 @@ #include "unicode/numberformatter.h" #include "number_types.h" #include "number_decimalquantity.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "formattedval_impl.h" U_NAMESPACE_BEGIN namespace number { @@ -31,9 +31,9 @@ * The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used * to add a toDecNumber() or similar method. */ -class UFormattedNumberData : public FormattedValueNumberStringBuilderImpl { +class UFormattedNumberData : public FormattedValueStringBuilderImpl { public: - UFormattedNumberData() : FormattedValueNumberStringBuilderImpl(0) {} + UFormattedNumberData() : FormattedValueStringBuilderImpl(0) {} virtual ~UFormattedNumberData(); DecimalQuantity quantity; diff -Nru icu-64.2/source/i18n/numfmt.cpp icu-65.1/source/i18n/numfmt.cpp --- icu-64.2/source/i18n/numfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -569,7 +569,7 @@ if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) { // trying to format a different currency. // Right now, we clone. - LocalPointer cloneFmt((NumberFormat*)this->clone()); + LocalPointer cloneFmt(this->clone()); cloneFmt->setCurrency(iso, status); // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount. return cloneFmt->format(*n, appendTo, pos, status); @@ -624,7 +624,7 @@ if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) { // trying to format a different currency. // Right now, we clone. - LocalPointer cloneFmt((NumberFormat*)this->clone()); + LocalPointer cloneFmt(this->clone()); cloneFmt->setCurrency(iso, status); // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount. return cloneFmt->format(*n, appendTo, posIter, status); @@ -986,15 +986,19 @@ URegistryKey U_EXPORT2 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status) { - ICULocaleService *service = getNumberFormatService(); - if (service) { - NFFactory *tempnnf = new NFFactory(toAdopt); - if (tempnnf != NULL) { - return service->registerFactory(tempnnf, status); - } - } - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + if (U_FAILURE(status)) { + delete toAdopt; + return nullptr; + } + ICULocaleService *service = getNumberFormatService(); + if (service) { + NFFactory *tempnnf = new NFFactory(toAdopt); + if (tempnnf != NULL) { + return service->registerFactory(tempnnf, status); + } + } + status = U_MEMORY_ALLOCATION_ERROR; + return NULL; } // ------------------------------------- @@ -1055,7 +1059,7 @@ if (U_FAILURE(status)) { return NULL; } - NumberFormat *result = static_cast((*shared)->clone()); + NumberFormat *result = (*shared)->clone(); shared->removeRef(); if (result == NULL) { status = U_MEMORY_ALLOCATION_ERROR; @@ -1362,7 +1366,7 @@ // TODO: Bad hash key usage, see ticket #8504. int32_t hashKey = desiredLocale.hashCode(); - static icu::UMutex nscacheMutex = U_MUTEX_INITIALIZER; + static UMutex nscacheMutex; Mutex lock(&nscacheMutex); ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey); if (ns == NULL) { diff -Nru icu-64.2/source/i18n/numparse_affixes.cpp icu-65.1/source/i18n/numparse_affixes.cpp --- icu-64.2/source/i18n/numparse_affixes.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_affixes.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,7 @@ #include "numparse_affixes.h" #include "numparse_utils.h" #include "number_utils.h" +#include "string_segment.h" using namespace icu; using namespace icu::numparse; @@ -280,7 +281,9 @@ AffixPatternMatcher* posSuffix = nullptr; // Pre-process the affix strings to resolve LDML rules like sign display. - for (int8_t signum = 1; signum >= -1; signum--) { + for (int8_t signumInt = 1; signumInt >= -1; signumInt--) { + auto signum = static_cast(signumInt); + // Generate Prefix bool hasPrefix = false; PatternStringUtils::patternInfoToStringBuilder( diff -Nru icu-64.2/source/i18n/numparse_compositions.cpp icu-65.1/source/i18n/numparse_compositions.cpp --- icu-64.2/source/i18n/numparse_compositions.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_compositions.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,7 @@ #include "numparse_types.h" #include "numparse_compositions.h" +#include "string_segment.h" #include "unicode/uniset.h" using namespace icu; diff -Nru icu-64.2/source/i18n/numparse_currency.cpp icu-65.1/source/i18n/numparse_currency.cpp --- icu-64.2/source/i18n/numparse_currency.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_currency.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,7 @@ #include "ucurrimp.h" #include "unicode/errorcode.h" #include "numparse_utils.h" +#include "string_segment.h" using namespace icu; using namespace icu::numparse; diff -Nru icu-64.2/source/i18n/numparse_decimal.cpp icu-65.1/source/i18n/numparse_decimal.cpp --- icu-64.2/source/i18n/numparse_decimal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_decimal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,7 @@ #include "unicode/uchar.h" #include "putilimp.h" #include "number_decimalquantity.h" +#include "string_segment.h" using namespace icu; using namespace icu::numparse; diff -Nru icu-64.2/source/i18n/numparse_impl.cpp icu-65.1/source/i18n/numparse_impl.cpp --- icu-64.2/source/i18n/numparse_impl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_impl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -39,7 +39,7 @@ LocalPointer parser(new NumberParserImpl(parseFlags)); DecimalFormatSymbols symbols(locale, status); - parser->fLocalMatchers.ignorables = {unisets::DEFAULT_IGNORABLES}; + parser->fLocalMatchers.ignorables = {parseFlags}; IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables; DecimalFormatSymbols dfs(locale, status); @@ -114,6 +114,7 @@ parseFlags |= PARSE_FLAG_STRICT_SEPARATORS; parseFlags |= PARSE_FLAG_USE_FULL_AFFIXES; parseFlags |= PARSE_FLAG_EXACT_AFFIX; + parseFlags |= PARSE_FLAG_STRICT_IGNORABLES; } else { parseFlags |= PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES; } @@ -129,8 +130,7 @@ LocalPointer parser(new NumberParserImpl(parseFlags)); - parser->fLocalMatchers.ignorables = { - isStrict ? unisets::STRICT_IGNORABLES : unisets::DEFAULT_IGNORABLES}; + parser->fLocalMatchers.ignorables = {parseFlags}; IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables; ////////////////////// diff -Nru icu-64.2/source/i18n/numparse_impl.h icu-65.1/source/i18n/numparse_impl.h --- icu-64.2/source/i18n/numparse_impl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_impl.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,6 +18,7 @@ #include "unicode/localpointer.h" #include "numparse_validators.h" #include "number_multiplier.h" +#include "string_segment.h" U_NAMESPACE_BEGIN diff -Nru icu-64.2/source/i18n/numparse_parsednumber.cpp icu-65.1/source/i18n/numparse_parsednumber.cpp --- icu-64.2/source/i18n/numparse_parsednumber.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_parsednumber.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,7 @@ #include "numparse_types.h" #include "number_decimalquantity.h" +#include "string_segment.h" #include "putilimp.h" #include @@ -73,7 +74,7 @@ status = U_INVALID_STATE_ERROR; return 0.0; } - if (quantity.isZero() && quantity.isNegative()) { + if (quantity.isZeroish() && quantity.isNegative()) { return -0.0; } @@ -106,7 +107,7 @@ } } U_ASSERT(!quantity.bogus); - if (quantity.isZero() && quantity.isNegative() && !integerOnly) { + if (quantity.isZeroish() && quantity.isNegative() && !integerOnly) { output.setDouble(-0.0); return; } diff -Nru icu-64.2/source/i18n/numparse_scientific.cpp icu-65.1/source/i18n/numparse_scientific.cpp --- icu-64.2/source/i18n/numparse_scientific.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_scientific.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,7 @@ #include "numparse_types.h" #include "numparse_scientific.h" #include "static_unicode_sets.h" +#include "string_segment.h" using namespace icu; using namespace icu::numparse; @@ -33,7 +34,8 @@ ScientificMatcher::ScientificMatcher(const DecimalFormatSymbols& dfs, const Grouper& grouper) : fExponentSeparatorString(dfs.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol)), - fExponentMatcher(dfs, grouper, PARSE_FLAG_INTEGER_ONLY | PARSE_FLAG_GROUPING_DISABLED) { + fExponentMatcher(dfs, grouper, PARSE_FLAG_INTEGER_ONLY | PARSE_FLAG_GROUPING_DISABLED), + fIgnorablesMatcher(PARSE_FLAG_STRICT_IGNORABLES) { const UnicodeString& minusSign = dfs.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); if (minusSignSet().contains(minusSign)) { @@ -63,15 +65,25 @@ // First match the scientific separator, and then match another number after it. // NOTE: This is guarded by the smoke test; no need to check fExponentSeparatorString length again. - int overlap1 = segment.getCommonPrefixLength(fExponentSeparatorString); - if (overlap1 == fExponentSeparatorString.length()) { + int32_t initialOffset = segment.getOffset(); + int32_t overlap = segment.getCommonPrefixLength(fExponentSeparatorString); + if (overlap == fExponentSeparatorString.length()) { // Full exponent separator match. // First attempt to get a code point, returning true if we can't get one. - if (segment.length() == overlap1) { + if (segment.length() == overlap) { + return true; + } + segment.adjustOffset(overlap); + + // Allow ignorables before the sign. + // Note: call site is guarded by the segment.length() check above. + // Note: the ignorables matcher should not touch the result. + fIgnorablesMatcher.match(segment, result, status); + if (segment.length() == 0) { + segment.setOffset(initialOffset); return true; } - segment.adjustOffset(overlap1); // Allow a sign, and then try to match digits. int8_t exponentSign = 1; @@ -81,24 +93,37 @@ } else if (segment.startsWith(plusSignSet())) { segment.adjustOffsetByCodePoint(); } else if (segment.startsWith(fCustomMinusSign)) { - // Note: call site is guarded with startsWith, which returns false on empty string - int32_t overlap2 = segment.getCommonPrefixLength(fCustomMinusSign); - if (overlap2 != fCustomMinusSign.length()) { - // Partial custom sign match; un-match the exponent separator. - segment.adjustOffset(-overlap1); + overlap = segment.getCommonPrefixLength(fCustomMinusSign); + if (overlap != fCustomMinusSign.length()) { + // Partial custom sign match + segment.setOffset(initialOffset); return true; } exponentSign = -1; - segment.adjustOffset(overlap2); + segment.adjustOffset(overlap); } else if (segment.startsWith(fCustomPlusSign)) { - // Note: call site is guarded with startsWith, which returns false on empty string - int32_t overlap2 = segment.getCommonPrefixLength(fCustomPlusSign); - if (overlap2 != fCustomPlusSign.length()) { - // Partial custom sign match; un-match the exponent separator. - segment.adjustOffset(-overlap1); + overlap = segment.getCommonPrefixLength(fCustomPlusSign); + if (overlap != fCustomPlusSign.length()) { + // Partial custom sign match + segment.setOffset(initialOffset); return true; } - segment.adjustOffset(overlap2); + segment.adjustOffset(overlap); + } + + // Return true if the segment is empty. + if (segment.length() == 0) { + segment.setOffset(initialOffset); + return true; + } + + // Allow ignorables after the sign. + // Note: call site is guarded by the segment.length() check above. + // Note: the ignorables matcher should not touch the result. + fIgnorablesMatcher.match(segment, result, status); + if (segment.length() == 0) { + segment.setOffset(initialOffset); + return true; } // We are supposed to accept E0 after NaN, so we need to make sure result.quantity is available. @@ -112,12 +137,12 @@ // At least one exponent digit was matched. result.flags |= FLAG_HAS_EXPONENT; } else { - // No exponent digits were matched; un-match the exponent separator. - segment.adjustOffset(-overlap1); + // No exponent digits were matched + segment.setOffset(initialOffset); } return digitsReturnValue; - } else if (overlap1 == segment.length()) { + } else if (overlap == segment.length()) { // Partial exponent separator match return true; } diff -Nru icu-64.2/source/i18n/numparse_scientific.h icu-65.1/source/i18n/numparse_scientific.h --- icu-64.2/source/i18n/numparse_scientific.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_scientific.h 2019-10-03 11:16:41.000000000 +0000 @@ -9,6 +9,7 @@ #include "numparse_types.h" #include "numparse_decimal.h" +#include "numparse_symbols.h" #include "unicode/numberformatter.h" using icu::number::impl::Grouper; @@ -32,6 +33,7 @@ private: UnicodeString fExponentSeparatorString; DecimalMatcher fExponentMatcher; + IgnorablesMatcher fIgnorablesMatcher; UnicodeString fCustomMinusSign; UnicodeString fCustomPlusSign; }; diff -Nru icu-64.2/source/i18n/numparse_stringsegment.cpp icu-65.1/source/i18n/numparse_stringsegment.cpp --- icu-64.2/source/i18n/numparse_stringsegment.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_stringsegment.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -// © 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -// Allow implicit conversion from char16_t* to UnicodeString for this file: -// Helpful in toString methods and elsewhere. -#define UNISTR_FROM_STRING_EXPLICIT - -#include "numparse_types.h" -#include "numparse_stringsegment.h" -#include "putilimp.h" -#include "unicode/utf16.h" -#include "unicode/uniset.h" - -using namespace icu; -using namespace icu::numparse; -using namespace icu::numparse::impl; - - -StringSegment::StringSegment(const UnicodeString& str, bool ignoreCase) - : fStr(str), fStart(0), fEnd(str.length()), - fFoldCase(ignoreCase) {} - -int32_t StringSegment::getOffset() const { - return fStart; -} - -void StringSegment::setOffset(int32_t start) { - fStart = start; -} - -void StringSegment::adjustOffset(int32_t delta) { - fStart += delta; -} - -void StringSegment::adjustOffsetByCodePoint() { - fStart += U16_LENGTH(getCodePoint()); -} - -void StringSegment::setLength(int32_t length) { - fEnd = fStart + length; -} - -void StringSegment::resetLength() { - fEnd = fStr.length(); -} - -int32_t StringSegment::length() const { - return fEnd - fStart; -} - -char16_t StringSegment::charAt(int32_t index) const { - return fStr.charAt(index + fStart); -} - -UChar32 StringSegment::codePointAt(int32_t index) const { - return fStr.char32At(index + fStart); -} - -UnicodeString StringSegment::toUnicodeString() const { - return UnicodeString(fStr.getBuffer() + fStart, fEnd - fStart); -} - -const UnicodeString StringSegment::toTempUnicodeString() const { - // Use the readonly-aliasing constructor for efficiency. - return UnicodeString(FALSE, fStr.getBuffer() + fStart, fEnd - fStart); -} - -UChar32 StringSegment::getCodePoint() const { - char16_t lead = fStr.charAt(fStart); - if (U16_IS_LEAD(lead) && fStart + 1 < fEnd) { - return fStr.char32At(fStart); - } else if (U16_IS_SURROGATE(lead)) { - return -1; - } else { - return lead; - } -} - -bool StringSegment::startsWith(UChar32 otherCp) const { - return codePointsEqual(getCodePoint(), otherCp, fFoldCase); -} - -bool StringSegment::startsWith(const UnicodeSet& uniset) const { - // TODO: Move UnicodeSet case-folding logic here. - // TODO: Handle string matches here instead of separately. - UChar32 cp = getCodePoint(); - if (cp == -1) { - return false; - } - return uniset.contains(cp); -} - -bool StringSegment::startsWith(const UnicodeString& other) const { - if (other.isBogus() || other.length() == 0 || length() == 0) { - return false; - } - int cp1 = getCodePoint(); - int cp2 = other.char32At(0); - return codePointsEqual(cp1, cp2, fFoldCase); -} - -int32_t StringSegment::getCommonPrefixLength(const UnicodeString& other) { - return getPrefixLengthInternal(other, fFoldCase); -} - -int32_t StringSegment::getCaseSensitivePrefixLength(const UnicodeString& other) { - return getPrefixLengthInternal(other, false); -} - -int32_t StringSegment::getPrefixLengthInternal(const UnicodeString& other, bool foldCase) { - U_ASSERT(other.length() > 0); - int32_t offset = 0; - for (; offset < uprv_min(length(), other.length());) { - // TODO: case-fold code points, not chars - char16_t c1 = charAt(offset); - char16_t c2 = other.charAt(offset); - if (!codePointsEqual(c1, c2, foldCase)) { - break; - } - offset++; - } - return offset; -} - -bool StringSegment::codePointsEqual(UChar32 cp1, UChar32 cp2, bool foldCase) { - if (cp1 == cp2) { - return true; - } - if (!foldCase) { - return false; - } - cp1 = u_foldCase(cp1, TRUE); - cp2 = u_foldCase(cp2, TRUE); - return cp1 == cp2; -} - -bool StringSegment::operator==(const UnicodeString& other) const { - return toTempUnicodeString() == other; -} - - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/numparse_stringsegment.h icu-65.1/source/i18n/numparse_stringsegment.h --- icu-64.2/source/i18n/numparse_stringsegment.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_stringsegment.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -// © 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING -#ifndef __NUMPARSE_STRINGSEGMENT_H__ -#define __NUMPARSE_STRINGSEGMENT_H__ - -#include "numparse_types.h" -#include "number_types.h" -#include "unicode/unistr.h" - -U_NAMESPACE_BEGIN -namespace numparse { -namespace impl { - - -} // namespace impl -} // namespace numparse -U_NAMESPACE_END - -#endif //__NUMPARSE_STRINGSEGMENT_H__ -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/numparse_symbols.cpp icu-65.1/source/i18n/numparse_symbols.cpp --- icu-64.2/source/i18n/numparse_symbols.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_symbols.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,7 @@ #include "numparse_types.h" #include "numparse_symbols.h" #include "numparse_utils.h" +#include "string_segment.h" using namespace icu; using namespace icu::numparse; @@ -68,8 +69,12 @@ } -IgnorablesMatcher::IgnorablesMatcher(unisets::Key key) - : SymbolMatcher({}, key) { +IgnorablesMatcher::IgnorablesMatcher(parse_flags_t parseFlags) : + SymbolMatcher( + {}, + (0 != (parseFlags & PARSE_FLAG_STRICT_IGNORABLES)) ? + unisets::STRICT_IGNORABLES : + unisets::DEFAULT_IGNORABLES) { } bool IgnorablesMatcher::isFlexible() const { diff -Nru icu-64.2/source/i18n/numparse_symbols.h icu-65.1/source/i18n/numparse_symbols.h --- icu-64.2/source/i18n/numparse_symbols.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_symbols.h 2019-10-03 11:16:41.000000000 +0000 @@ -50,7 +50,7 @@ public: IgnorablesMatcher() = default; // WARNING: Leaves the object in an unusable state - IgnorablesMatcher(unisets::Key key); + IgnorablesMatcher(parse_flags_t parseFlags); bool isFlexible() const override; diff -Nru icu-64.2/source/i18n/numparse_types.h icu-65.1/source/i18n/numparse_types.h --- icu-64.2/source/i18n/numparse_types.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numparse_types.h 2019-10-03 11:16:41.000000000 +0000 @@ -9,12 +9,13 @@ #include "unicode/uobject.h" #include "number_decimalquantity.h" +#include "string_segment.h" -U_NAMESPACE_BEGIN namespace numparse { +U_NAMESPACE_BEGIN +namespace numparse { namespace impl { // Forward-declarations -class StringSegment; class ParsedNumber; typedef int32_t result_flags_t; @@ -50,6 +51,7 @@ // PARSE_FLAG_FORCE_BIG_DECIMAL = 0x1000, // not used in ICU4C PARSE_FLAG_NO_FOREIGN_CURRENCY = 0x2000, PARSE_FLAG_ALLOW_INFINITE_RECURSION = 0x4000, + PARSE_FLAG_STRICT_IGNORABLES = 0x8000, }; @@ -169,115 +171,6 @@ }; -/** - * A mutable class allowing for a String with a variable offset and length. The charAt, length, and - * subSequence methods all operate relative to the fixed offset into the String. - * - * @author sffc - */ -// Exported as U_I18N_API for tests -class U_I18N_API StringSegment : public UMemory { - public: - StringSegment(const UnicodeString& str, bool ignoreCase); - - int32_t getOffset() const; - - void setOffset(int32_t start); - - /** - * Equivalent to setOffset(getOffset()+delta). - * - *

    - * This method is usually called by a Matcher to register that a char was consumed. If the char is - * strong (it usually is, except for things like whitespace), follow this with a call to - * {@link ParsedNumber#setCharsConsumed}. For more information on strong chars, see that method. - */ - void adjustOffset(int32_t delta); - - /** - * Adjusts the offset by the width of the current code point, either 1 or 2 chars. - */ - void adjustOffsetByCodePoint(); - - void setLength(int32_t length); - - void resetLength(); - - int32_t length() const; - - char16_t charAt(int32_t index) const; - - UChar32 codePointAt(int32_t index) const; - - UnicodeString toUnicodeString() const; - - const UnicodeString toTempUnicodeString() const; - - /** - * Returns the first code point in the string segment, or -1 if the string starts with an invalid - * code point. - * - *

    - * Important: Most of the time, you should use {@link #matches}, which handles case - * folding logic, instead of this method. - */ - UChar32 getCodePoint() const; - - /** - * Returns true if the first code point of this StringSegment equals the given code point. - * - *

    - * This method will perform case folding if case folding is enabled for the parser. - */ - bool startsWith(UChar32 otherCp) const; - - /** - * Returns true if the first code point of this StringSegment is in the given UnicodeSet. - */ - bool startsWith(const UnicodeSet& uniset) const; - - /** - * Returns true if there is at least one code point of overlap between this StringSegment and the - * given UnicodeString. - */ - bool startsWith(const UnicodeString& other) const; - - /** - * Returns the length of the prefix shared by this StringSegment and the given CharSequence. For - * example, if this string segment is "aab", and the char sequence is "aac", this method returns 2, - * since the first 2 characters are the same. - * - *

    - * This method only returns offsets along code point boundaries. - * - *

    - * This method will perform case folding if case folding was enabled in the constructor. - * - *

    - * IMPORTANT: The given UnicodeString must not be empty! It is the caller's responsibility to check. - */ - int32_t getCommonPrefixLength(const UnicodeString& other); - - /** - * Like {@link #getCommonPrefixLength}, but never performs case folding, even if case folding is - * enabled for the parser. - */ - int32_t getCaseSensitivePrefixLength(const UnicodeString& other); - - bool operator==(const UnicodeString& other) const; - - private: - const UnicodeString& fStr; - int32_t fStart; - int32_t fEnd; - bool fFoldCase; - - int32_t getPrefixLengthInternal(const UnicodeString& other, bool foldCase); - - static bool codePointsEqual(UChar32 cp1, UChar32 cp2, bool foldCase); -}; - - /** * The core interface implemented by all matchers used for number parsing. * diff -Nru icu-64.2/source/i18n/numrange_fluent.cpp icu-65.1/source/i18n/numrange_fluent.cpp --- icu-64.2/source/i18n/numrange_fluent.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numrange_fluent.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -382,7 +382,7 @@ UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE) // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool - return fData->getStringRef().nextFieldPosition(fieldPosition, status) ? TRUE : FALSE; + return fData->nextFieldPosition(fieldPosition, status); } void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { @@ -393,7 +393,7 @@ void FormattedNumberRange::getAllFieldPositionsImpl( FieldPositionIteratorHandler& fpih, UErrorCode& status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG) - fData->getStringRef().getAllFieldPositions(fpih, status); + fData->getAllFieldPositions(fpih, status); } UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const { diff -Nru icu-64.2/source/i18n/numrange_impl.cpp icu-65.1/source/i18n/numrange_impl.cpp --- icu-64.2/source/i18n/numrange_impl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numrange_impl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -397,7 +397,7 @@ break; } - NumberStringBuilder& string = data.getStringRef(); + FormattedStringBuilder& string = data.getStringRef(); int32_t lengthPrefix = 0; int32_t length1 = 0; int32_t lengthInfix = 0; diff -Nru icu-64.2/source/i18n/numrange_impl.h icu-65.1/source/i18n/numrange_impl.h --- icu-64.2/source/i18n/numrange_impl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numrange_impl.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,7 +13,7 @@ #include "number_types.h" #include "number_decimalquantity.h" #include "number_formatimpl.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "formattedval_impl.h" U_NAMESPACE_BEGIN namespace number { @@ -29,9 +29,9 @@ * Possible magic number: 0x46445200 * Reads in ASCII as "FDR" (FormatteDnumberRange with room at the end) */ -class UFormattedNumberRangeData : public FormattedValueNumberStringBuilderImpl { +class UFormattedNumberRangeData : public FormattedValueStringBuilderImpl { public: - UFormattedNumberRangeData() : FormattedValueNumberStringBuilderImpl(0) {} + UFormattedNumberRangeData() : FormattedValueStringBuilderImpl(0) {} virtual ~UFormattedNumberRangeData(); DecimalQuantity quantity1; diff -Nru icu-64.2/source/i18n/numsys.cpp icu-65.1/source/i18n/numsys.cpp --- icu-64.2/source/i18n/numsys.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/numsys.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -37,7 +37,7 @@ // Useful constants -#define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789"); +#define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789") static const char gNumberingSystems[] = "numberingSystems"; static const char gNumberElements[] = "NumberElements"; static const char gDefault[] = "default"; diff -Nru icu-64.2/source/i18n/olsontz.cpp icu-65.1/source/i18n/olsontz.cpp --- icu-64.2/source/i18n/olsontz.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/olsontz.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -287,8 +287,7 @@ typeMapData = other.typeMapData; delete finalZone; - finalZone = (other.finalZone != 0) ? - (SimpleTimeZone*) other.finalZone->clone() : 0; + finalZone = (other.finalZone != 0) ? other.finalZone->clone() : 0; finalStartYear = other.finalStartYear; finalStartMillis = other.finalStartMillis; @@ -319,7 +318,7 @@ /** * TimeZone API. */ -TimeZone* OlsonTimeZone::clone() const { +OlsonTimeZone* OlsonTimeZone::clone() const { return new OlsonTimeZone(*this); } @@ -816,7 +815,7 @@ * For now, we do not set the valid start year when the construction time * and create a clone and set the start year when extracting rules. */ - finalZoneWithStartYear = (SimpleTimeZone*)finalZone->clone(); + finalZoneWithStartYear = finalZone->clone(); // Check to make sure finalZone was actually cloned. if (finalZoneWithStartYear == NULL) { status = U_MEMORY_ALLOCATION_ERROR; @@ -837,7 +836,7 @@ startTime = tzt.getTime(); } else { // final rule with no transitions - finalZoneWithStartYear = (SimpleTimeZone*)finalZone->clone(); + finalZoneWithStartYear = finalZone->clone(); // Check to make sure finalZone was actually cloned. if (finalZoneWithStartYear == NULL) { status = U_MEMORY_ALLOCATION_ERROR; diff -Nru icu-64.2/source/i18n/olsontz.h icu-65.1/source/i18n/olsontz.h --- icu-64.2/source/i18n/olsontz.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/olsontz.h 2019-10-03 11:16:41.000000000 +0000 @@ -151,7 +151,7 @@ /** * TimeZone API. */ - virtual TimeZone* clone() const; + virtual OlsonTimeZone* clone() const; /** * TimeZone API. @@ -398,7 +398,7 @@ TimeArrayTimeZoneRule **historicRules; int16_t historicRuleCount; SimpleTimeZone *finalZoneWithStartYear; // hack - UInitOnce transitionRulesInitOnce; + UInitOnce transitionRulesInitOnce = U_INITONCE_INITIALIZER; }; inline int16_t diff -Nru icu-64.2/source/i18n/persncal.cpp icu-65.1/source/i18n/persncal.cpp --- icu-64.2/source/i18n/persncal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/persncal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -74,7 +74,7 @@ return "persian"; } -Calendar* PersianCalendar::clone() const { +PersianCalendar* PersianCalendar::clone() const { return new PersianCalendar(*this); } diff -Nru icu-64.2/source/i18n/persncal.h icu-65.1/source/i18n/persncal.h --- icu-64.2/source/i18n/persncal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/persncal.h 2019-10-03 11:16:41.000000000 +0000 @@ -164,7 +164,7 @@ // TODO: copy c'tor, etc // clone - virtual Calendar* clone() const; + virtual PersianCalendar* clone() const; private: /** diff -Nru icu-64.2/source/i18n/plurfmt.cpp icu-65.1/source/i18n/plurfmt.cpp --- icu-64.2/source/i18n/plurfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/plurfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -159,7 +159,7 @@ if (other.numberFormat == NULL) { numberFormat = NumberFormat::createInstance(locale, status); } else { - numberFormat = (NumberFormat*)other.numberFormat->clone(); + numberFormat = other.numberFormat->clone(); } if (other.pluralRulesWrapper.pluralRules == NULL) { pluralRulesWrapper.pluralRules = PluralRules::forLocale(locale, status); @@ -277,7 +277,14 @@ UnicodeString numberString; auto *decFmt = dynamic_cast(numberFormat); if(decFmt != nullptr) { - decFmt->toNumberFormatter().formatImpl(&data, status); // mutates &data + const number::LocalizedNumberFormatter* lnf = decFmt->toNumberFormatter(status); + if (U_FAILURE(status)) { + return appendTo; + } + lnf->formatImpl(&data, status); // mutates &data + if (U_FAILURE(status)) { + return appendTo; + } numberString = data.getStringRef().toUnicodeString(); } else { if (offset == 0) { @@ -346,7 +353,7 @@ if (U_FAILURE(status)) { return; } - NumberFormat* nf = (NumberFormat*)format->clone(); + NumberFormat* nf = format->clone(); if (nf != NULL) { delete numberFormat; numberFormat = nf; @@ -355,7 +362,7 @@ } } -Format* +PluralFormat* PluralFormat::clone() const { return new PluralFormat(*this); diff -Nru icu-64.2/source/i18n/quant.cpp icu-65.1/source/i18n/quant.cpp --- icu-64.2/source/i18n/quant.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/quant.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -47,7 +47,7 @@ /** * Implement UnicodeFunctor */ -UnicodeFunctor* Quantifier::clone() const { +Quantifier* Quantifier::clone() const { return new Quantifier(*this); } diff -Nru icu-64.2/source/i18n/quant.h icu-65.1/source/i18n/quant.h --- icu-64.2/source/i18n/quant.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/quant.h 2019-10-03 11:16:41.000000000 +0000 @@ -45,7 +45,7 @@ * Implement UnicodeFunctor * @return a copy of the object. */ - virtual UnicodeFunctor* clone() const; + virtual Quantifier* clone() const; /** * Implement UnicodeMatcher diff -Nru icu-64.2/source/i18n/quantityformatter.cpp icu-65.1/source/i18n/quantityformatter.cpp --- icu-64.2/source/i18n/quantityformatter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/quantityformatter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -26,7 +26,7 @@ #include "uassert.h" #include "number_decimalquantity.h" #include "number_utypes.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" U_NAMESPACE_BEGIN @@ -180,7 +180,7 @@ double quantity, const NumberFormat& fmt, const PluralRules& rules, - number::impl::NumberStringBuilder& output, + FormattedStringBuilder& output, StandardPlural::Form& pluralForm, UErrorCode& status) { UnicodeString pluralKeyword; @@ -188,7 +188,11 @@ if (df != nullptr) { number::impl::UFormattedNumberData fn; fn.quantity.setToDouble(quantity); - df->toNumberFormatter().formatImpl(&fn, status); + const number::LocalizedNumberFormatter* lnf = df->toNumberFormatter(status); + if (U_FAILURE(status)) { + return; + } + lnf->formatImpl(&fn, status); if (U_FAILURE(status)) { return; } diff -Nru icu-64.2/source/i18n/quantityformatter.h icu-65.1/source/i18n/quantityformatter.h --- icu-64.2/source/i18n/quantityformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/quantityformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,12 +26,7 @@ class NumberFormat; class Formattable; class FieldPosition; - -namespace number { -namespace impl { -class NumberStringBuilder; -} -} +class FormattedStringBuilder; /** * A plural aware formatter that is good for expressing a single quantity and @@ -129,7 +124,7 @@ /** * Formats a quantity and selects its plural form. The output is appended - * to a NumberStringBuilder in order to retain field information. + * to a FormattedStringBuilder in order to retain field information. * * @param quantity The number to format. * @param fmt The formatter to use to format the number. @@ -144,7 +139,7 @@ double quantity, const NumberFormat& fmt, const PluralRules& rules, - number::impl::NumberStringBuilder& output, + FormattedStringBuilder& output, StandardPlural::Form& pluralForm, UErrorCode& status); diff -Nru icu-64.2/source/i18n/rbnf.cpp icu-65.1/source/i18n/rbnf.cpp --- icu-64.2/source/i18n/rbnf.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rbnf.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -355,10 +355,16 @@ }; #ifdef RBNF_DEBUG -#define ERROR(msg) parseError(msg); return NULL; +#define ERROR(msg) UPRV_BLOCK_MACRO_BEGIN { \ + parseError(msg); \ + return NULL; \ +} UPRV_BLOCK_MACRO_END #define EXPLANATION_ARG explanationArg #else -#define ERROR(msg) parseError(NULL); return NULL; +#define ERROR(msg) UPRV_BLOCK_MACRO_BEGIN { \ + parseError(NULL); \ + return NULL; \ +} UPRV_BLOCK_MACRO_END #define EXPLANATION_ARG #endif @@ -924,8 +930,8 @@ dispose(); } -Format* -RuleBasedNumberFormat::clone(void) const +RuleBasedNumberFormat* +RuleBasedNumberFormat::clone() const { return new RuleBasedNumberFormat(*this); } @@ -1112,45 +1118,6 @@ UnicodeString& RuleBasedNumberFormat::format(const DecimalQuantity &number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return appendTo; - } - DecimalQuantity copy(number); - if (copy.fitsInLong()) { - format(number.toLong(), appendTo, posIter, status); - } - else { - copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status); - if (copy.fitsInLong()) { - format(number.toDouble(), appendTo, posIter, status); - } - else { - // We're outside of our normal range that this framework can handle. - // The DecimalFormat will provide more accurate results. - - // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J. - LocalPointer decimalFormat(NumberFormat::createInstance(locale, UNUM_DECIMAL, status), status); - if (decimalFormat.isNull()) { - return appendTo; - } - Formattable f; - LocalPointer decimalQuantity(new DecimalQuantity(number), status); - if (decimalQuantity.isNull()) { - return appendTo; - } - f.adoptDecimalQuantity(decimalQuantity.orphan()); // f now owns decimalQuantity. - decimalFormat->format(f, appendTo, posIter, status); - } - } - return appendTo; -} - - -UnicodeString& -RuleBasedNumberFormat::format(const DecimalQuantity &number, UnicodeString& appendTo, FieldPosition& pos, UErrorCode &status) const { diff -Nru icu-64.2/source/i18n/rbt.cpp icu-65.1/source/i18n/rbt.cpp --- icu-64.2/source/i18n/rbt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rbt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -191,8 +191,8 @@ } } -Transliterator* // Covariant return NOT ALLOWED (for portability) -RuleBasedTransliterator::clone(void) const { +RuleBasedTransliterator* +RuleBasedTransliterator::clone() const { return new RuleBasedTransliterator(*this); } @@ -253,7 +253,7 @@ // // TODO(andy): Need a better scheme for handling this. - static UMutex transliteratorDataMutex = U_MUTEX_INITIALIZER; + static UMutex transliteratorDataMutex; UBool needToLock; { Mutex m; diff -Nru icu-64.2/source/i18n/rbt.h icu-65.1/source/i18n/rbt.h --- icu-64.2/source/i18n/rbt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rbt.h 2019-10-03 11:16:41.000000000 +0000 @@ -144,7 +144,7 @@ * Implement Transliterator API. * @internal Use transliterator factory methods instead since this class will be removed in that release. */ - virtual Transliterator* clone(void) const; + virtual RuleBasedTransliterator* clone() const; protected: /** diff -Nru icu-64.2/source/i18n/rbt_pars.cpp icu-65.1/source/i18n/rbt_pars.cpp --- icu-64.2/source/i18n/rbt_pars.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rbt_pars.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1111,7 +1111,7 @@ int32_t p = UHASH_FIRST; const UHashElement* he = variableNames.nextElement(p); while (he != NULL) { - UnicodeString* tempus = (UnicodeString*)(((UnicodeString*)(he->value.pointer))->clone()); + UnicodeString* tempus = ((UnicodeString*)(he->value.pointer))->clone(); if (tempus == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; diff -Nru icu-64.2/source/i18n/rbt_rule.cpp icu-65.1/source/i18n/rbt_rule.cpp --- icu-64.2/source/i18n/rbt_rule.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rbt_rule.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -180,13 +180,13 @@ } if (other.anteContext != NULL) { - anteContext = (StringMatcher*) other.anteContext->clone(); + anteContext = other.anteContext->clone(); } if (other.key != NULL) { - key = (StringMatcher*) other.key->clone(); + key = other.key->clone(); } if (other.postContext != NULL) { - postContext = (StringMatcher*) other.postContext->clone(); + postContext = other.postContext->clone(); } output = other.output->clone(); } diff -Nru icu-64.2/source/i18n/rbtz.cpp icu-65.1/source/i18n/rbtz.cpp --- icu-64.2/source/i18n/rbtz.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rbtz.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -149,7 +149,7 @@ void RuleBasedTimeZone::completeConst(UErrorCode& status) const { - static UMutex gLock = U_MUTEX_INITIALIZER; + static UMutex gLock; if (U_FAILURE(status)) { return; } @@ -356,8 +356,8 @@ fUpToDate = FALSE; } -TimeZone* -RuleBasedTimeZone::clone(void) const { +RuleBasedTimeZone* +RuleBasedTimeZone::clone() const { return new RuleBasedTimeZone(*this); } diff -Nru icu-64.2/source/i18n/regexcmp.cpp icu-65.1/source/i18n/regexcmp.cpp --- icu-64.2/source/i18n/regexcmp.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/regexcmp.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -561,7 +561,7 @@ // sequence; don't change without making updates there too. // // Compiles to - // 1 START_LA dataLoc Saves SP, Input Pos + // 1 LA_START dataLoc Saves SP, Input Pos, Active input region. // 2. STATE_SAVE 4 on failure of lookahead, goto 4 // 3 JMP 6 continue ... // @@ -575,10 +575,14 @@ // 8. code for parenthesized stuff. // 9. LA_END // - // Two data slots are reserved, for saving the stack ptr and the input position. + // Four data slots are reserved, for saving state on entry to the look-around + // 0: stack pointer on entry. + // 1: input position on entry. + // 2: fActiveStart, the active bounds start on entry. + // 3: fActiveLimit, the active bounds limit on entry. { fixLiterals(); - int32_t dataLoc = allocateData(2); + int32_t dataLoc = allocateData(4); appendOp(URX_LA_START, dataLoc); appendOp(URX_STATE_SAVE, fRXPat->fCompiledPat->size()+ 2); appendOp(URX_JMP, fRXPat->fCompiledPat->size()+ 3); @@ -599,18 +603,23 @@ case doOpenLookAheadNeg: // Negated Lookahead. (?! stuff ) // Compiles to - // 1. START_LA dataloc + // 1. LA_START dataloc // 2. SAVE_STATE 7 // Fail within look-ahead block restores to this state, // // which continues with the match. // 3. NOP // Std. Open Paren sequence, for possible '|' // 4. code for parenthesized stuff. - // 5. END_LA // Cut back stack, remove saved state from step 2. + // 5. LA_END // Cut back stack, remove saved state from step 2. // 6. BACKTRACK // code in block succeeded, so neg. lookahead fails. // 7. END_LA // Restore match region, in case look-ahead was using // an alternate (transparent) region. + // Four data slots are reserved, for saving state on entry to the look-around + // 0: stack pointer on entry. + // 1: input position on entry. + // 2: fActiveStart, the active bounds start on entry. + // 3: fActiveLimit, the active bounds limit on entry. { fixLiterals(); - int32_t dataLoc = allocateData(2); + int32_t dataLoc = allocateData(4); appendOp(URX_LA_START, dataLoc); appendOp(URX_STATE_SAVE, 0); // dest address will be patched later. appendOp(URX_NOP, 0); @@ -644,14 +653,16 @@ // Allocate a block of matcher data, to contain (when running a match) // 0: Stack ptr on entry // 1: Input Index on entry - // 2: Start index of match current match attempt. - // 3: Original Input String len. + // 2: fActiveStart, the active bounds start on entry. + // 3: fActiveLimit, the active bounds limit on entry. + // 4: Start index of match current match attempt. + // The first four items must match the layout of data for LA_START / LA_END // Generate match code for any pending literals. fixLiterals(); // Allocate data space - int32_t dataLoc = allocateData(4); + int32_t dataLoc = allocateData(5); // Emit URX_LB_START appendOp(URX_LB_START, dataLoc); @@ -696,14 +707,16 @@ // Allocate a block of matcher data, to contain (when running a match) // 0: Stack ptr on entry // 1: Input Index on entry - // 2: Start index of match current match attempt. - // 3: Original Input String len. + // 2: fActiveStart, the active bounds start on entry. + // 3: fActiveLimit, the active bounds limit on entry. + // 4: Start index of match current match attempt. + // The first four items must match the layout of data for LA_START / LA_END // Generate match code for any pending literals. fixLiterals(); // Allocate data space - int32_t dataLoc = allocateData(4); + int32_t dataLoc = allocateData(5); // Emit URX_LB_START appendOp(URX_LB_START, dataLoc); @@ -2285,7 +2298,7 @@ error(U_REGEX_LOOK_BEHIND_LIMIT); break; } - if (minML == INT32_MAX && maxML == 0) { + if (minML == INT32_MAX) { // This condition happens when no match is possible, such as with a // [set] expression containing no elements. // In principle, the generated code to evaluate the expression could be deleted, @@ -2328,7 +2341,7 @@ error(U_REGEX_LOOK_BEHIND_LIMIT); break; } - if (minML == INT32_MAX && maxML == 0) { + if (minML == INT32_MAX) { // This condition happens when no match is possible, such as with a // [set] expression containing no elements. // In principle, the generated code to evaluate the expression could be deleted, @@ -3381,7 +3394,7 @@ // it assumes that the look-ahead match might be zero-length. // TODO: Positive lookahead could recursively do the block, then continue // with the longer of the block or the value coming in. Ticket 6060 - int32_t depth = (opType == URX_LA_START? 2: 1);; + int32_t depth = (opType == URX_LA_START? 2: 1); for (;;) { loc++; op = (int32_t)fRXPat->fCompiledPat->elementAti(loc); @@ -3463,7 +3476,6 @@ U_ASSERT(start <= end); U_ASSERT(end < fRXPat->fCompiledPat->size()); - int32_t loc; int32_t op; int32_t opType; @@ -3672,7 +3684,7 @@ case URX_CTR_LOOP: case URX_CTR_LOOP_NG: - // These opcodes will be skipped over by code for URX_CRT_INIT. + // These opcodes will be skipped over by code for URX_CTR_INIT. // We shouldn't encounter them here. UPRV_UNREACHABLE; @@ -3700,21 +3712,15 @@ { // Look-behind. Scan forward until the matching look-around end, // without processing the look-behind block. - int32_t depth = 0; - for (;;) { - loc++; + int32_t dataLoc = URX_VAL(op); + for (loc = loc + 1; loc < end; ++loc) { op = (int32_t)fRXPat->fCompiledPat->elementAti(loc); - if (URX_TYPE(op) == URX_LA_START || URX_TYPE(op) == URX_LB_START) { - depth++; - } - if (URX_TYPE(op) == URX_LA_END || URX_TYPE(op)==URX_LBN_END) { - if (depth == 0) { - break; - } - depth--; + int32_t opType = URX_TYPE(op); + if ((opType == URX_LA_END || opType == URX_LBN_END) && (URX_VAL(op) == dataLoc)) { + break; } - U_ASSERT(loc < end); } + U_ASSERT(loc < end); } break; diff -Nru icu-64.2/source/i18n/regeximp.h icu-65.1/source/i18n/regeximp.h --- icu-64.2/source/i18n/regeximp.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/regeximp.h 2019-10-03 11:16:41.000000000 +0000 @@ -123,7 +123,7 @@ // saved input position, FAIL rather than taking // the JMP URX_LA_START = 37, // Starting a LookAround expression. - // Save InputPos and SP in static data. + // Save InputPos, SP and active region in static data. // Operand: Static data offset for the save URX_LA_END = 38, // Ending a Lookaround expression. // Restore InputPos and Stack to saved values. diff -Nru icu-64.2/source/i18n/region.cpp icu-65.1/source/i18n/region.cpp --- icu-64.2/source/i18n/region.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/region.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -25,7 +25,6 @@ #include "unicode/uobject.h" #include "unicode/unistr.h" #include "unicode/ures.h" -#include "unicode/decimfmt.h" #include "ucln_in.h" #include "cstring.h" #include "mutex.h" @@ -33,6 +32,7 @@ #include "umutex.h" #include "uresimp.h" #include "region_impl.h" +#include "util.h" #if !UCONFIG_NO_FORMATTING @@ -87,7 +87,6 @@ LocalUHashtablePointer newRegionIDMap(uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status)); LocalUHashtablePointer newNumericCodeMap(uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status)); LocalUHashtablePointer newRegionAliases(uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status)); - LocalPointer df(new DecimalFormat(status), status); LocalPointer continents(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); LocalPointer groupings(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); @@ -115,7 +114,6 @@ } // now, initialize - df->setParseIntegerOnly(TRUE); uhash_setValueDeleter(newRegionIDMap.getAlias(), deleteRegion); // regionIDMap owns objs uhash_setKeyDeleter(newRegionAliases.getAlias(), uprv_deleteUObject); // regionAliases owns the string keys @@ -192,11 +190,10 @@ r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); r->fType = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. - Formattable result; - UErrorCode ps = U_ZERO_ERROR; - df->parse(r->idStr,result,ps); - if ( U_SUCCESS(ps) ) { - r->code = result.getLong(); // Convert string to number + int32_t pos = 0; + int32_t result = ICU_Utility::parseAsciiInteger(r->idStr, pos); + if (pos > 0) { + r->code = result; // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)(r.getAlias()),&status); r->fType = URGN_SUBCONTINENT; } else { @@ -230,11 +227,10 @@ aliasFromRegion->idStr.setTo(*aliasFromStr); aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV); uhash_put(newRegionIDMap.getAlias(),(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); - Formattable result; - UErrorCode ps = U_ZERO_ERROR; - df->parse(aliasFromRegion->idStr,result,ps); - if ( U_SUCCESS(ps) ) { - aliasFromRegion->code = result.getLong(); // Convert string to number + int32_t pos = 0; + int32_t result = ICU_Utility::parseAsciiInteger(aliasFromRegion->idStr, pos); + if ( pos > 0 ) { + aliasFromRegion->code = result; // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),aliasFromRegion->code,(void *)aliasFromRegion,&status); } else { aliasFromRegion->code = -1; @@ -279,11 +275,10 @@ Region *r = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)&codeMappingID); if ( r ) { - Formattable result; - UErrorCode ps = U_ZERO_ERROR; - df->parse(codeMappingNumber,result,ps); - if ( U_SUCCESS(ps) ) { - r->code = result.getLong(); // Convert string to number + int32_t pos = 0; + int32_t result = ICU_Utility::parseAsciiInteger(codeMappingNumber, pos); + if ( pos > 0 ) { + r->code = result; // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)r,&status); } LocalPointer code3(new UnicodeString(codeMapping3Letter), status); @@ -516,15 +511,8 @@ Region *r = (Region *)uhash_iget(numericCodeMap,code); if ( !r ) { // Just in case there's an alias that's numeric, try to find it. - UnicodeString pat = UNICODE_STRING_SIMPLE("0"); - LocalPointer df(new DecimalFormat(pat,status), status); - if( U_FAILURE(status) ) { - return NULL; - } UnicodeString id; - id.remove(); - FieldPosition posIter; - df->format(code,id, posIter, status); + ICU_Utility::appendNumber(id, code, 10, 1); r = (Region *)uhash_get(regionAliases,&id); } diff -Nru icu-64.2/source/i18n/reldatefmt.cpp icu-65.1/source/i18n/reldatefmt.cpp --- icu-64.2/source/i18n/reldatefmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/reldatefmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -43,7 +43,7 @@ #include "standardplural.h" #include "unifiedcache.h" #include "util.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "number_utypes.h" #include "number_modifiers.h" #include "formattedval_impl.h" @@ -315,6 +315,10 @@ return UDAT_ABSOLUTE_FRIDAY; case SATURDAY: return UDAT_ABSOLUTE_SATURDAY; + case HOUR: + return UDAT_ABSOLUTE_HOUR; + case MINUTE: + return UDAT_ABSOLUTE_MINUTE; default: return -1; } @@ -725,14 +729,14 @@ static constexpr number::impl::Field kRDTNumericField - = number::impl::NumFieldUtils::compress(); + = StringBuilderFieldUtils::compress(); static constexpr number::impl::Field kRDTLiteralField - = number::impl::NumFieldUtils::compress(); + = StringBuilderFieldUtils::compress(); -class FormattedRelativeDateTimeData : public FormattedValueNumberStringBuilderImpl { +class FormattedRelativeDateTimeData : public FormattedValueStringBuilderImpl { public: - FormattedRelativeDateTimeData() : FormattedValueNumberStringBuilderImpl(kRDTNumericField) {} + FormattedRelativeDateTimeData() : FormattedValueStringBuilderImpl(kRDTNumericField) {} virtual ~FormattedRelativeDateTimeData(); }; @@ -1157,6 +1161,8 @@ case UDAT_REL_UNIT_THURSDAY: absunit = UDAT_ABSOLUTE_THURSDAY; break; case UDAT_REL_UNIT_FRIDAY: absunit = UDAT_ABSOLUTE_FRIDAY; break; case UDAT_REL_UNIT_SATURDAY: absunit = UDAT_ABSOLUTE_SATURDAY; break; + case UDAT_REL_UNIT_HOUR: absunit = UDAT_ABSOLUTE_HOUR; break; + case UDAT_REL_UNIT_MINUTE: absunit = UDAT_ABSOLUTE_MINUTE; break; default: break; } if (direction != UDAT_DIRECTION_COUNT && absunit != UDAT_ABSOLUTE_UNIT_COUNT) { @@ -1184,7 +1190,7 @@ // Must guarantee that one thread at a time accesses the shared break // iterator. - static icu::UMutex gBrkIterMutex = U_MUTEX_INITIALIZER; + static UMutex gBrkIterMutex; Mutex lock(&gBrkIterMutex); str.toTitle( fOptBreakIterator->get(), diff -Nru icu-64.2/source/i18n/reldtfmt.cpp icu-65.1/source/i18n/reldtfmt.cpp --- icu-64.2/source/i18n/reldtfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/reldtfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -51,7 +51,7 @@ fCapitalizationBrkIter(NULL) { if(other.fDateTimeFormatter != NULL) { - fDateTimeFormatter = (SimpleDateFormat*)other.fDateTimeFormatter->clone(); + fDateTimeFormatter = other.fDateTimeFormatter->clone(); } if(other.fCombinedFormat != NULL) { fCombinedFormat = new SimpleFormatter(*other.fCombinedFormat); @@ -131,7 +131,7 @@ } -Format* RelativeDateFormat::clone(void) const { +RelativeDateFormat* RelativeDateFormat::clone() const { return new RelativeDateFormat(*this); } diff -Nru icu-64.2/source/i18n/reldtfmt.h icu-65.1/source/i18n/reldtfmt.h --- icu-64.2/source/i18n/reldtfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/reldtfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -71,7 +71,7 @@ * @return A copy of the object. * @internal ICU 3.8 */ - virtual Format* clone(void) const; + virtual RelativeDateFormat* clone() const; /** * Return true if the given Format objects are semantically equal. Objects diff -Nru icu-64.2/source/i18n/rematch.cpp icu-65.1/source/i18n/rematch.cpp --- icu-64.2/source/i18n/rematch.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rematch.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -2069,7 +2069,7 @@ // if (U_FAILURE(status)) { return 0; - }; + } if (destCapacity < 1) { status = U_ILLEGAL_ARGUMENT_ERROR; @@ -3805,11 +3805,13 @@ case URX_LA_START: { - // Entering a lookahead block. + // Entering a look around block. // Save Stack Ptr, Input Pos. - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+3fDataSize); fData[opValue] = fStack->size(); fData[opValue+1] = fp->fInputIdx; + fData[opValue+2] = fActiveStart; + fData[opValue+3] = fActiveLimit; fActiveStart = fLookStart; // Set the match region change for fActiveLimit = fLookLimit; // transparent bounds. } @@ -3819,7 +3821,7 @@ { // Leaving a look-ahead block. // restore Stack Ptr, Input Pos to positions they had on entry to block. - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+3fDataSize); int32_t stackSize = fStack->size(); int32_t newStackSize =(int32_t)fData[opValue]; U_ASSERT(stackSize >= newStackSize); @@ -3839,8 +3841,10 @@ // Restore the active region bounds in the input string; they may have // been changed because of transparent bounds on a Region. - fActiveStart = fRegionStart; - fActiveLimit = fRegionLimit; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); } break; @@ -3916,17 +3920,19 @@ case URX_LB_START: { // Entering a look-behind block. - // Save Stack Ptr, Input Pos. + // Save Stack Ptr, Input Pos and active input region. // TODO: implement transparent bounds. Ticket #6067 - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+4fDataSize); fData[opValue] = fStack->size(); fData[opValue+1] = fp->fInputIdx; - // Init the variable containing the start index for attempted matches. - fData[opValue+2] = -1; // Save input string length, then reset to pin any matches to end at // the current position. + fData[opValue+2] = fActiveStart; fData[opValue+3] = fActiveLimit; + fActiveStart = fRegionStart; fActiveLimit = fp->fInputIdx; + // Init the variable containing the start index for attempted matches. + fData[opValue+4] = -1; } break; @@ -3949,8 +3955,8 @@ U_ASSERT(minML >= 0); // Fetch (from data) the last input index where a match was attempted. - U_ASSERT(opValue>=0 && opValue+1fDataSize); - int64_t &lbStartIdx = fData[opValue+2]; + U_ASSERT(opValue>=0 && opValue+4fDataSize); + int64_t &lbStartIdx = fData[opValue+4]; if (lbStartIdx < 0) { // First time through loop. lbStartIdx = fp->fInputIdx - minML; @@ -3976,10 +3982,10 @@ // getting a match. Backtrack out, and out of the // Look Behind altogether. fp = (REStackFrame *)fStack->popFrame(fFrameSize); - int64_t restoreInputLen = fData[opValue+3]; - U_ASSERT(restoreInputLen >= fActiveLimit); - U_ASSERT(restoreInputLen <= fInputLength); - fActiveLimit = restoreInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); break; } @@ -3993,7 +3999,7 @@ case URX_LB_END: // End of a look-behind block, after a successful match. { - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+4fDataSize); if (fp->fInputIdx != fActiveLimit) { // The look-behind expression matched, but the match did not // extend all the way to the point that we are looking behind from. @@ -4004,13 +4010,13 @@ break; } - // Look-behind match is good. Restore the orignal input string length, + // Look-behind match is good. Restore the orignal input string region, // which had been truncated to pin the end of the lookbehind match to the // position being looked-behind. - int64_t originalInputLen = fData[opValue+3]; - U_ASSERT(originalInputLen >= fActiveLimit); - U_ASSERT(originalInputLen <= fInputLength); - fActiveLimit = originalInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); } break; @@ -4035,8 +4041,8 @@ U_ASSERT(continueLoc > fp->fPatIdx); // Fetch (from data) the last input index where a match was attempted. - U_ASSERT(opValue>=0 && opValue+1fDataSize); - int64_t &lbStartIdx = fData[opValue+2]; + U_ASSERT(opValue>=0 && opValue+4fDataSize); + int64_t &lbStartIdx = fData[opValue+4]; if (lbStartIdx < 0) { // First time through loop. lbStartIdx = fp->fInputIdx - minML; @@ -4061,10 +4067,10 @@ // We have tried all potential match starting points without // getting a match, which means that the negative lookbehind as // a whole has succeeded. Jump forward to the continue location - int64_t restoreInputLen = fData[opValue+3]; - U_ASSERT(restoreInputLen >= fActiveLimit); - U_ASSERT(restoreInputLen <= fInputLength); - fActiveLimit = restoreInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); fp->fPatIdx = continueLoc; break; } @@ -4079,7 +4085,7 @@ case URX_LBN_END: // End of a negative look-behind block, after a successful match. { - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+4fDataSize); if (fp->fInputIdx != fActiveLimit) { // The look-behind expression matched, but the match did not // extend all the way to the point that we are looking behind from. @@ -4096,10 +4102,10 @@ // Restore the orignal input string length, which had been truncated // inorder to pin the end of the lookbehind match // to the position being looked-behind. - int64_t originalInputLen = fData[opValue+3]; - U_ASSERT(originalInputLen >= fActiveLimit); - U_ASSERT(originalInputLen <= fInputLength); - fActiveLimit = originalInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); // Restore original stack position, discarding any state saved // by the successful pattern match. @@ -5336,11 +5342,13 @@ case URX_LA_START: { - // Entering a lookahead block. + // Entering a look around block. // Save Stack Ptr, Input Pos. - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+3fDataSize); fData[opValue] = fStack->size(); fData[opValue+1] = fp->fInputIdx; + fData[opValue+2] = fActiveStart; + fData[opValue+3] = fActiveLimit; fActiveStart = fLookStart; // Set the match region change for fActiveLimit = fLookLimit; // transparent bounds. } @@ -5348,9 +5356,9 @@ case URX_LA_END: { - // Leaving a look-ahead block. + // Leaving a look around block. // restore Stack Ptr, Input Pos to positions they had on entry to block. - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+3fDataSize); int32_t stackSize = fStack->size(); int32_t newStackSize = (int32_t)fData[opValue]; U_ASSERT(stackSize >= newStackSize); @@ -5370,8 +5378,10 @@ // Restore the active region bounds in the input string; they may have // been changed because of transparent bounds on a Region. - fActiveStart = fRegionStart; - fActiveLimit = fRegionLimit; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); } break; @@ -5434,17 +5444,19 @@ case URX_LB_START: { // Entering a look-behind block. - // Save Stack Ptr, Input Pos. + // Save Stack Ptr, Input Pos and active input region. // TODO: implement transparent bounds. Ticket #6067 - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+4fDataSize); fData[opValue] = fStack->size(); fData[opValue+1] = fp->fInputIdx; - // Init the variable containing the start index for attempted matches. - fData[opValue+2] = -1; // Save input string length, then reset to pin any matches to end at // the current position. + fData[opValue+2] = fActiveStart; fData[opValue+3] = fActiveLimit; + fActiveStart = fRegionStart; fActiveLimit = fp->fInputIdx; + // Init the variable containing the start index for attempted matches. + fData[opValue+4] = -1; } break; @@ -5462,8 +5474,8 @@ U_ASSERT(minML >= 0); // Fetch (from data) the last input index where a match was attempted. - U_ASSERT(opValue>=0 && opValue+1fDataSize); - int64_t &lbStartIdx = fData[opValue+2]; + U_ASSERT(opValue>=0 && opValue+4fDataSize); + int64_t &lbStartIdx = fData[opValue+4]; if (lbStartIdx < 0) { // First time through loop. lbStartIdx = fp->fInputIdx - minML; @@ -5485,10 +5497,10 @@ // getting a match. Backtrack out, and out of the // Look Behind altogether. fp = (REStackFrame *)fStack->popFrame(fFrameSize); - int64_t restoreInputLen = fData[opValue+3]; - U_ASSERT(restoreInputLen >= fActiveLimit); - U_ASSERT(restoreInputLen <= fInputLength); - fActiveLimit = restoreInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); break; } @@ -5502,7 +5514,7 @@ case URX_LB_END: // End of a look-behind block, after a successful match. { - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+4fDataSize); if (fp->fInputIdx != fActiveLimit) { // The look-behind expression matched, but the match did not // extend all the way to the point that we are looking behind from. @@ -5513,13 +5525,13 @@ break; } - // Look-behind match is good. Restore the orignal input string length, + // Look-behind match is good. Restore the orignal input string region, // which had been truncated to pin the end of the lookbehind match to the // position being looked-behind. - int64_t originalInputLen = fData[opValue+3]; - U_ASSERT(originalInputLen >= fActiveLimit); - U_ASSERT(originalInputLen <= fInputLength); - fActiveLimit = originalInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); } break; @@ -5539,8 +5551,8 @@ U_ASSERT(continueLoc > fp->fPatIdx); // Fetch (from data) the last input index where a match was attempted. - U_ASSERT(opValue>=0 && opValue+1fDataSize); - int64_t &lbStartIdx = fData[opValue+2]; + U_ASSERT(opValue>=0 && opValue+4fDataSize); + int64_t &lbStartIdx = fData[opValue+4]; if (lbStartIdx < 0) { // First time through loop. lbStartIdx = fp->fInputIdx - minML; @@ -5561,10 +5573,10 @@ // We have tried all potential match starting points without // getting a match, which means that the negative lookbehind as // a whole has succeeded. Jump forward to the continue location - int64_t restoreInputLen = fData[opValue+3]; - U_ASSERT(restoreInputLen >= fActiveLimit); - U_ASSERT(restoreInputLen <= fInputLength); - fActiveLimit = restoreInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); fp->fPatIdx = continueLoc; break; } @@ -5579,7 +5591,7 @@ case URX_LBN_END: // End of a negative look-behind block, after a successful match. { - U_ASSERT(opValue>=0 && opValue+1fDataSize); + U_ASSERT(opValue>=0 && opValue+4fDataSize); if (fp->fInputIdx != fActiveLimit) { // The look-behind expression matched, but the match did not // extend all the way to the point that we are looking behind from. @@ -5596,10 +5608,10 @@ // Restore the orignal input string length, which had been truncated // inorder to pin the end of the lookbehind match // to the position being looked-behind. - int64_t originalInputLen = fData[opValue+3]; - U_ASSERT(originalInputLen >= fActiveLimit); - U_ASSERT(originalInputLen <= fInputLength); - fActiveLimit = originalInputLen; + fActiveStart = fData[opValue+2]; + fActiveLimit = fData[opValue+3]; + U_ASSERT(fActiveStart >= 0); + U_ASSERT(fActiveLimit <= fInputLength); // Restore original stack position, discarding any state saved // by the successful pattern match. diff -Nru icu-64.2/source/i18n/remtrans.cpp icu-65.1/source/i18n/remtrans.cpp --- icu-64.2/source/i18n/remtrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/remtrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -48,10 +48,10 @@ RemoveTransliterator::~RemoveTransliterator() {} -Transliterator* RemoveTransliterator::clone(void) const { - Transliterator* result = new RemoveTransliterator(); +RemoveTransliterator* RemoveTransliterator::clone() const { + RemoveTransliterator* result = new RemoveTransliterator(); if (result != NULL && getFilter() != 0) { - result->adoptFilter((UnicodeFilter*)(getFilter()->clone())); + result->adoptFilter(getFilter()->clone()); } return result; } diff -Nru icu-64.2/source/i18n/remtrans.h icu-65.1/source/i18n/remtrans.h --- icu-64.2/source/i18n/remtrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/remtrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -47,7 +47,7 @@ * Transliterator API. * @return A copy of the object. */ - virtual Transliterator* clone(void) const; + virtual RemoveTransliterator* clone() const; /** * Implements {@link Transliterator#handleTransliterate}. diff -Nru icu-64.2/source/i18n/repattrn.cpp icu-65.1/source/i18n/repattrn.cpp --- icu-64.2/source/i18n/repattrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/repattrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -646,7 +646,7 @@ { if (U_FAILURE(status)) { return 0; - }; + } RegexMatcher m(this); int32_t r = 0; @@ -667,7 +667,7 @@ { if (U_FAILURE(status)) { return 0; - }; + } RegexMatcher m(this); int32_t r = 0; diff -Nru icu-64.2/source/i18n/rulebasedcollator.cpp icu-65.1/source/i18n/rulebasedcollator.cpp --- icu-64.2/source/i18n/rulebasedcollator.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/rulebasedcollator.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -220,7 +220,7 @@ actualLocaleIsSameAsValid = FALSE; } -Collator * +RuleBasedCollator * RuleBasedCollator::clone() const { return new RuleBasedCollator(*this); } diff -Nru icu-64.2/source/i18n/scientificnumberformatter.cpp icu-65.1/source/i18n/scientificnumberformatter.cpp --- icu-64.2/source/i18n/scientificnumberformatter.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/scientificnumberformatter.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -121,7 +121,7 @@ return result; } -ScientificNumberFormatter::Style *ScientificNumberFormatter::SuperscriptStyle::clone() const { +ScientificNumberFormatter::SuperscriptStyle *ScientificNumberFormatter::SuperscriptStyle::clone() const { return new ScientificNumberFormatter::SuperscriptStyle(*this); } @@ -195,7 +195,7 @@ return appendTo; } -ScientificNumberFormatter::Style *ScientificNumberFormatter::MarkupStyle::clone() const { +ScientificNumberFormatter::MarkupStyle *ScientificNumberFormatter::MarkupStyle::clone() const { return new ScientificNumberFormatter::MarkupStyle(*this); } diff -Nru icu-64.2/source/i18n/selfmt.cpp icu-65.1/source/i18n/selfmt.cpp --- icu-64.2/source/i18n/selfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/selfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -151,7 +151,7 @@ return msgStart; } -Format* SelectFormat::clone() const +SelectFormat* SelectFormat::clone() const { return new SelectFormat(*this); } diff -Nru icu-64.2/source/i18n/simpletz.cpp icu-65.1/source/i18n/simpletz.cpp --- icu-64.2/source/i18n/simpletz.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/simpletz.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -33,6 +33,7 @@ #include "unicode/gregocal.h" #include "unicode/smpdtfmt.h" +#include "cmemory.h" #include "gregoimp.h" #include "umutex.h" @@ -242,7 +243,7 @@ // ------------------------------------- // Called by TimeZone::createDefault() inside a Mutex - be careful. -TimeZone* +SimpleTimeZone* SimpleTimeZone::clone() const { return new SimpleTimeZone(*this); @@ -1083,7 +1084,7 @@ if (U_FAILURE(status)) { return; } - static UMutex gLock = U_MUTEX_INITIALIZER; + static UMutex gLock; umtx_lock(&gLock); if (!transitionRulesInitialized) { SimpleTimeZone *ncThis = const_cast(this); diff -Nru icu-64.2/source/i18n/smpdtfmt.cpp icu-65.1/source/i18n/smpdtfmt.cpp --- icu-64.2/source/i18n/smpdtfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/smpdtfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -230,10 +230,7 @@ static const int32_t HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000; static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000; -static UMutex *LOCK() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex LOCK; UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat) @@ -623,7 +620,7 @@ //---------------------------------------------------------------------- -Format* +SimpleDateFormat* SimpleDateFormat::clone() const { return new SimpleDateFormat(*this); @@ -1223,10 +1220,14 @@ //---------------------------------------------------------------------- static number::LocalizedNumberFormatter* -createFastFormatter(const DecimalFormat* df, int32_t minInt, int32_t maxInt) { - return new number::LocalizedNumberFormatter( - df->toNumberFormatter() - .integerWidth(number::IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt))); +createFastFormatter(const DecimalFormat* df, int32_t minInt, int32_t maxInt, UErrorCode& status) { + const number::LocalizedNumberFormatter* lnfBase = df->toNumberFormatter(status); + if (U_FAILURE(status)) { + return nullptr; + } + return lnfBase->integerWidth( + number::IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt) + ).clone().orphan(); } void SimpleDateFormat::initFastNumberFormatters(UErrorCode& status) { @@ -1237,11 +1238,11 @@ if (df == nullptr) { return; } - fFastNumberFormatters[SMPDTFMT_NF_1x10] = createFastFormatter(df, 1, 10); - fFastNumberFormatters[SMPDTFMT_NF_2x10] = createFastFormatter(df, 2, 10); - fFastNumberFormatters[SMPDTFMT_NF_3x10] = createFastFormatter(df, 3, 10); - fFastNumberFormatters[SMPDTFMT_NF_4x10] = createFastFormatter(df, 4, 10); - fFastNumberFormatters[SMPDTFMT_NF_2x2] = createFastFormatter(df, 2, 2); + fFastNumberFormatters[SMPDTFMT_NF_1x10] = createFastFormatter(df, 1, 10, status); + fFastNumberFormatters[SMPDTFMT_NF_2x10] = createFastFormatter(df, 2, 10, status); + fFastNumberFormatters[SMPDTFMT_NF_3x10] = createFastFormatter(df, 3, 10, status); + fFastNumberFormatters[SMPDTFMT_NF_4x10] = createFastFormatter(df, 4, 10, status); + fFastNumberFormatters[SMPDTFMT_NF_2x2] = createFastFormatter(df, 2, 2, status); } void SimpleDateFormat::freeFastNumberFormatters() { @@ -1266,14 +1267,14 @@ if ( fDateOverride.isBogus() && fTimeOverride.isBogus() ) { return; } - umtx_lock(LOCK()); + umtx_lock(&LOCK); if (fSharedNumberFormatters == NULL) { fSharedNumberFormatters = allocSharedNumberFormatters(); if (fSharedNumberFormatters == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } } - umtx_unlock(LOCK()); + umtx_unlock(&LOCK); if (U_FAILURE(status)) { return; @@ -1980,9 +1981,11 @@ break; } if (titlecase) { + BreakIterator* const mutableCapitalizationBrkIter = fCapitalizationBrkIter->clone(); UnicodeString firstField(appendTo, beginOffset); - firstField.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); + firstField.toTitle(mutableCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); appendTo.replaceBetween(beginOffset, appendTo.length(), firstField); + delete mutableCapitalizationBrkIter; } } #endif @@ -2107,7 +2110,7 @@ // Fall back to slow path (clone and mutate the NumberFormat) if (currentNumberFormat != nullptr) { FieldPosition pos(FieldPosition::DONT_CARE); - LocalPointer nf(dynamic_cast(currentNumberFormat->clone())); + LocalPointer nf(currentNumberFormat->clone()); nf->setMinimumIntegerDigits(minDigits); nf->setMaximumIntegerDigits(maxDigits); nf->format(value, appendTo, pos); // 3rd arg is there to speed up processing @@ -3770,7 +3773,7 @@ auto* fmtAsDF = dynamic_cast(fmt); LocalPointer df; if (!allowNegative && fmtAsDF != nullptr) { - df.adoptInstead(dynamic_cast(fmtAsDF->clone())); + df.adoptInstead(fmtAsDF->clone()); if (df.isNull()) { // Memory allocation error return; @@ -3901,11 +3904,11 @@ } else if (fDateOverride.isBogus() && fHasHanYearChar) { // No current override (=> no Gannen numbering) but new pattern needs it; // use procedures from initNUmberFormatters / adoptNumberFormat - umtx_lock(LOCK()); + umtx_lock(&LOCK); if (fSharedNumberFormatters == NULL) { fSharedNumberFormatters = allocSharedNumberFormatters(); } - umtx_unlock(LOCK()); + umtx_unlock(&LOCK); if (fSharedNumberFormatters != NULL) { Locale ovrLoc(fLocale.getLanguage(),fLocale.getCountry(),fLocale.getVariant(),"numbers=jpanyear"); UErrorCode status = U_ZERO_ERROR; @@ -3998,6 +4001,7 @@ DateFormatSymbols *newSymbols = DateFormatSymbols::createForLocale(calLocale, status); if (U_FAILURE(status)) { + delete calendarToAdopt; return; } DateFormat::adoptCalendar(calendarToAdopt); @@ -4237,7 +4241,7 @@ TimeZoneFormat * SimpleDateFormat::tzFormat(UErrorCode &status) const { if (fTimeZoneFormat == NULL) { - umtx_lock(LOCK()); + umtx_lock(&LOCK); { if (fTimeZoneFormat == NULL) { TimeZoneFormat *tzfmt = TimeZoneFormat::createInstance(fLocale, status); @@ -4248,7 +4252,7 @@ const_cast(this)->fTimeZoneFormat = tzfmt; } } - umtx_unlock(LOCK()); + umtx_unlock(&LOCK); } return fTimeZoneFormat; } diff -Nru icu-64.2/source/i18n/string_segment.cpp icu-65.1/source/i18n/string_segment.cpp --- icu-64.2/source/i18n/string_segment.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/string_segment.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,145 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + +#include "numparse_types.h" +#include "string_segment.h" +#include "putilimp.h" +#include "unicode/utf16.h" +#include "unicode/uniset.h" + +U_NAMESPACE_BEGIN + + +StringSegment::StringSegment(const UnicodeString& str, bool ignoreCase) + : fStr(str), fStart(0), fEnd(str.length()), + fFoldCase(ignoreCase) {} + +int32_t StringSegment::getOffset() const { + return fStart; +} + +void StringSegment::setOffset(int32_t start) { + fStart = start; +} + +void StringSegment::adjustOffset(int32_t delta) { + fStart += delta; +} + +void StringSegment::adjustOffsetByCodePoint() { + fStart += U16_LENGTH(getCodePoint()); +} + +void StringSegment::setLength(int32_t length) { + fEnd = fStart + length; +} + +void StringSegment::resetLength() { + fEnd = fStr.length(); +} + +int32_t StringSegment::length() const { + return fEnd - fStart; +} + +char16_t StringSegment::charAt(int32_t index) const { + return fStr.charAt(index + fStart); +} + +UChar32 StringSegment::codePointAt(int32_t index) const { + return fStr.char32At(index + fStart); +} + +UnicodeString StringSegment::toUnicodeString() const { + return UnicodeString(fStr.getBuffer() + fStart, fEnd - fStart); +} + +const UnicodeString StringSegment::toTempUnicodeString() const { + // Use the readonly-aliasing constructor for efficiency. + return UnicodeString(FALSE, fStr.getBuffer() + fStart, fEnd - fStart); +} + +UChar32 StringSegment::getCodePoint() const { + char16_t lead = fStr.charAt(fStart); + if (U16_IS_LEAD(lead) && fStart + 1 < fEnd) { + return fStr.char32At(fStart); + } else if (U16_IS_SURROGATE(lead)) { + return -1; + } else { + return lead; + } +} + +bool StringSegment::startsWith(UChar32 otherCp) const { + return codePointsEqual(getCodePoint(), otherCp, fFoldCase); +} + +bool StringSegment::startsWith(const UnicodeSet& uniset) const { + // TODO: Move UnicodeSet case-folding logic here. + // TODO: Handle string matches here instead of separately. + UChar32 cp = getCodePoint(); + if (cp == -1) { + return false; + } + return uniset.contains(cp); +} + +bool StringSegment::startsWith(const UnicodeString& other) const { + if (other.isBogus() || other.length() == 0 || length() == 0) { + return false; + } + int cp1 = getCodePoint(); + int cp2 = other.char32At(0); + return codePointsEqual(cp1, cp2, fFoldCase); +} + +int32_t StringSegment::getCommonPrefixLength(const UnicodeString& other) { + return getPrefixLengthInternal(other, fFoldCase); +} + +int32_t StringSegment::getCaseSensitivePrefixLength(const UnicodeString& other) { + return getPrefixLengthInternal(other, false); +} + +int32_t StringSegment::getPrefixLengthInternal(const UnicodeString& other, bool foldCase) { + U_ASSERT(other.length() > 0); + int32_t offset = 0; + for (; offset < uprv_min(length(), other.length());) { + // TODO: case-fold code points, not chars + char16_t c1 = charAt(offset); + char16_t c2 = other.charAt(offset); + if (!codePointsEqual(c1, c2, foldCase)) { + break; + } + offset++; + } + return offset; +} + +bool StringSegment::codePointsEqual(UChar32 cp1, UChar32 cp2, bool foldCase) { + if (cp1 == cp2) { + return true; + } + if (!foldCase) { + return false; + } + cp1 = u_foldCase(cp1, TRUE); + cp2 = u_foldCase(cp2, TRUE); + return cp1 == cp2; +} + +bool StringSegment::operator==(const UnicodeString& other) const { + return toTempUnicodeString() == other; +} + + +U_NAMESPACE_END +#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/string_segment.h icu-65.1/source/i18n/string_segment.h --- icu-64.2/source/i18n/string_segment.h 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/i18n/string_segment.h 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,134 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#ifndef __NUMPARSE_STRINGSEGMENT_H__ +#define __NUMPARSE_STRINGSEGMENT_H__ + +#include "unicode/unistr.h" +#include "unicode/uniset.h" + +U_NAMESPACE_BEGIN + + +/** + * A mutable UnicodeString wrapper with a variable offset and length and + * support for case folding. The charAt, length, and subSequence methods all + * operate relative to the fixed offset into the UnicodeString. + * + * Intended to be useful for parsing. + * + * CAUTION: Since this class is mutable, it must not be used anywhere that an + * immutable object is required, like in a cache or as the key of a hash map. + * + * @author sffc (Shane Carr) + */ +// Exported as U_I18N_API for tests +class U_I18N_API StringSegment : public UMemory { + public: + StringSegment(const UnicodeString& str, bool ignoreCase); + + int32_t getOffset() const; + + void setOffset(int32_t start); + + /** + * Equivalent to setOffset(getOffset()+delta). + * + *

    + * This method is usually called by a Matcher to register that a char was consumed. If the char is + * strong (it usually is, except for things like whitespace), follow this with a call to + * {@link ParsedNumber#setCharsConsumed}. For more information on strong chars, see that method. + */ + void adjustOffset(int32_t delta); + + /** + * Adjusts the offset by the width of the current code point, either 1 or 2 chars. + */ + void adjustOffsetByCodePoint(); + + void setLength(int32_t length); + + void resetLength(); + + int32_t length() const; + + char16_t charAt(int32_t index) const; + + UChar32 codePointAt(int32_t index) const; + + UnicodeString toUnicodeString() const; + + const UnicodeString toTempUnicodeString() const; + + /** + * Returns the first code point in the string segment, or -1 if the string starts with an invalid + * code point. + * + *

    + * Important: Most of the time, you should use {@link #startsWith}, which handles case + * folding logic, instead of this method. + */ + UChar32 getCodePoint() const; + + /** + * Returns true if the first code point of this StringSegment equals the given code point. + * + *

    + * This method will perform case folding if case folding is enabled for the parser. + */ + bool startsWith(UChar32 otherCp) const; + + /** + * Returns true if the first code point of this StringSegment is in the given UnicodeSet. + */ + bool startsWith(const UnicodeSet& uniset) const; + + /** + * Returns true if there is at least one code point of overlap between this StringSegment and the + * given UnicodeString. + */ + bool startsWith(const UnicodeString& other) const; + + /** + * Returns the length of the prefix shared by this StringSegment and the given UnicodeString. For + * example, if this string segment is "aab", and the char sequence is "aac", this method returns 2, + * since the first 2 characters are the same. + * + *

    + * This method only returns offsets along code point boundaries. + * + *

    + * This method will perform case folding if case folding was enabled in the constructor. + * + *

    + * IMPORTANT: The given UnicodeString must not be empty! It is the caller's responsibility to check. + */ + int32_t getCommonPrefixLength(const UnicodeString& other); + + /** + * Like {@link #getCommonPrefixLength}, but never performs case folding, even if case folding is + * enabled for the parser. + */ + int32_t getCaseSensitivePrefixLength(const UnicodeString& other); + + bool operator==(const UnicodeString& other) const; + + private: + const UnicodeString& fStr; + int32_t fStart; + int32_t fEnd; + bool fFoldCase; + + int32_t getPrefixLengthInternal(const UnicodeString& other, bool foldCase); + + static bool codePointsEqual(UChar32 cp1, UChar32 cp2, bool foldCase); +}; + + +U_NAMESPACE_END + +#endif //__NUMPARSE_STRINGSEGMENT_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/strmatch.cpp icu-65.1/source/i18n/strmatch.cpp --- icu-64.2/source/i18n/strmatch.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/strmatch.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -58,7 +58,7 @@ /** * Implement UnicodeFunctor */ -UnicodeFunctor* StringMatcher::clone() const { +StringMatcher* StringMatcher::clone() const { return new StringMatcher(*this); } diff -Nru icu-64.2/source/i18n/strmatch.h icu-65.1/source/i18n/strmatch.h --- icu-64.2/source/i18n/strmatch.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/strmatch.h 2019-10-03 11:16:41.000000000 +0000 @@ -78,7 +78,7 @@ * Implement UnicodeFunctor * @return a copy of the object. */ - virtual UnicodeFunctor* clone() const; + virtual StringMatcher* clone() const; /** * UnicodeFunctor API. Cast 'this' to a UnicodeMatcher* pointer diff -Nru icu-64.2/source/i18n/strrepl.cpp icu-65.1/source/i18n/strrepl.cpp --- icu-64.2/source/i18n/strrepl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/strrepl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -87,7 +87,7 @@ /** * Implement UnicodeFunctor */ -UnicodeFunctor* StringReplacer::clone() const { +StringReplacer* StringReplacer::clone() const { return new StringReplacer(*this); } diff -Nru icu-64.2/source/i18n/strrepl.h icu-65.1/source/i18n/strrepl.h --- icu-64.2/source/i18n/strrepl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/strrepl.h 2019-10-03 11:16:41.000000000 +0000 @@ -111,7 +111,7 @@ /** * Implement UnicodeFunctor */ - virtual UnicodeFunctor* clone() const; + virtual StringReplacer* clone() const; /** * UnicodeFunctor API. Cast 'this' to a UnicodeReplacer* pointer diff -Nru icu-64.2/source/i18n/stsearch.cpp icu-65.1/source/i18n/stsearch.cpp --- icu-64.2/source/i18n/stsearch.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/stsearch.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -282,7 +282,7 @@ usearch_reset(m_strsrch_); } -SearchIterator * StringSearch::safeClone(void) const +StringSearch * StringSearch::safeClone() const { UErrorCode status = U_ZERO_ERROR; StringSearch *result = new StringSearch(m_pattern_, m_text_, diff -Nru icu-64.2/source/i18n/taiwncal.cpp icu-65.1/source/i18n/taiwncal.cpp --- icu-64.2/source/i18n/taiwncal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/taiwncal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -53,7 +53,7 @@ return *this; } -Calendar* TaiwanCalendar::clone(void) const +TaiwanCalendar* TaiwanCalendar::clone() const { return new TaiwanCalendar(*this); } diff -Nru icu-64.2/source/i18n/taiwncal.h icu-65.1/source/i18n/taiwncal.h --- icu-64.2/source/i18n/taiwncal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/taiwncal.h 2019-10-03 11:16:41.000000000 +0000 @@ -91,7 +91,7 @@ * @return return a polymorphic copy of this calendar. * @internal */ - virtual Calendar* clone(void) const; + virtual TaiwanCalendar* clone() const; public: /** diff -Nru icu-64.2/source/i18n/timezone.cpp icu-65.1/source/i18n/timezone.cpp --- icu-64.2/source/i18n/timezone.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/timezone.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -527,6 +527,8 @@ // ------------------------------------- +static UMutex gDefaultZoneMutex; + /** * Initialize DEFAULT_ZONE from the system default time zone. * Upon return, DEFAULT_ZONE will not be NULL, unless operator new() @@ -536,6 +538,7 @@ { ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup); + Mutex lock(&gDefaultZoneMutex); // If setDefault() has already been called we can skip getting the // default zone information from the system. if (DEFAULT_ZONE != NULL) { @@ -557,9 +560,6 @@ TimeZone *default_zone = TimeZone::detectHostTimeZone(); - // The only way for DEFAULT_ZONE to be non-null at this point is if the user - // made a thread-unsafe call to setDefault() or adoptDefault() in another - // thread while this thread was doing something that required getting the default. U_ASSERT(DEFAULT_ZONE == NULL); DEFAULT_ZONE = default_zone; @@ -571,7 +571,10 @@ TimeZone::createDefault() { umtx_initOnce(gDefaultZoneInitOnce, initDefault); - return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL; + { + Mutex lock(&gDefaultZoneMutex); + return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL; + } } // ------------------------------------- @@ -581,9 +584,12 @@ { if (zone != NULL) { - TimeZone *old = DEFAULT_ZONE; - DEFAULT_ZONE = zone; - delete old; + { + Mutex lock(&gDefaultZoneMutex); + TimeZone *old = DEFAULT_ZONE; + DEFAULT_ZONE = zone; + delete old; + } ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup); } } diff -Nru icu-64.2/source/i18n/titletrn.cpp icu-65.1/source/i18n/titletrn.cpp --- icu-64.2/source/i18n/titletrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/titletrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -60,7 +60,7 @@ /** * Transliterator API. */ -Transliterator* TitlecaseTransliterator::clone(void) const { +TitlecaseTransliterator* TitlecaseTransliterator::clone() const { return new TitlecaseTransliterator(*this); } diff -Nru icu-64.2/source/i18n/titletrn.h icu-65.1/source/i18n/titletrn.h --- icu-64.2/source/i18n/titletrn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/titletrn.h 2019-10-03 11:16:41.000000000 +0000 @@ -52,7 +52,7 @@ * Transliterator API. * @return a copy of the object. */ - virtual Transliterator* clone(void) const; + virtual TitlecaseTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/tmunit.cpp icu-65.1/source/i18n/tmunit.cpp --- icu-64.2/source/i18n/tmunit.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tmunit.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -102,7 +102,7 @@ : MeasureUnit(other), fTimeUnitField(other.fTimeUnitField) { } -UObject* +TimeUnit* TimeUnit::clone() const { return new TimeUnit(*this); } diff -Nru icu-64.2/source/i18n/tmutamt.cpp icu-65.1/source/i18n/tmutamt.cpp --- icu-64.2/source/i18n/tmutamt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tmutamt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -50,7 +50,7 @@ return Measure::operator==(other); } -UObject* +TimeUnitAmount* TimeUnitAmount::clone() const { return new TimeUnitAmount(*this); } diff -Nru icu-64.2/source/i18n/tmutfmt.cpp icu-65.1/source/i18n/tmutfmt.cpp --- icu-64.2/source/i18n/tmutfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tmutfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -136,8 +136,8 @@ } -Format* -TimeUnitFormat::clone(void) const { +TimeUnitFormat* +TimeUnitFormat::clone() const { return new TimeUnitFormat(*this); } @@ -685,7 +685,7 @@ if (U_FAILURE(status)) { return; } - adoptNumberFormat((NumberFormat *)format.clone(), status); + adoptNumberFormat(format.clone(), status); } @@ -721,8 +721,8 @@ const UHashTok valueTok = element->value; const MessageFormat** value = (const MessageFormat**)valueTok.pointer; MessageFormat** newVal = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)); - newVal[0] = (MessageFormat*)value[0]->clone(); - newVal[1] = (MessageFormat*)value[1]->clone(); + newVal[0] = value[0]->clone(); + newVal[1] = value[1]->clone(); target->put(UnicodeString(*key), newVal, status); if ( U_FAILURE(status) ) { delete newVal[0]; diff -Nru icu-64.2/source/i18n/tolowtrn.cpp icu-65.1/source/i18n/tolowtrn.cpp --- icu-64.2/source/i18n/tolowtrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tolowtrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -58,7 +58,7 @@ /** * Transliterator API. */ -Transliterator* LowercaseTransliterator::clone(void) const { +LowercaseTransliterator* LowercaseTransliterator::clone() const { return new LowercaseTransliterator(*this); } diff -Nru icu-64.2/source/i18n/tolowtrn.h icu-65.1/source/i18n/tolowtrn.h --- icu-64.2/source/i18n/tolowtrn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tolowtrn.h 2019-10-03 11:16:41.000000000 +0000 @@ -50,7 +50,7 @@ * Transliterator API. * @return a copy of the object. */ - virtual Transliterator* clone(void) const; + virtual LowercaseTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/toupptrn.cpp icu-65.1/source/i18n/toupptrn.cpp --- icu-64.2/source/i18n/toupptrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/toupptrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -58,7 +58,7 @@ /** * Transliterator API. */ -Transliterator* UppercaseTransliterator::clone(void) const { +UppercaseTransliterator* UppercaseTransliterator::clone() const { return new UppercaseTransliterator(*this); } diff -Nru icu-64.2/source/i18n/toupptrn.h icu-65.1/source/i18n/toupptrn.h --- icu-64.2/source/i18n/toupptrn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/toupptrn.h 2019-10-03 11:16:41.000000000 +0000 @@ -50,7 +50,7 @@ * Transliterator API. * @return a copy of the object. */ - virtual Transliterator* clone(void) const; + virtual UppercaseTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/translit.cpp icu-65.1/source/i18n/translit.cpp --- icu-64.2/source/i18n/translit.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/translit.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -91,10 +91,7 @@ /** * The mutex controlling access to registry object. */ -static icu::UMutex *registryMutex() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UMutex registryMutex; /** * System transliterator registry; non-null when initialized. @@ -161,7 +158,7 @@ if (other.filter != 0) { // We own the filter, so we must have our own copy - filter = (UnicodeFilter*) other.filter->clone(); + filter = other.filter->clone(); } } @@ -178,7 +175,7 @@ ID.getTerminatedBuffer(); maximumContextLength = other.maximumContextLength; - adoptFilter((other.filter == 0) ? 0 : (UnicodeFilter*) other.filter->clone()); + adoptFilter((other.filter == 0) ? 0 : other.filter->clone()); return *this; } @@ -926,13 +923,15 @@ return NULL; } - UnicodeSet* globalFilter; + UnicodeSet* globalFilter = nullptr; // TODO add code for parseError...currently unused, but // later may be used by parsing code... if (!TransliteratorIDParser::parseCompoundID(ID, dir, canonID, list, globalFilter)) { status = U_INVALID_ID; + delete globalFilter; return NULL; } + LocalPointer lpGlobalFilter(globalFilter); TransliteratorIDParser::instantiateList(list, status); if (U_FAILURE(status)) { @@ -956,8 +955,8 @@ // Check null pointer if (t != NULL) { t->setID(canonID); - if (globalFilter != NULL) { - t->adoptFilter(globalFilter); + if (lpGlobalFilter.isValid()) { + t->adoptFilter(lpGlobalFilter.orphan()); } } else if (U_SUCCESS(status)) { @@ -981,11 +980,11 @@ TransliteratorAlias* alias = 0; Transliterator* t = 0; - umtx_lock(registryMutex()); + umtx_lock(®istryMutex); if (HAVE_REGISTRY(ec)) { t = registry->get(id, alias, ec); } - umtx_unlock(registryMutex()); + umtx_unlock(®istryMutex); if (U_FAILURE(ec)) { delete t; @@ -1013,11 +1012,11 @@ alias = 0; // Step 2. reget - umtx_lock(registryMutex()); + umtx_lock(®istryMutex); if (HAVE_REGISTRY(ec)) { t = registry->reget(id, parser, alias, ec); } - umtx_unlock(registryMutex()); + umtx_unlock(®istryMutex); // Step 3. Loop back around! } else { @@ -1104,6 +1103,10 @@ UnicodeString* idBlock = (UnicodeString*)parser.idBlockVector.elementAt(i); if (!idBlock->isEmpty()) { Transliterator* temp = createInstance(*idBlock, UTRANS_FORWARD, parseError, status); + if (U_FAILURE(status)) { + delete temp; + return nullptr; + } if (temp != NULL && typeid(*temp) != typeid(NullTransliterator)) transliterators.addElement(temp, status); else @@ -1117,8 +1120,10 @@ data, TRUE); // Check if NULL before adding it to transliterators to avoid future usage of NULL pointer. if (temprbt == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return t; + if (U_SUCCESS(status)) { + status = U_MEMORY_ALLOCATION_ERROR; + } + return t; } transliterators.addElement(temprbt, status); } @@ -1215,7 +1220,7 @@ void U_EXPORT2 Transliterator::registerFactory(const UnicodeString& id, Transliterator::Factory factory, Transliterator::Token context) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _registerFactory(id, factory, context); @@ -1254,7 +1259,7 @@ * @see #unregister */ void U_EXPORT2 Transliterator::registerInstance(Transliterator* adoptedPrototype) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _registerInstance(adoptedPrototype); @@ -1268,7 +1273,7 @@ void U_EXPORT2 Transliterator::registerAlias(const UnicodeString& aliasID, const UnicodeString& realID) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _registerAlias(aliasID, realID); @@ -1290,7 +1295,7 @@ */ void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { registry->remove(ID); @@ -1305,7 +1310,7 @@ */ int32_t U_EXPORT2 Transliterator::countAvailableIDs(void) { int32_t retVal = 0; - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { retVal = registry->countAvailableIDs(); @@ -1321,12 +1326,12 @@ */ const UnicodeString& U_EXPORT2 Transliterator::getAvailableID(int32_t index) { const UnicodeString* result = NULL; - umtx_lock(registryMutex()); + umtx_lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { result = ®istry->getAvailableID(index); } - umtx_unlock(registryMutex()); + umtx_unlock(®istryMutex); U_ASSERT(result != NULL); // fail if no registry return *result; } @@ -1334,11 +1339,11 @@ StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) { if (U_FAILURE(ec)) return NULL; StringEnumeration* result = NULL; - umtx_lock(registryMutex()); + umtx_lock(®istryMutex); if (HAVE_REGISTRY(ec)) { result = registry->getAvailableIDs(); } - umtx_unlock(registryMutex()); + umtx_unlock(®istryMutex); if (result == NULL) { ec = U_INTERNAL_TRANSLITERATOR_ERROR; } @@ -1346,14 +1351,14 @@ } int32_t U_EXPORT2 Transliterator::countAvailableSources(void) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; return HAVE_REGISTRY(ec) ? _countAvailableSources() : 0; } UnicodeString& U_EXPORT2 Transliterator::getAvailableSource(int32_t index, UnicodeString& result) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _getAvailableSource(index, result); @@ -1362,7 +1367,7 @@ } int32_t U_EXPORT2 Transliterator::countAvailableTargets(const UnicodeString& source) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; return HAVE_REGISTRY(ec) ? _countAvailableTargets(source) : 0; } @@ -1370,7 +1375,7 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableTarget(int32_t index, const UnicodeString& source, UnicodeString& result) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _getAvailableTarget(index, source, result); @@ -1380,7 +1385,7 @@ int32_t U_EXPORT2 Transliterator::countAvailableVariants(const UnicodeString& source, const UnicodeString& target) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; return HAVE_REGISTRY(ec) ? _countAvailableVariants(source, target) : 0; } @@ -1389,7 +1394,7 @@ const UnicodeString& source, const UnicodeString& target, UnicodeString& result) { - Mutex lock(registryMutex()); + Mutex lock(®istryMutex); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _getAvailableVariant(index, source, target, result); diff -Nru icu-64.2/source/i18n/transreg.cpp icu-65.1/source/i18n/transreg.cpp --- icu-64.2/source/i18n/transreg.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/transreg.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -131,7 +131,7 @@ return 0; } if (compoundFilter != 0) - t->adoptFilter((UnicodeSet*)compoundFilter->clone()); + t->adoptFilter(compoundFilter->clone()); break; case COMPOUND: { @@ -173,8 +173,8 @@ if (U_SUCCESS(ec)) { t = new CompoundTransliterator(ID, transliterators, - (compoundFilter ? (UnicodeSet*)(compoundFilter->clone()) : 0), - anonymousRBTs, pe, ec); + (compoundFilter ? compoundFilter->clone() : nullptr), + anonymousRBTs, pe, ec); if (t == 0) { ec = U_MEMORY_ALLOCATION_ERROR; return 0; @@ -946,7 +946,7 @@ if (visible) { registerSTV(source, target, variant); if (!availableIDs.contains((void*) &ID)) { - UnicodeString *newID = (UnicodeString *)ID.clone(); + UnicodeString *newID = ID.clone(); // Check to make sure newID was created. if (newID != NULL) { // NUL-terminate the ID string diff -Nru icu-64.2/source/i18n/tridpars.cpp icu-65.1/source/i18n/tridpars.cpp --- icu-64.2/source/i18n/tridpars.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tridpars.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -50,10 +50,7 @@ /** * The mutex controlling access to SPECIAL_INVERSES */ -static UMutex *LOCK() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex LOCK; TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString& t, const UnicodeString& v, UBool sawS, @@ -297,6 +294,7 @@ pos = ppos.getIndex(); if (withParens == 1 && !ICU_Utility::parseChar(id, pos, CLOSE_REV)) { + delete filter; pos = start; return NULL; } @@ -662,7 +660,7 @@ bidirectional = FALSE; } - Mutex lock(LOCK()); + Mutex lock(&LOCK); UnicodeString *tempus = new UnicodeString(inverseTarget); // Used for null pointer check before usage. if (tempus == NULL) { @@ -866,9 +864,9 @@ UnicodeString* inverseTarget; - umtx_lock(LOCK()); + umtx_lock(&LOCK); inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target); - umtx_unlock(LOCK()); + umtx_unlock(&LOCK); if (inverseTarget != NULL) { // If the original ID contained "Any-" then make the diff -Nru icu-64.2/source/i18n/tzfmt.cpp icu-65.1/source/i18n/tzfmt.cpp --- icu-64.2/source/i18n/tzfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tzfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -19,12 +19,15 @@ #include "unicode/udat.h" #include "unicode/ustring.h" #include "unicode/utf16.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "tzgnames.h" #include "cmemory.h" #include "cstring.h" #include "putilimp.h" #include "uassert.h" #include "ucln_in.h" +#include "ulocimp.h" #include "umutex.h" #include "uresimp.h" #include "ureslocs.h" @@ -147,10 +150,7 @@ static TextTrieMap *gShortZoneIdTrie = NULL; static icu::UInitOnce gShortZoneIdTrieInitOnce = U_INITONCE_INITIALIZER; -static UMutex *gLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gLock; U_CDECL_BEGIN /** @@ -327,10 +327,13 @@ const char* region = fLocale.getCountry(); int32_t regionLen = static_cast(uprv_strlen(region)); if (regionLen == 0) { - char loc[ULOC_FULLNAME_CAPACITY]; - uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status); + CharString loc; + { + CharStringByteSink sink(&loc); + ulocimp_addLikelySubtags(fLocale.getName(), sink, &status); + } - regionLen = uloc_getCountry(loc, fTargetRegion, sizeof(fTargetRegion), &status); + regionLen = uloc_getCountry(loc.data(), fTargetRegion, sizeof(fTargetRegion), &status); if (U_SUCCESS(status)) { fTargetRegion[regionLen] = 0; } else { @@ -502,7 +505,7 @@ return isEqual; } -Format* +TimeZoneFormat* TimeZoneFormat::clone() const { return new TimeZoneFormat(*this); } @@ -1385,12 +1388,12 @@ return NULL; } - umtx_lock(gLock()); + umtx_lock(&gLock); if (fTimeZoneGenericNames == NULL) { TimeZoneFormat *nonConstThis = const_cast(this); nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status); } - umtx_unlock(gLock()); + umtx_unlock(&gLock); return fTimeZoneGenericNames; } @@ -1401,7 +1404,7 @@ return NULL; } - umtx_lock(gLock()); + umtx_lock(&gLock); if (fTZDBTimeZoneNames == NULL) { TZDBTimeZoneNames *tzdbNames = new TZDBTimeZoneNames(fLocale); if (tzdbNames == NULL) { @@ -1411,7 +1414,7 @@ nonConstThis->fTZDBTimeZoneNames = tzdbNames; } } - umtx_unlock(gLock()); + umtx_unlock(&gLock); return fTZDBTimeZoneNames; } @@ -1875,7 +1878,7 @@ while (len > 0) { UChar32 ch; int32_t chLen; - U16_GET(patStr, 0, 0, len, ch) + U16_GET(patStr, 0, 0, len, ch); if (PatternProps::isWhiteSpace(ch)) { chLen = U16_LENGTH(ch); len -= chLen; diff -Nru icu-64.2/source/i18n/tzgnames.cpp icu-65.1/source/i18n/tzgnames.cpp --- icu-64.2/source/i18n/tzgnames.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tzgnames.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -21,12 +21,15 @@ #include "unicode/strenum.h" #include "unicode/vtzone.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "mutex.h" #include "uhash.h" #include "uassert.h" #include "umutex.h" +#include "ulocimp.h" #include "uresimp.h" #include "ureslocs.h" #include "zonemeta.h" @@ -269,10 +272,7 @@ return results; } -static UMutex *gLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gLock; class TZGNCore : public UMemory { public: @@ -412,10 +412,13 @@ const char* region = fLocale.getCountry(); int32_t regionLen = static_cast(uprv_strlen(region)); if (regionLen == 0) { - char loc[ULOC_FULLNAME_CAPACITY]; - uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status); + CharString loc; + { + CharStringByteSink sink(&loc); + ulocimp_addLikelySubtags(fLocale.getName(), sink, &status); + } - regionLen = uloc_getCountry(loc, fTargetRegion, sizeof(fTargetRegion), &status); + regionLen = uloc_getCountry(loc.data(), fTargetRegion, sizeof(fTargetRegion), &status); if (U_SUCCESS(status)) { fTargetRegion[regionLen] = 0; } else { @@ -488,11 +491,11 @@ const UChar *locname = NULL; TZGNCore *nonConstThis = const_cast(this); - umtx_lock(gLock()); + umtx_lock(&gLock); { locname = nonConstThis->getGenericLocationName(tzCanonicalID); } - umtx_unlock(gLock()); + umtx_unlock(&gLock); if (locname == NULL) { name.setToBogus(); @@ -743,11 +746,11 @@ const UChar *uplname = NULL; TZGNCore *nonConstThis = const_cast(this); - umtx_lock(gLock()); + umtx_lock(&gLock); { uplname = nonConstThis->getPartialLocationName(tzCanonicalID, mzID, isLong, mzDisplayName); } - umtx_unlock(gLock()); + umtx_unlock(&gLock); if (uplname == NULL) { name.setToBogus(); @@ -1010,11 +1013,11 @@ TZGNCore *nonConstThis = const_cast(this); - umtx_lock(gLock()); + umtx_lock(&gLock); { fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); } - umtx_unlock(gLock()); + umtx_unlock(&gLock); if (U_FAILURE(status)) { return NULL; @@ -1041,7 +1044,7 @@ // All names are not yet loaded into the local trie. // Load all available names into the trie. This could be very heavy. - umtx_lock(gLock()); + umtx_lock(&gLock); { if (!fGNamesTrieFullyLoaded) { StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status); @@ -1063,18 +1066,18 @@ } } } - umtx_unlock(gLock()); + umtx_unlock(&gLock); if (U_FAILURE(status)) { return NULL; } - umtx_lock(gLock()); + umtx_lock(&gLock); { // now try it again fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); } - umtx_unlock(gLock()); + umtx_unlock(&gLock); results = handler.getMatches(maxLen); if (results != NULL && maxLen > 0) { @@ -1115,10 +1118,7 @@ } TZGNCoreRef; // TZGNCore object cache handling -static UMutex *gTZGNLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gTZGNLock; static UHashtable *gTZGNCoreCache = NULL; static UBool gTZGNCoreCacheInitialized = FALSE; @@ -1184,13 +1184,13 @@ } TimeZoneGenericNames::~TimeZoneGenericNames() { - umtx_lock(gTZGNLock()); + umtx_lock(&gTZGNLock); { U_ASSERT(fRef->refCount > 0); // Just decrement the reference count fRef->refCount--; } - umtx_unlock(gTZGNLock()); + umtx_unlock(&gTZGNLock); } TimeZoneGenericNames* @@ -1206,7 +1206,7 @@ TZGNCoreRef *cacheEntry = NULL; { - Mutex lock(gTZGNLock()); + Mutex lock(&gTZGNLock); if (!gTZGNCoreCacheInitialized) { // Create empty hashtable @@ -1298,13 +1298,13 @@ TimeZoneGenericNames::clone() const { TimeZoneGenericNames* other = new TimeZoneGenericNames(); if (other) { - umtx_lock(gTZGNLock()); + umtx_lock(&gTZGNLock); { // Just increments the reference count fRef->refCount++; other->fRef = fRef; } - umtx_unlock(gTZGNLock()); + umtx_unlock(&gTZGNLock); } return other; } diff -Nru icu-64.2/source/i18n/tznames.cpp icu-65.1/source/i18n/tznames.cpp --- icu-64.2/source/i18n/tznames.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tznames.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -29,10 +29,7 @@ U_NAMESPACE_BEGIN // TimeZoneNames object cache handling -static UMutex *gTimeZoneNamesLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gTimeZoneNamesLock; static UHashtable *gTimeZoneNamesCache = NULL; static UBool gTimeZoneNamesCacheInitialized = FALSE; @@ -109,7 +106,7 @@ virtual UBool operator==(const TimeZoneNames& other) const; virtual UBool operator!=(const TimeZoneNames& other) const {return !operator==(other);} - virtual TimeZoneNames* clone() const; + virtual TimeZoneNamesDelegate* clone() const; StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const; StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const; @@ -135,7 +132,7 @@ } TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status) { - Mutex lock(gTimeZoneNamesLock()); + Mutex lock(&gTimeZoneNamesLock); if (!gTimeZoneNamesCacheInitialized) { // Create empty hashtable if it is not already initialized. gTimeZoneNamesCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); @@ -211,7 +208,7 @@ } TimeZoneNamesDelegate::~TimeZoneNamesDelegate() { - umtx_lock(gTimeZoneNamesLock()); + umtx_lock(&gTimeZoneNamesLock); { if (fTZnamesCacheEntry) { U_ASSERT(fTZnamesCacheEntry->refCount > 0); @@ -219,7 +216,7 @@ fTZnamesCacheEntry->refCount--; } } - umtx_unlock(gTimeZoneNamesLock()); + umtx_unlock(&gTimeZoneNamesLock); } UBool @@ -236,17 +233,17 @@ return FALSE; } -TimeZoneNames* +TimeZoneNamesDelegate* TimeZoneNamesDelegate::clone() const { TimeZoneNamesDelegate* other = new TimeZoneNamesDelegate(); if (other != NULL) { - umtx_lock(gTimeZoneNamesLock()); + umtx_lock(&gTimeZoneNamesLock); { // Just increment the reference count fTZnamesCacheEntry->refCount++; other->fTZnamesCacheEntry = fTZnamesCacheEntry; } - umtx_unlock(gTimeZoneNamesLock()); + umtx_unlock(&gTimeZoneNamesLock); } return other; } diff -Nru icu-64.2/source/i18n/tznames_impl.cpp icu-65.1/source/i18n/tznames_impl.cpp --- icu-64.2/source/i18n/tznames_impl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tznames_impl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -21,11 +21,14 @@ #include "unicode/utf16.h" #include "tznames_impl.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "uassert.h" #include "mutex.h" #include "resource.h" +#include "ulocimp.h" #include "uresimp.h" #include "ureslocs.h" #include "zonemeta.h" @@ -49,10 +52,7 @@ static const char* TZDBNAMES_KEYS[] = {"ss", "sd"}; static const int32_t TZDBNAMES_KEYS_SIZE = UPRV_LENGTHOF(TZDBNAMES_KEYS); -static UMutex *gDataMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gDataMutex; static UHashtable* gTZDBNamesMap = NULL; static icu::UInitOnce gTZDBNamesMapInitOnce = U_INITONCE_INITIALIZER; @@ -388,7 +388,7 @@ // Don't do unless it's really required. // Mutex for protecting the lazy creation of the Trie node structure on the first call to search(). - static UMutex TextTrieMutex = U_MUTEX_INITIALIZER; + static UMutex TextTrieMutex; Mutex lock(&TextTrieMutex); if (fLazyContents != NULL) { @@ -1113,7 +1113,7 @@ return FALSE; } -TimeZoneNames* +TimeZoneNamesImpl* TimeZoneNamesImpl::clone() const { UErrorCode status = U_ZERO_ERROR; return new TimeZoneNamesImpl(fLocale, status); @@ -1214,7 +1214,7 @@ TimeZoneNamesImpl *nonConstThis = const_cast(this); { - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); UErrorCode status = U_ZERO_ERROR; znames = nonConstThis->loadMetaZoneNames(mzID, status); if (U_FAILURE(status)) { return name; } @@ -1240,7 +1240,7 @@ TimeZoneNamesImpl *nonConstThis = const_cast(this); { - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); UErrorCode status = U_ZERO_ERROR; tznames = nonConstThis->loadTimeZoneNames(tzID, status); if (U_FAILURE(status)) { return name; } @@ -1263,7 +1263,7 @@ TimeZoneNamesImpl *nonConstThis = const_cast(this); { - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); UErrorCode status = U_ZERO_ERROR; tznames = nonConstThis->loadTimeZoneNames(tzID, status); if (U_FAILURE(status)) { return name; } @@ -1358,7 +1358,7 @@ // Synchronize so that data is not loaded multiple times. // TODO: Consider more fine-grained synchronization. { - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); // First try of lookup. matches = doFind(handler, text, start, status); @@ -1585,7 +1585,7 @@ if (U_FAILURE(status)) return; { - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); internalLoadAllDisplayNames(status); } } @@ -1602,7 +1602,7 @@ // Load the time zone strings { - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); tznames = (void*) nonConstThis->loadTimeZoneNames(tzID, status); if (U_FAILURE(status)) { return; } } @@ -1622,7 +1622,7 @@ } else { // Load the meta zone strings // Mutex is scoped to the "else" statement - Mutex lock(gDataMutex()); + Mutex lock(&gDataMutex); mznames = (void*) nonConstThis->loadMetaZoneNames(mzID, status); if (U_FAILURE(status)) { return; } // Note: when the metazone doesn't exist, in Java, loadMetaZoneNames returns @@ -2135,9 +2135,12 @@ int32_t regionLen = static_cast(uprv_strlen(region)); if (regionLen == 0) { UErrorCode status = U_ZERO_ERROR; - char loc[ULOC_FULLNAME_CAPACITY]; - uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status); - regionLen = uloc_getCountry(loc, fRegion, sizeof(fRegion), &status); + CharString loc; + { + CharStringByteSink sink(&loc); + ulocimp_addLikelySubtags(fLocale.getName(), sink, &status); + } + regionLen = uloc_getCountry(loc.data(), fRegion, sizeof(fRegion), &status); if (U_SUCCESS(status) && regionLen < (int32_t)sizeof(fRegion)) { useWorld = FALSE; } @@ -2162,7 +2165,7 @@ return FALSE; } -TimeZoneNames* +TZDBTimeZoneNames* TZDBTimeZoneNames::clone() const { return new TZDBTimeZoneNames(fLocale); } @@ -2247,7 +2250,7 @@ U_ASSERT(status == U_ZERO_ERROR); // already checked length above mzIDKey[mzID.length()] = 0; - static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER; + static UMutex gTZDBNamesMapLock; umtx_lock(&gTZDBNamesMapLock); { void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey); diff -Nru icu-64.2/source/i18n/tznames_impl.h icu-65.1/source/i18n/tznames_impl.h --- icu-64.2/source/i18n/tznames_impl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tznames_impl.h 2019-10-03 11:16:41.000000000 +0000 @@ -174,7 +174,7 @@ virtual ~TimeZoneNamesImpl(); virtual UBool operator==(const TimeZoneNames& other) const; - virtual TimeZoneNames* clone() const; + virtual TimeZoneNamesImpl* clone() const; StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const; StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const; @@ -236,7 +236,7 @@ virtual ~TZDBTimeZoneNames(); virtual UBool operator==(const TimeZoneNames& other) const; - virtual TimeZoneNames* clone() const; + virtual TZDBTimeZoneNames* clone() const; StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const; StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const; diff -Nru icu-64.2/source/i18n/tzrule.cpp icu-65.1/source/i18n/tzrule.cpp --- icu-64.2/source/i18n/tzrule.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/tzrule.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -108,7 +108,7 @@ } InitialTimeZoneRule* -InitialTimeZoneRule::clone(void) const { +InitialTimeZoneRule::clone() const { return new InitialTimeZoneRule(*this); } diff -Nru icu-64.2/source/i18n/ucal.cpp icu-65.1/source/i18n/ucal.cpp --- icu-64.2/source/i18n/ucal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/ucal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -34,7 +34,7 @@ static TimeZone* _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) { TimeZone* zone = NULL; - if (ec!=NULL && U_SUCCESS(*ec)) { + if (ec != NULL && U_SUCCESS(*ec)) { // Note that if zoneID is invalid, we get back GMT. This odd // behavior is by design and goes back to the JDK. The only // failure we will see is a memory allocation failure. @@ -69,7 +69,7 @@ U_CAPI int32_t U_EXPORT2 ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { int32_t len = 0; - if (ec!=NULL && U_SUCCESS(*ec)) { + if (ec != NULL && U_SUCCESS(*ec)) { TimeZone* zone = TimeZone::createDefault(); if (zone == NULL) { *ec = U_MEMORY_ALLOCATION_ERROR; @@ -91,6 +91,23 @@ } } +U_DRAFT int32_t U_EXPORT2 +ucal_getHostTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { + int32_t len = 0; + if (ec != NULL && U_SUCCESS(*ec)) { + TimeZone *zone = TimeZone::detectHostTimeZone(); + if (zone == NULL) { + *ec = U_MEMORY_ALLOCATION_ERROR; + } else { + UnicodeString id; + zone->getID(id); + delete zone; + len = id.extract(result, resultCapacity, *ec); + } + } + return len; +} + U_CAPI int32_t U_EXPORT2 ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { int32_t result = 0; @@ -140,8 +157,8 @@ if(U_FAILURE(*status)) return 0; - TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() - : _createTimeZone(zoneID, len, status); + LocalPointer zone( (zoneID==NULL) ? TimeZone::createDefault() + : _createTimeZone(zoneID, len, status), *status); if (U_FAILURE(*status)) { return NULL; @@ -157,9 +174,9 @@ if (U_FAILURE(*status)) { return NULL; } - return (UCalendar*)Calendar::createInstance(zone, Locale(localeBuf), *status); + return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(localeBuf), *status); } - return (UCalendar*)Calendar::createInstance(zone, Locale(locale), *status); + return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(locale), *status); } U_CAPI void U_EXPORT2 diff -Nru icu-64.2/source/i18n/udat.cpp icu-65.1/source/i18n/udat.cpp --- icu-64.2/source/i18n/udat.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/udat.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -167,9 +167,13 @@ } } - if(fmt == 0) { + if(fmt == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; - return 0; + return nullptr; + } + if (U_FAILURE(*status)) { + delete fmt; + return nullptr; } if(tzID != 0) { diff -Nru icu-64.2/source/i18n/unesctrn.cpp icu-65.1/source/i18n/unesctrn.cpp --- icu-64.2/source/i18n/unesctrn.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unesctrn.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -164,7 +164,7 @@ /** * Transliterator API. */ -Transliterator* UnescapeTransliterator::clone() const { +UnescapeTransliterator* UnescapeTransliterator::clone() const { return new UnescapeTransliterator(*this); } diff -Nru icu-64.2/source/i18n/unesctrn.h icu-65.1/source/i18n/unesctrn.h --- icu-64.2/source/i18n/unesctrn.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unesctrn.h 2019-10-03 11:16:41.000000000 +0000 @@ -77,7 +77,7 @@ /** * Transliterator API. */ - virtual Transliterator* clone() const; + virtual UnescapeTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/uni2name.cpp icu-65.1/source/i18n/uni2name.cpp --- icu-64.2/source/i18n/uni2name.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/uni2name.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -60,7 +60,7 @@ /** * Transliterator API. */ -Transliterator* UnicodeNameTransliterator::clone(void) const { +UnicodeNameTransliterator* UnicodeNameTransliterator::clone() const { return new UnicodeNameTransliterator(*this); } diff -Nru icu-64.2/source/i18n/uni2name.h icu-65.1/source/i18n/uni2name.h --- icu-64.2/source/i18n/uni2name.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/uni2name.h 2019-10-03 11:16:41.000000000 +0000 @@ -48,7 +48,7 @@ /** * Transliterator API. */ - virtual Transliterator* clone(void) const; + virtual UnicodeNameTransliterator* clone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. diff -Nru icu-64.2/source/i18n/unicode/alphaindex.h icu-65.1/source/i18n/unicode/alphaindex.h --- icu-64.2/source/i18n/unicode/alphaindex.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/alphaindex.h 2019-10-03 11:16:41.000000000 +0000 @@ -13,6 +13,9 @@ #define INDEXCHARS_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/locid.h" #include "unicode/unistr.h" @@ -757,4 +760,7 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_COLLATION + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/basictz.h icu-65.1/source/i18n/unicode/basictz.h --- icu-64.2/source/i18n/unicode/basictz.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/basictz.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/timezone.h" @@ -42,6 +44,14 @@ virtual ~BasicTimeZone(); /** + * Clones this object polymorphically. + * The caller owns the result and should delete it when done. + * @return clone, or nullptr if an error occurred + * @stable ICU 3.8 + */ + virtual BasicTimeZone* clone() const = 0; + + /** * Gets the first time zone transition after the base time. * @param base The base time. * @param inclusive Whether the base time is inclusive or not. @@ -211,6 +221,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // BASICTZ_H //eof diff -Nru icu-64.2/source/i18n/unicode/calendar.h icu-65.1/source/i18n/unicode/calendar.h --- icu-64.2/source/i18n/unicode/calendar.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/calendar.h 2019-10-03 11:16:41.000000000 +0000 @@ -29,6 +29,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Calendar object @@ -184,7 +186,7 @@ */ class U_I18N_API Calendar : public UObject { public: - +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Field IDs for date and time. Used to specify date/time fields. ERA is calendar * specific. Example ranges given are for illustration only; see specific Calendar @@ -227,6 +229,7 @@ FIELD_COUNT = UCAL_FIELD_COUNT // See ucal.h for other fields. #endif /* U_HIDE_DEPRECATED_API */ }; +#endif // U_FORCE_HIDE_DEPRECATED_API #ifndef U_HIDE_DEPRECATED_API /** @@ -287,7 +290,7 @@ * @return a polymorphic copy of this calendar. * @stable ICU 2.0 */ - virtual Calendar* clone(void) const = 0; + virtual Calendar* clone() const = 0; /** * Creates a Calendar using the default timezone and locale. Clients are responsible @@ -518,6 +521,7 @@ */ UBool after(const Calendar& when, UErrorCode& status) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * UDate Arithmetic function. Adds the specified (signed) amount of time to the given * time field, based on the calendar's rules. For example, to subtract 5 days from @@ -539,6 +543,7 @@ * @deprecated ICU 2.6. use add(UCalendarDateFields field, int32_t amount, UErrorCode& status) instead. */ virtual void add(EDateFields field, int32_t amount, UErrorCode& status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * UDate Arithmetic function. Adds the specified (signed) amount of time to the given @@ -632,6 +637,7 @@ */ inline void roll(UCalendarDateFields field, UBool up, UErrorCode& status); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Time Field Rolling function. Rolls by the given amount on the given * time field. For example, to roll the current date up by one day, call @@ -664,6 +670,7 @@ * @deprecated ICU 2.6. Use roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) instead. */ virtual void roll(EDateFields field, int32_t amount, UErrorCode& status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Time Field Rolling function. Rolls by the given amount on the given @@ -698,6 +705,7 @@ */ virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode& status); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Return the difference between the given time and the time this * calendar object is set to. If this calendar is set @@ -754,6 +762,7 @@ * @deprecated ICU 2.6. Use fieldDifference(UDate when, UCalendarDateFields field, UErrorCode& status). */ virtual int32_t fieldDifference(UDate when, EDateFields field, UErrorCode& status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Return the difference between the given time and the time this @@ -1010,6 +1019,7 @@ */ uint8_t getMinimalDaysInFirstWeek(void) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Gets the minimum value for the given time field. e.g., for Gregorian * DAY_OF_MONTH, 1. @@ -1019,6 +1029,7 @@ * @deprecated ICU 2.6. Use getMinimum(UCalendarDateFields field) instead. */ virtual int32_t getMinimum(EDateFields field) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the minimum value for the given time field. e.g., for Gregorian @@ -1030,6 +1041,7 @@ */ virtual int32_t getMinimum(UCalendarDateFields field) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Gets the maximum value for the given time field. e.g. for Gregorian DAY_OF_MONTH, * 31. @@ -1039,6 +1051,7 @@ * @deprecated ICU 2.6. Use getMaximum(UCalendarDateFields field) instead. */ virtual int32_t getMaximum(EDateFields field) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the maximum value for the given time field. e.g. for Gregorian DAY_OF_MONTH, @@ -1050,6 +1063,7 @@ */ virtual int32_t getMaximum(UCalendarDateFields field) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Gets the highest minimum value for the given field if varies. Otherwise same as * getMinimum(). For Gregorian, no difference. @@ -1059,6 +1073,7 @@ * @deprecated ICU 2.6. Use getGreatestMinimum(UCalendarDateFields field) instead. */ virtual int32_t getGreatestMinimum(EDateFields field) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the highest minimum value for the given field if varies. Otherwise same as @@ -1070,6 +1085,7 @@ */ virtual int32_t getGreatestMinimum(UCalendarDateFields field) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Gets the lowest maximum value for the given field if varies. Otherwise same as * getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28. @@ -1079,6 +1095,7 @@ * @deprecated ICU 2.6. Use getLeastMaximum(UCalendarDateFields field) instead. */ virtual int32_t getLeastMaximum(EDateFields field) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the lowest maximum value for the given field if varies. Otherwise same as @@ -1895,11 +1912,13 @@ */ int32_t fFields[UCAL_FIELD_COUNT]; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * The flags which tell if a specified time field for the calendar is set. * @deprecated ICU 2.8 use (fStamp[n]!=kUnset) */ UBool fIsSet[UCAL_FIELD_COUNT]; +#endif // U_FORCE_HIDE_DEPRECATED_API /** Special values of stamp[] * @stable ICU 2.0 @@ -2281,7 +2300,6 @@ * should only be called if this calendar is not lenient. * @see #isLenient * @see #validateField(int, int&) - * @internal */ void validateFields(UErrorCode &status); @@ -2291,7 +2309,6 @@ * U_ILLEGAL_ARGUMENT_ERROR will be set. Subclasses may * use this method in their implementation of {@link * #validateField(int, int&)}. - * @internal */ void validateField(UCalendarDateFields field, int32_t min, int32_t max, UErrorCode& status); @@ -2529,4 +2546,6 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _CALENDAR diff -Nru icu-64.2/source/i18n/unicode/choicfmt.h icu-65.1/source/i18n/unicode/choicfmt.h --- icu-64.2/source/i18n/unicode/choicfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/choicfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,13 +26,14 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Choice Format. */ #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DEPRECATED_API #include "unicode/fieldpos.h" #include "unicode/format.h" @@ -40,6 +41,8 @@ #include "unicode/numfmt.h" #include "unicode/unistr.h" +#ifndef U_HIDE_DEPRECATED_API + U_NAMESPACE_BEGIN class MessageFormat; @@ -248,7 +251,7 @@ * @return a copy of this object * @deprecated ICU 49 Use MessageFormat instead, with plural and select arguments. */ - virtual Format* clone(void) const; + virtual ChoiceFormat* clone() const; /** * Returns true if the given Format objects are semantically equal. @@ -592,5 +595,7 @@ #endif // U_HIDE_DEPRECATED_API #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // CHOICFMT_H //eof diff -Nru icu-64.2/source/i18n/unicode/coleitr.h icu-65.1/source/i18n/unicode/coleitr.h --- icu-64.2/source/i18n/unicode/coleitr.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/coleitr.h 2019-10-03 11:16:41.000000000 +0000 @@ -35,6 +35,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_COLLATION #include "unicode/unistr.h" @@ -404,4 +406,6 @@ #endif /* #if !UCONFIG_NO_COLLATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/coll.h icu-65.1/source/i18n/unicode/coll.h --- icu-64.2/source/i18n/unicode/coll.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/coll.h 2019-10-03 11:16:41.000000000 +0000 @@ -54,6 +54,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_COLLATION #include "unicode/uobject.h" @@ -204,6 +206,7 @@ // Cannot use #ifndef U_HIDE_DEPRECATED_API for the following, it is // used by virtual methods that cannot have that conditional. +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * LESS is returned if source string is compared to be less than target * string in the compare() method. @@ -220,6 +223,7 @@ EQUAL = UCOL_EQUAL, // 0 GREATER = UCOL_GREATER // 1 }; +#endif // U_FORCE_HIDE_DEPRECATED_API // Collator public destructor ----------------------------------------- @@ -265,7 +269,7 @@ * @return a copy of this object, owned by the caller * @stable ICU 2.0 */ - virtual Collator* clone(void) const = 0; + virtual Collator* clone() const = 0; /** * Creates the Collator object for the current default locale. @@ -323,6 +327,7 @@ */ static Collator* U_EXPORT2 createInstance(const Locale& loc, UErrorCode& err); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * The comparison function compares the character data stored in two * different strings. Returns information about whether a string is less @@ -336,6 +341,7 @@ */ virtual EComparisonResult compare(const UnicodeString& source, const UnicodeString& target) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * The comparison function compares the character data stored in two @@ -353,6 +359,7 @@ const UnicodeString& target, UErrorCode &status) const = 0; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Does the same thing as compare but limits the comparison to a specified * length @@ -368,6 +375,7 @@ virtual EComparisonResult compare(const UnicodeString& source, const UnicodeString& target, int32_t length) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Does the same thing as compare but limits the comparison to a specified @@ -387,6 +395,7 @@ int32_t length, UErrorCode &status) const = 0; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * The comparison function compares the character data stored in two * different string arrays. Returns information about whether a string array @@ -423,6 +432,7 @@ virtual EComparisonResult compare(const char16_t* source, int32_t sourceLength, const char16_t* target, int32_t targetLength) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * The comparison function compares the character data stored in two @@ -527,6 +537,7 @@ */ virtual int32_t hashCode(void) const = 0; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Gets the locale of the Collator * @@ -540,6 +551,7 @@ * in ICU 3.0. */ virtual Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Convenience method for comparing two strings based on the collation rules. @@ -576,6 +588,7 @@ */ UBool equals(const UnicodeString& source, const UnicodeString& target) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Determines the minimum strength that will be used in comparison or * transformation. @@ -607,6 +620,7 @@ * @deprecated ICU 2.6 Use setAttribute(UCOL_STRENGTH...) instead */ virtual void setStrength(ECollationStrength newStrength); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Retrieves the reordering codes for this collator. @@ -904,6 +918,7 @@ */ virtual UColReorderCode getMaxVariable() const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Sets the variable top to the primary weight of the specified string. * @@ -951,6 +966,7 @@ * @deprecated ICU 53 Call setMaxVariable() instead. */ virtual void setVariableTop(uint32_t varTop, UErrorCode &status) = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the variable top value of a Collator. @@ -972,6 +988,7 @@ */ virtual UnicodeSet *getTailoredSet(UErrorCode &status) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Same as clone(). * The base class implementation simply calls clone(). @@ -979,7 +996,8 @@ * @see clone() * @deprecated ICU 50 no need to have two methods for cloning */ - virtual Collator* safeClone(void) const; + virtual Collator* safeClone() const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Get the sort key as an array of bytes from a UnicodeString. @@ -1271,4 +1289,6 @@ #endif /* #if !UCONFIG_NO_COLLATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/compactdecimalformat.h icu-65.1/source/i18n/unicode/compactdecimalformat.h --- icu-64.2/source/i18n/unicode/compactdecimalformat.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/compactdecimalformat.h 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,9 @@ #define __COMPACT_DECIMAL_FORMAT_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Compatibility APIs for compact decimal number formatting. @@ -102,7 +105,7 @@ * @return a polymorphic copy of this CompactDecimalFormat. * @stable ICU 51 */ - Format* clone() const U_OVERRIDE; + CompactDecimalFormat* clone() const U_OVERRIDE; using DecimalFormat::format; @@ -187,5 +190,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __COMPACT_DECIMAL_FORMAT_H__ //eof diff -Nru icu-64.2/source/i18n/unicode/curramt.h icu-65.1/source/i18n/unicode/curramt.h --- icu-64.2/source/i18n/unicode/curramt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/curramt.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/measure.h" @@ -79,7 +81,7 @@ * have the same class as returned by getDynamicClassID(). * @stable ICU 3.0 */ - virtual UObject* clone() const; + virtual CurrencyAmount* clone() const; /** * Destructor @@ -129,4 +131,7 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_FORMATTING + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __CURRENCYAMOUNT_H__ diff -Nru icu-64.2/source/i18n/unicode/currpinf.h icu-65.1/source/i18n/unicode/currpinf.h --- icu-64.2/source/i18n/unicode/currpinf.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/currpinf.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Currency Plural Information used by Decimal Format @@ -266,5 +268,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _CURRPINFO //eof diff -Nru icu-64.2/source/i18n/unicode/currunit.h icu-65.1/source/i18n/unicode/currunit.h --- icu-64.2/source/i18n/unicode/currunit.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/currunit.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/measunit.h" @@ -94,7 +96,7 @@ * have the same class as returned by getDynamicClassID(). * @stable ICU 3.0 */ - virtual UObject* clone() const; + virtual CurrencyUnit* clone() const; /** * Destructor @@ -140,4 +142,7 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_FORMATTING + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __CURRENCYUNIT_H__ diff -Nru icu-64.2/source/i18n/unicode/datefmt.h icu-65.1/source/i18n/unicode/datefmt.h --- icu-64.2/source/i18n/unicode/datefmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/datefmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -23,6 +23,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/udat.h" @@ -222,6 +224,14 @@ virtual ~DateFormat(); /** + * Clones this object polymorphically. + * The caller owns the result and should delete it when done. + * @return clone, or nullptr if an error occurred + * @stable ICU 2.0 + */ + virtual DateFormat* clone() const = 0; + + /** * Equality operator. Returns true if the two formats have the same behavior. * @stable ICU 2.0 */ @@ -953,5 +963,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _DATEFMT //eof diff -Nru icu-64.2/source/i18n/unicode/dcfmtsym.h icu-65.1/source/i18n/unicode/dcfmtsym.h --- icu-64.2/source/i18n/unicode/dcfmtsym.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/dcfmtsym.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,10 +28,12 @@ #define DCFMTSYM_H #include "unicode/utypes.h" -#include "unicode/uchar.h" + +#if U_SHOW_CPLUSPLUS_API #if !UCONFIG_NO_FORMATTING +#include "unicode/uchar.h" #include "unicode/uobject.h" #include "unicode/locid.h" #include "unicode/numsys.h" @@ -455,13 +457,11 @@ * to non-resource bundle strings, * then regular UnicodeString copies must be used instead of fastCopyFrom(). * - * @internal */ UnicodeString fSymbols[kFormatSymbolCount]; /** * Non-symbol variable for getConstSymbol(). Always empty. - * @internal */ UnicodeString fNoSymbol; @@ -582,5 +582,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _DCFMTSYM //eof diff -Nru icu-64.2/source/i18n/unicode/decimfmt.h icu-65.1/source/i18n/unicode/decimfmt.h --- icu-64.2/source/i18n/unicode/decimfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/decimfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,9 @@ #define DECIMFMT_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Compatibility APIs for decimal formatting. @@ -896,7 +899,7 @@ * @return a polymorphic copy of this DecimalFormat. * @stable ICU 2.0 */ - Format* clone(void) const U_OVERRIDE; + DecimalFormat* clone() const U_OVERRIDE; /** * Return true if the given Format objects are semantically equal. @@ -1331,7 +1334,6 @@ */ virtual void setMultiplier(int32_t newValue); -#ifndef U_HIDE_DRAFT_API /** * Gets the power of ten by which number should be multiplied before formatting, which * can be combined with setMultiplier() to multiply by any arbitrary decimal value. @@ -1342,7 +1344,7 @@ * This method is analogous to UNUM_SCALE in getAttribute. * * @return the current value of the power-of-ten multiplier. - * @draft ICU 62 + * @stable ICU 62 */ int32_t getMultiplierScale(void) const; @@ -1363,10 +1365,9 @@ * This method is analogous to UNUM_SCALE in setAttribute. * * @param newValue the new value of the power-of-ten multiplier. - * @draft ICU 62 + * @stable ICU 62 */ void setMultiplierScale(int32_t newValue); -#endif /* U_HIDE_DRAFT_API */ /** * Get the rounding increment. @@ -2020,12 +2021,14 @@ */ void setCurrency(const char16_t* theCurrency, UErrorCode& ec) U_OVERRIDE; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Sets the currency used to display currency amounts. See * setCurrency(const char16_t*, UErrorCode&). * @deprecated ICU 3.0. Use setCurrency(const char16_t*, UErrorCode&). */ virtual void setCurrency(const char16_t* theCurrency); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Sets the `Currency Usage` object used to display currency. @@ -2113,22 +2116,6 @@ const number::LocalizedNumberFormatter* toNumberFormatter(UErrorCode& status) const; #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DEPRECATED_API - /** - * Deprecated: Like {@link #toNumberFormatter(UErrorCode&) const}, - * but does not take an error code. - * - * The new signature should be used in case an error occurs while returning the - * LocalizedNumberFormatter. - * - * This old signature will be removed in ICU 65. - * - * @return A reference to an internal object. - * @deprecated ICU 64 - */ - const number::LocalizedNumberFormatter& toNumberFormatter() const; -#endif /* U_HIDE_DEPRECATED_API */ - /** * Return the class ID for this class. This is useful only for * comparing to a return value from getDynamicClassID(). For example: @@ -2216,5 +2203,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _DECIMFMT //eof diff -Nru icu-64.2/source/i18n/unicode/dtfmtsym.h icu-65.1/source/i18n/unicode/dtfmtsym.h --- icu-64.2/source/i18n/unicode/dtfmtsym.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/dtfmtsym.h 2019-10-03 11:16:41.000000000 +0000 @@ -22,6 +22,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/calendar.h" @@ -1011,5 +1013,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _DTFMTSYM //eof diff -Nru icu-64.2/source/i18n/unicode/dtitvfmt.h icu-65.1/source/i18n/unicode/dtitvfmt.h --- icu-64.2/source/i18n/unicode/dtitvfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/dtitvfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Format and parse date interval in a language-independent manner. @@ -432,7 +434,7 @@ * @return A copy of the object. * @stable ICU 4.0 */ - virtual Format* clone(void) const; + virtual DateIntervalFormat* clone() const; /** * Return true if the given Format objects are semantically equal. Objects @@ -1151,5 +1153,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _DTITVFMT_H__ //eof diff -Nru icu-64.2/source/i18n/unicode/dtitvinf.h icu-65.1/source/i18n/unicode/dtitvinf.h --- icu-64.2/source/i18n/unicode/dtitvinf.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/dtitvinf.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Date/Time interval patterns for formatting date/time interval @@ -195,7 +197,7 @@ * @return a copy of the object * @stable ICU 4.0 */ - virtual DateIntervalInfo* clone(void) const; + virtual DateIntervalInfo* clone() const; /** * Destructor. @@ -515,5 +517,7 @@ #endif +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/dtptngen.h icu-65.1/source/i18n/unicode/dtptngen.h --- icu-64.2/source/i18n/unicode/dtptngen.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/dtptngen.h 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,10 @@ #ifndef __DTPTNGEN_H__ #define __DTPTNGEN_H__ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/datefmt.h" #include "unicode/locid.h" #include "unicode/udat.h" @@ -279,7 +283,7 @@ * * @param field The desired UDateTimePatternField, such as UDATPG_ERA_FIELD. * @param width The desired UDateTimePGDisplayWidth, such as UDATPG_ABBREVIATED. - * @return. The display name for field + * @return The display name for field * @stable ICU 61 */ UnicodeString getFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width) const; @@ -561,12 +565,10 @@ void setDateTimeFromCalendar(const Locale& locale, UErrorCode& status); void setDecimalSymbols(const Locale& locale, UErrorCode& status); UDateTimePatternField getAppendFormatNumber(const char* field) const; -#ifndef U_HIDE_DRAFT_API - // The following three have to be U_HIDE_DRAFT_API (though private) because UDateTimePGDisplayWidth is + // Note for the next 3: UDateTimePGDisplayWidth is now stable ICU 61 UDateTimePatternField getFieldAndWidthIndices(const char* key, UDateTimePGDisplayWidth* widthP) const; void setFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width, const UnicodeString& value); UnicodeString& getMutableFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width); -#endif // U_HIDE_DRAFT_API void getAppendName(UDateTimePatternField field, UnicodeString& value); UnicodeString mapSkeletonMetacharacters(const UnicodeString& patternForm, int32_t* flags, UErrorCode& status); const UnicodeString* getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, UErrorCode& status, const PtnSkeleton** specifiedSkeletonPtr = 0); @@ -587,4 +589,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/dtrule.h icu-65.1/source/i18n/unicode/dtrule.h --- icu-64.2/source/i18n/unicode/dtrule.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/dtrule.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Rule for specifying date and time in an year @@ -126,7 +128,7 @@ * @return A copy of the object. * @stable ICU 3.8 */ - DateTimeRule* clone(void) const; + DateTimeRule* clone() const; /** * Assignment operator. @@ -248,5 +250,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // DTRULE_H //eof diff -Nru icu-64.2/source/i18n/unicode/fieldpos.h icu-65.1/source/i18n/unicode/fieldpos.h --- icu-64.2/source/i18n/unicode/fieldpos.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/fieldpos.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,6 +26,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: FieldPosition identifies the fields in a formatted output. @@ -290,5 +292,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _FIELDPOS //eof diff -Nru icu-64.2/source/i18n/unicode/fmtable.h icu-65.1/source/i18n/unicode/fmtable.h --- icu-64.2/source/i18n/unicode/fmtable.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/fmtable.h 2019-10-03 11:16:41.000000000 +0000 @@ -19,6 +19,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Formattable is a thin wrapper for primitive types used for formatting and parsing @@ -751,5 +753,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif //_FMTABLE //eof diff -Nru icu-64.2/source/i18n/unicode/format.h icu-65.1/source/i18n/unicode/format.h --- icu-64.2/source/i18n/unicode/format.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/format.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,6 +26,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Base class for all formats. @@ -303,5 +305,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _FORMAT //eof diff -Nru icu-64.2/source/i18n/unicode/formattedvalue.h icu-65.1/source/i18n/unicode/formattedvalue.h --- icu-64.2/source/i18n/unicode/formattedvalue.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/formattedvalue.h 2019-10-03 11:16:41.000000000 +0000 @@ -5,8 +5,10 @@ #define __FORMATTEDVALUE_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API #include "unicode/appendable.h" #include "unicode/fpositer.h" @@ -24,6 +26,10 @@ */ +// The following cannot have #ifndef U_HIDE_DRAFT_API because +// class FormattedValue depends on it, and FormattedValue cannot be +// hidden becauseclass FormattedNumber (stable ICU 60) depends on it. +#ifndef U_FORCE_HIDE_DRAFT_API /** * Represents a span of a string containing a given field. * @@ -52,6 +58,7 @@ /** @draft ICU 64 */ ~ConstrainedFieldPosition(); +#ifndef U_HIDE_DRAFT_API /** * Resets this ConstrainedFieldPosition to its initial state, as if it were newly created: * @@ -221,17 +228,23 @@ int32_t field, int32_t start, int32_t limit); +#endif /* U_HIDE_DRAFT_API */ private: int64_t fContext = 0LL; int32_t fField = 0; int32_t fStart = 0; int32_t fLimit = 0; +#ifndef U_HIDE_DRAFT_API int32_t fCategory = UFIELD_CATEGORY_UNDEFINED; +#else /* U_HIDE_DRAFT_API */ + int32_t fCategory = 0; +#endif /* U_HIDE_DRAFT_API */ int8_t fConstraint = 0; }; - +// The following cannot have #ifndef U_HIDE_DRAFT_API because +// class FormattedNumber (stable ICU 60) depends on it. /** * An abstract formatted value: a string with associated field attributes. * Many formatters format to classes implementing FormattedValue. @@ -308,10 +321,12 @@ */ virtual UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const = 0; }; - +#endif // U_FORCE_HIDE_DRAFT_API U_NAMESPACE_END -#endif /* U_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __FORMATTEDVALUE_H__ diff -Nru icu-64.2/source/i18n/unicode/fpositer.h icu-65.1/source/i18n/unicode/fpositer.h --- icu-64.2/source/i18n/unicode/fpositer.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/fpositer.h 2019-10-03 11:16:41.000000000 +0000 @@ -19,6 +19,9 @@ #define FPOSITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -116,4 +119,6 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // FPOSITER_H diff -Nru icu-64.2/source/i18n/unicode/gender.h icu-65.1/source/i18n/unicode/gender.h --- icu-64.2/source/i18n/unicode/gender.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/gender.h 2019-10-03 11:16:41.000000000 +0000 @@ -25,6 +25,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/locid.h" @@ -114,5 +116,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _GENDER //eof diff -Nru icu-64.2/source/i18n/unicode/gregocal.h icu-65.1/source/i18n/unicode/gregocal.h --- icu-64.2/source/i18n/unicode/gregocal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/gregocal.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/calendar.h" @@ -301,7 +303,7 @@ * @return return a polymorphic copy of this calendar. * @stable ICU 2.0 */ - virtual Calendar* clone(void) const; + virtual GregorianCalendar* clone() const; /** * Sets the GregorianCalendar change date. This is the point when the switch from @@ -350,6 +352,7 @@ */ virtual UBool isEquivalentTo(const Calendar& other) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * (Overrides Calendar) Rolls up or down by the given amount in the specified field. * For more information, see the documentation for Calendar::roll(). @@ -362,6 +365,7 @@ * @deprecated ICU 2.6. Use roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) instead. */ virtual void roll(EDateFields field, int32_t amount, UErrorCode& status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * (Overrides Calendar) Rolls up or down by the given amount in the specified field. @@ -774,6 +778,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _GREGOCAL //eof diff -Nru icu-64.2/source/i18n/unicode/listformatter.h icu-65.1/source/i18n/unicode/listformatter.h --- icu-64.2/source/i18n/unicode/listformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/listformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -21,6 +21,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unistr.h" #include "unicode/locid.h" #include "unicode/formattedvalue.h" @@ -237,7 +239,7 @@ UnicodeString& format(const UnicodeString items[], int32_t n_items, UnicodeString & appendTo, FieldPositionIterator* posIter, UErrorCode& errorCode) const; -#endif /* U_HIDE_DRAFT_API */ +#endif // U_HIDE_DRAFT_API #if !UCONFIG_NO_FORMATTING #ifndef U_HIDE_DRAFT_API @@ -298,4 +300,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __LISTFORMATTER_H__ diff -Nru icu-64.2/source/i18n/unicode/measfmt.h icu-65.1/source/i18n/unicode/measfmt.h --- icu-64.2/source/i18n/unicode/measfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/measfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/format.h" @@ -151,7 +153,7 @@ * Clones this object polymorphically. * @stable ICU 53 */ - virtual Format *clone() const; + virtual MeasureFormat *clone() const; /** * Formats object to produce a string. @@ -163,6 +165,7 @@ FieldPosition &pos, UErrorCode &status) const; +#ifndef U_FORCE_HIDE_DRAFT_API /** * Parse a string to produce an object. This implementation sets * status to U_UNSUPPORTED_ERROR. @@ -173,6 +176,7 @@ const UnicodeString &source, Formattable &reslt, ParsePosition &pos) const; +#endif // U_FORCE_HIDE_DRAFT_API /** * Formats measure objects to produce a string. An example of such a @@ -382,17 +386,12 @@ int32_t bitMap, // 1=hour set, 2=minute set, 4=second set UnicodeString &appendTo, UErrorCode &status) const; - - UnicodeString &formatNumeric( - UDate date, - const DateFormat &dateFmt, - UDateFormatField smallestField, - const Formattable &smallestAmount, - UnicodeString &appendTo, - UErrorCode &status) const; }; U_NAMESPACE_END #endif // #if !UCONFIG_NO_FORMATTING + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // #ifndef MEASUREFORMAT_H diff -Nru icu-64.2/source/i18n/unicode/measunit.h icu-65.1/source/i18n/unicode/measunit.h --- icu-64.2/source/i18n/unicode/measunit.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/measunit.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/unistr.h" @@ -62,7 +64,7 @@ * have the same class as returned by getDynamicClassID(). * @stable ICU 3.0 */ - virtual UObject* clone() const; + virtual MeasureUnit* clone() const; /** * Destructor @@ -604,16 +606,14 @@ static MeasureUnit getPartPerMillion(); #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: percent. * Caller owns returned value and must free it. * Also see {@link #getPercent()}. * @param status ICU error code. - * @draft ICU 63 + * @stable ICU 63 */ static MeasureUnit *createPercent(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -624,16 +624,14 @@ static MeasureUnit getPercent(); #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: permille. * Caller owns returned value and must free it. * Also see {@link #getPermille()}. * @param status ICU error code. - * @draft ICU 63 + * @stable ICU 63 */ static MeasureUnit *createPermille(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -878,16 +876,14 @@ static MeasureUnit getMegabyte(); #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of digital: petabyte. * Caller owns returned value and must free it. * Also see {@link #getPetabyte()}. * @param status ICU error code. - * @draft ICU 63 + * @stable ICU 63 */ static MeasureUnit *createPetabyte(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -979,9 +975,7 @@ * @draft ICU 64 */ static MeasureUnit *createDayPerson(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: day-person. * Also see {@link #createDayPerson()}. @@ -990,6 +984,24 @@ static MeasureUnit getDayPerson(); #endif /* U_HIDE_DRAFT_API */ +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of duration: decade. + * Caller owns returned value and must free it. + * Also see {@link #getDecade()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createDecade(UErrorCode &status); + + /** + * Returns by value, unit of duration: decade. + * Also see {@link #createDecade()}. + * @draft ICU 65 + */ + static MeasureUnit getDecade(); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns by pointer, unit of duration: hour. * Caller owns returned value and must free it. @@ -1089,9 +1101,7 @@ * @draft ICU 64 */ static MeasureUnit *createMonthPerson(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: month-person. * Also see {@link #createMonthPerson()}. @@ -1163,9 +1173,7 @@ * @draft ICU 64 */ static MeasureUnit *createWeekPerson(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: week-person. * Also see {@link #createWeekPerson()}. @@ -1201,9 +1209,7 @@ * @draft ICU 64 */ static MeasureUnit *createYearPerson(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by value, unit of duration: year-person. * Also see {@link #createYearPerson()}. @@ -1430,6 +1436,24 @@ #ifndef U_HIDE_DRAFT_API /** + * Returns by pointer, unit of energy: therm-us. + * Caller owns returned value and must free it. + * Also see {@link #getThermUs()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createThermUs(UErrorCode &status); + + /** + * Returns by value, unit of energy: therm-us. + * Also see {@link #createThermUs()}. + * @draft ICU 65 + */ + static MeasureUnit getThermUs(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** * Returns by pointer, unit of force: newton. * Caller owns returned value and must free it. * Also see {@link #getNewton()}. @@ -1536,6 +1560,132 @@ static MeasureUnit getMegahertz(); #endif /* U_HIDE_DRAFT_API */ +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: dot-per-centimeter. + * Caller owns returned value and must free it. + * Also see {@link #getDotPerCentimeter()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createDotPerCentimeter(UErrorCode &status); + + /** + * Returns by value, unit of graphics: dot-per-centimeter. + * Also see {@link #createDotPerCentimeter()}. + * @draft ICU 65 + */ + static MeasureUnit getDotPerCentimeter(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: dot-per-inch. + * Caller owns returned value and must free it. + * Also see {@link #getDotPerInch()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createDotPerInch(UErrorCode &status); + + /** + * Returns by value, unit of graphics: dot-per-inch. + * Also see {@link #createDotPerInch()}. + * @draft ICU 65 + */ + static MeasureUnit getDotPerInch(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: em. + * Caller owns returned value and must free it. + * Also see {@link #getEm()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createEm(UErrorCode &status); + + /** + * Returns by value, unit of graphics: em. + * Also see {@link #createEm()}. + * @draft ICU 65 + */ + static MeasureUnit getEm(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: megapixel. + * Caller owns returned value and must free it. + * Also see {@link #getMegapixel()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createMegapixel(UErrorCode &status); + + /** + * Returns by value, unit of graphics: megapixel. + * Also see {@link #createMegapixel()}. + * @draft ICU 65 + */ + static MeasureUnit getMegapixel(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: pixel. + * Caller owns returned value and must free it. + * Also see {@link #getPixel()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createPixel(UErrorCode &status); + + /** + * Returns by value, unit of graphics: pixel. + * Also see {@link #createPixel()}. + * @draft ICU 65 + */ + static MeasureUnit getPixel(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: pixel-per-centimeter. + * Caller owns returned value and must free it. + * Also see {@link #getPixelPerCentimeter()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createPixelPerCentimeter(UErrorCode &status); + + /** + * Returns by value, unit of graphics: pixel-per-centimeter. + * Also see {@link #createPixelPerCentimeter()}. + * @draft ICU 65 + */ + static MeasureUnit getPixelPerCentimeter(); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of graphics: pixel-per-inch. + * Caller owns returned value and must free it. + * Also see {@link #getPixelPerInch()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createPixelPerInch(UErrorCode &status); + + /** + * Returns by value, unit of graphics: pixel-per-inch. + * Also see {@link #createPixelPerInch()}. + * @draft ICU 65 + */ + static MeasureUnit getPixelPerInch(); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns by pointer, unit of length: astronomical-unit. * Caller owns returned value and must free it. @@ -2310,16 +2460,14 @@ static MeasureUnit getWatt(); #endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of pressure: atmosphere. * Caller owns returned value and must free it. * Also see {@link #getAtmosphere()}. * @param status ICU error code. - * @draft ICU 63 + * @stable ICU 63 */ static MeasureUnit *createAtmosphere(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -2330,6 +2478,24 @@ static MeasureUnit getAtmosphere(); #endif /* U_HIDE_DRAFT_API */ +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of pressure: bar. + * Caller owns returned value and must free it. + * Also see {@link #getBar()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createBar(UErrorCode &status); + + /** + * Returns by value, unit of pressure: bar. + * Also see {@link #createBar()}. + * @draft ICU 65 + */ + static MeasureUnit getBar(); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns by pointer, unit of pressure: hectopascal. * Caller owns returned value and must free it. @@ -2438,6 +2604,24 @@ static MeasureUnit getMillimeterOfMercury(); #endif /* U_HIDE_DRAFT_API */ +#ifndef U_HIDE_DRAFT_API + /** + * Returns by pointer, unit of pressure: pascal. + * Caller owns returned value and must free it. + * Also see {@link #getPascal()}. + * @param status ICU error code. + * @draft ICU 65 + */ + static MeasureUnit *createPascal(UErrorCode &status); + + /** + * Returns by value, unit of pressure: pascal. + * Also see {@link #createPascal()}. + * @draft ICU 65 + */ + static MeasureUnit getPascal(); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns by pointer, unit of pressure: pound-per-square-inch. * Caller owns returned value and must free it. @@ -3164,4 +3348,7 @@ U_NAMESPACE_END #endif // !UNCONFIG_NO_FORMATTING + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __MEASUREUNIT_H__ diff -Nru icu-64.2/source/i18n/unicode/measure.h icu-65.1/source/i18n/unicode/measure.h --- icu-64.2/source/i18n/unicode/measure.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/measure.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: MeasureUnit object. @@ -72,7 +74,7 @@ * have the same class as returned by getDynamicClassID(). * @stable ICU 3.0 */ - virtual UObject* clone() const; + virtual Measure* clone() const; /** * Destructor @@ -158,4 +160,7 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_FORMATTING + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __MEASURE_H__ diff -Nru icu-64.2/source/i18n/unicode/msgfmt.h icu-65.1/source/i18n/unicode/msgfmt.h --- icu-64.2/source/i18n/unicode/msgfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/msgfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -21,6 +21,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Formats messages in a language-neutral way. @@ -184,7 +186,7 @@ * argSkeletonText * NumberFormatter::forSkeleton(argSkeletonText, status).locale(getLocale()).toFormat(status) * - * date + * date * (none) * DateFormat.createDateInstance(kDefault, getLocale(), status) * @@ -418,7 +420,7 @@ * result and should delete it when done. * @stable ICU 2.0 */ - virtual Format* clone(void) const; + virtual MessageFormat* clone() const; /** * Returns true if the given Format objects are semantically equal. @@ -1087,7 +1089,7 @@ class U_I18N_API DummyFormat : public Format { public: virtual UBool operator==(const Format&) const; - virtual Format* clone() const; + virtual DummyFormat* clone() const; virtual UnicodeString& format(const Formattable& obj, UnicodeString& appendTo, UErrorCode& status) const; @@ -1111,5 +1113,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _MSGFMT //eof diff -Nru icu-64.2/source/i18n/unicode/nounit.h icu-65.1/source/i18n/unicode/nounit.h --- icu-64.2/source/i18n/unicode/nounit.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/nounit.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,11 +12,14 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API #include "unicode/measunit.h" +#ifndef U_HIDE_DRAFT_API + /** * \file * \brief C++ API: units for percent and permille @@ -72,7 +75,7 @@ * have the same class as returned by getDynamicClassID(). * @draft ICU 60 */ - virtual UObject* clone() const; + virtual NoUnit* clone() const; /** * Returns a unique class ID for this object POLYMORPHICALLY. @@ -106,6 +109,8 @@ #endif /* U_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __NOUNIT_H__ //eof // diff -Nru icu-64.2/source/i18n/unicode/numberformatter.h icu-65.1/source/i18n/unicode/numberformatter.h --- icu-64.2/source/i18n/unicode/numberformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/numberformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -1,15 +1,19 @@ // © 2017 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html +#ifndef __NUMBERFORMATTER_H__ +#define __NUMBERFORMATTER_H__ + #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING -#ifndef __NUMBERFORMATTER_H__ -#define __NUMBERFORMATTER_H__ #include "unicode/appendable.h" -#include "unicode/dcfmtsym.h" +#include "unicode/bytestream.h" #include "unicode/currunit.h" +#include "unicode/dcfmtsym.h" #include "unicode/fieldpos.h" #include "unicode/formattedvalue.h" #include "unicode/fpositer.h" @@ -22,8 +26,6 @@ #include "unicode/unumberformatter.h" #include "unicode/uobject.h" -#ifndef U_HIDE_DRAFT_API - /** * \file * \brief C++ API: Library for localized number formatting introduced in ICU 60. @@ -85,6 +87,7 @@ // Forward declarations: class IFixedDecimal; class FieldPositionIteratorHandler; +class FormattedStringBuilder; namespace numparse { namespace impl { @@ -142,7 +145,6 @@ class RoundingImpl; class ScientificHandler; class Modifier; -class NumberStringBuilder; class AffixPatternProvider; class NumberPropertyMapper; struct DecimalFormatProperties; @@ -167,21 +169,21 @@ /** * Extra name reserved in case it is needed in the future. * - * @draft ICU 63 + * @stable ICU 63 */ typedef Notation CompactNotation; /** * Extra name reserved in case it is needed in the future. * - * @draft ICU 63 + * @stable ICU 63 */ typedef Notation SimpleNotation; /** * A class that defines the notation style to be used when formatting numbers in NumberFormatter. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API Notation : public UMemory { public: @@ -207,7 +209,7 @@ * * * @return A ScientificNotation for chaining or passing to the NumberFormatter notation() setter. - * @draft ICU 60 + * @stable ICU 60 */ static ScientificNotation scientific(); @@ -231,7 +233,7 @@ * * * @return A ScientificNotation for chaining or passing to the NumberFormatter notation() setter. - * @draft ICU 60 + * @stable ICU 60 */ static ScientificNotation engineering(); @@ -274,7 +276,7 @@ * * * @return A CompactNotation for passing to the NumberFormatter notation() setter. - * @draft ICU 60 + * @stable ICU 60 */ static CompactNotation compactShort(); @@ -298,7 +300,7 @@ * * * @return A CompactNotation for passing to the NumberFormatter notation() setter. - * @draft ICU 60 + * @stable ICU 60 */ static CompactNotation compactLong(); @@ -324,7 +326,7 @@ * * * @return A SimpleNotation for passing to the NumberFormatter notation() setter. - * @draft ICU 60 + * @stable ICU 60 */ static SimpleNotation simple(); @@ -391,7 +393,7 @@ *

    * To create a ScientificNotation, use one of the factory methods in {@link Notation}. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API ScientificNotation : public Notation { public: @@ -406,7 +408,7 @@ * @param minExponentDigits * The minimum number of digits to show in the exponent. * @return A ScientificNotation, for chaining. - * @draft ICU 60 + * @stable ICU 60 */ ScientificNotation withMinExponentDigits(int32_t minExponentDigits) const; @@ -421,7 +423,7 @@ * @param exponentSignDisplay * The strategy for displaying the sign in the exponent. * @return A ScientificNotation, for chaining. - * @draft ICU 60 + * @stable ICU 60 */ ScientificNotation withExponentSignDisplay(UNumberSignDisplay exponentSignDisplay) const; @@ -442,7 +444,7 @@ /** * Extra name reserved in case it is needed in the future. * - * @draft ICU 63 + * @stable ICU 63 */ typedef Precision SignificantDigitsPrecision; @@ -452,7 +454,7 @@ *

    * To create a Precision, use one of the factory methods. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API Precision : public UMemory { @@ -472,7 +474,7 @@ * http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/ * * @return A Precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static Precision unlimited(); @@ -480,7 +482,7 @@ * Show numbers rounded if necessary to the nearest integer. * * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static FractionPrecision integer(); @@ -509,7 +511,7 @@ * The minimum and maximum number of numerals to display after the decimal separator (rounding if too * long or padding with zeros if too short). * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static FractionPrecision fixedFraction(int32_t minMaxFractionPlaces); @@ -524,7 +526,7 @@ * The minimum number of numerals to display after the decimal separator (padding with zeros if * necessary). * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static FractionPrecision minFraction(int32_t minFractionPlaces); @@ -536,7 +538,7 @@ * @param maxFractionPlaces * The maximum number of numerals to display after the decimal mark (rounding if necessary). * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static FractionPrecision maxFraction(int32_t maxFractionPlaces); @@ -551,7 +553,7 @@ * @param maxFractionPlaces * The maximum number of numerals to display after the decimal separator (rounding if necessary). * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static FractionPrecision minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces); @@ -566,7 +568,7 @@ * The minimum and maximum number of significant digits to display (rounding if too long or padding with * zeros if too short). * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 62 + * @stable ICU 62 */ static SignificantDigitsPrecision fixedSignificantDigits(int32_t minMaxSignificantDigits); @@ -580,7 +582,7 @@ * @param minSignificantDigits * The minimum number of significant digits to display (padding with zeros if too short). * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 62 + * @stable ICU 62 */ static SignificantDigitsPrecision minSignificantDigits(int32_t minSignificantDigits); @@ -590,7 +592,7 @@ * @param maxSignificantDigits * The maximum number of significant digits to display (rounding if too long). * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 62 + * @stable ICU 62 */ static SignificantDigitsPrecision maxSignificantDigits(int32_t maxSignificantDigits); @@ -603,7 +605,7 @@ * @param maxSignificantDigits * The maximum number of significant digits to display (rounding if necessary). * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 62 + * @stable ICU 62 */ static SignificantDigitsPrecision minMaxSignificantDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits); @@ -625,7 +627,7 @@ * @param roundingIncrement * The increment to which to round numbers. * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static IncrementPrecision increment(double roundingIncrement); @@ -644,7 +646,7 @@ * Either STANDARD (for digital transactions) or CASH (for transactions where the rounding increment may * be limited by the available denominations of cash or coins). * @return A CurrencyPrecision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ static CurrencyPrecision currency(UCurrencyUsage currencyUsage); @@ -771,7 +773,7 @@ *

    * To create a FractionPrecision, use one of the factory methods on Precision. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API FractionPrecision : public Precision { public: @@ -789,7 +791,7 @@ * @param minSignificantDigits * The number of significant figures to guarantee. * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ Precision withMinDigits(int32_t minSignificantDigits) const; @@ -808,7 +810,7 @@ * @param maxSignificantDigits * Round the number to no more than this number of significant figures. * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ Precision withMaxDigits(int32_t maxSignificantDigits) const; @@ -827,7 +829,7 @@ *

    * To create a CurrencyPrecision, use one of the factory methods on Precision. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API CurrencyPrecision : public Precision { public: @@ -846,7 +848,7 @@ * @param currency * The currency to associate with this rounding precision. * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ Precision withCurrency(const CurrencyUnit ¤cy) const; @@ -865,7 +867,7 @@ *

    * To create an IncrementPrecision, use one of the factory methods on Precision. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API IncrementPrecision : public Precision { public: @@ -882,7 +884,7 @@ * * @param minFrac The minimum number of digits after the decimal separator. * @return A precision for chaining or passing to the NumberFormatter precision() setter. - * @draft ICU 60 + * @stable ICU 60 */ Precision withMinFraction(int32_t minFrac) const; @@ -900,7 +902,7 @@ *

    * To create an IntegerWidth, use one of the factory methods. * - * @draft ICU 60 + * @stable ICU 60 * @see NumberFormatter */ class U_I18N_API IntegerWidth : public UMemory { @@ -914,7 +916,7 @@ * @param minInt * The minimum number of places before the decimal separator. * @return An IntegerWidth for chaining or passing to the NumberFormatter integerWidth() setter. - * @draft ICU 60 + * @stable ICU 60 */ static IntegerWidth zeroFillTo(int32_t minInt); @@ -927,7 +929,7 @@ * The maximum number of places before the decimal separator. maxInt == -1 means no * truncation. * @return An IntegerWidth for passing to the NumberFormatter integerWidth() setter. - * @draft ICU 60 + * @stable ICU 60 */ IntegerWidth truncateAt(int32_t maxInt); @@ -994,7 +996,7 @@ *

    * To create a Scale, use one of the factory methods. * - * @draft ICU 62 + * @stable ICU 62 */ class U_I18N_API Scale : public UMemory { public: @@ -1002,7 +1004,7 @@ * Do not change the value of numbers when formatting or parsing. * * @return A Scale to prevent any multiplication. - * @draft ICU 62 + * @stable ICU 62 */ static Scale none(); @@ -1014,7 +1016,7 @@ * * * @return A Scale for passing to the setter in NumberFormatter. - * @draft ICU 62 + * @stable ICU 62 */ static Scale powerOfTen(int32_t power); @@ -1028,7 +1030,7 @@ * Also see the version of this method that takes a double. * * @return A Scale for passing to the setter in NumberFormatter. - * @draft ICU 62 + * @stable ICU 62 */ static Scale byDecimal(StringPiece multiplicand); @@ -1038,7 +1040,7 @@ * This method takes a double; also see the version of this method that takes an exact decimal. * * @return A Scale for passing to the setter in NumberFormatter. - * @draft ICU 62 + * @stable ICU 62 */ static Scale byDouble(double multiplicand); @@ -1046,26 +1048,26 @@ * Multiply a number by both a power of ten and by an arbitrary double value. * * @return A Scale for passing to the setter in NumberFormatter. - * @draft ICU 62 + * @stable ICU 62 */ static Scale byDoubleAndPowerOfTen(double multiplicand, int32_t power); // We need a custom destructor for the DecNum, which means we need to declare // the copy/move constructor/assignment quartet. - /** @draft ICU 62 */ + /** @stable ICU 62 */ Scale(const Scale& other); - /** @draft ICU 62 */ + /** @stable ICU 62 */ Scale& operator=(const Scale& other); - /** @draft ICU 62 */ + /** @stable ICU 62 */ Scale(Scale&& src) U_NOEXCEPT; - /** @draft ICU 62 */ + /** @stable ICU 62 */ Scale& operator=(Scale&& src) U_NOEXCEPT; - /** @draft ICU 62 */ + /** @stable ICU 62 */ ~Scale(); #ifndef U_HIDE_INTERNAL_API @@ -1343,7 +1345,7 @@ } int32_t padAndApply(const impl::Modifier &mod1, const impl::Modifier &mod2, - impl::NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex, + FormattedStringBuilder &string, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const; // To allow MacroProps/MicroProps to initialize empty instances: @@ -1465,7 +1467,7 @@ * The notation strategy to use. * @return The fluent chain. * @see Notation - * @draft ICU 60 + * @stable ICU 60 */ Derived notation(const Notation ¬ation) const &; @@ -1476,7 +1478,7 @@ * The notation strategy to use. * @return The fluent chain. * @see #notation - * @draft ICU 62 + * @stable ICU 62 */ Derived notation(const Notation ¬ation) &&; @@ -1521,7 +1523,7 @@ * @see Currency * @see NoUnit * @see #perUnit - * @draft ICU 60 + * @stable ICU 60 */ Derived unit(const icu::MeasureUnit &unit) const &; @@ -1532,7 +1534,7 @@ * The unit to render. * @return The fluent chain. * @see #unit - * @draft ICU 62 + * @stable ICU 62 */ Derived unit(const icu::MeasureUnit &unit) &&; @@ -1547,7 +1549,7 @@ * @return The fluent chain. * @see #unit * @see MeasureUnit - * @draft ICU 60 + * @stable ICU 60 */ Derived adoptUnit(icu::MeasureUnit *unit) const &; @@ -1558,7 +1560,7 @@ * The unit to render. * @return The fluent chain. * @see #adoptUnit - * @draft ICU 62 + * @stable ICU 62 */ Derived adoptUnit(icu::MeasureUnit *unit) &&; @@ -1582,7 +1584,7 @@ * The unit to render in the denominator. * @return The fluent chain * @see #unit - * @draft ICU 61 + * @stable ICU 61 */ Derived perUnit(const icu::MeasureUnit &perUnit) const &; @@ -1593,7 +1595,7 @@ * The unit to render in the denominator. * @return The fluent chain. * @see #perUnit - * @draft ICU 62 + * @stable ICU 62 */ Derived perUnit(const icu::MeasureUnit &perUnit) &&; @@ -1608,7 +1610,7 @@ * @return The fluent chain. * @see #perUnit * @see MeasureUnit - * @draft ICU 61 + * @stable ICU 61 */ Derived adoptPerUnit(icu::MeasureUnit *perUnit) const &; @@ -1619,7 +1621,7 @@ * The unit to render in the denominator. * @return The fluent chain. * @see #adoptPerUnit - * @draft ICU 62 + * @stable ICU 62 */ Derived adoptPerUnit(icu::MeasureUnit *perUnit) &&; @@ -1651,7 +1653,7 @@ * The rounding precision to use. * @return The fluent chain. * @see Precision - * @draft ICU 62 + * @stable ICU 62 */ Derived precision(const Precision& precision) const &; @@ -1662,7 +1664,7 @@ * The rounding precision to use. * @return The fluent chain. * @see #precision - * @draft ICU 62 + * @stable ICU 62 */ Derived precision(const Precision& precision) &&; @@ -1682,7 +1684,7 @@ * * @param roundingMode The rounding mode to use. * @return The fluent chain. - * @draft ICU 62 + * @stable ICU 62 */ Derived roundingMode(UNumberFormatRoundingMode roundingMode) const &; @@ -1692,7 +1694,7 @@ * @param roundingMode The rounding mode to use. * @return The fluent chain. * @see #roundingMode - * @draft ICU 62 + * @stable ICU 62 */ Derived roundingMode(UNumberFormatRoundingMode roundingMode) &&; @@ -1721,7 +1723,7 @@ * @param strategy * The grouping strategy to use. * @return The fluent chain. - * @draft ICU 61 + * @stable ICU 61 */ Derived grouping(UNumberGroupingStrategy strategy) const &; @@ -1732,7 +1734,7 @@ * The grouping strategy to use. * @return The fluent chain. * @see #grouping - * @draft ICU 62 + * @stable ICU 62 */ Derived grouping(UNumberGroupingStrategy strategy) &&; @@ -1758,7 +1760,7 @@ * The integer width to use. * @return The fluent chain. * @see IntegerWidth - * @draft ICU 60 + * @stable ICU 60 */ Derived integerWidth(const IntegerWidth &style) const &; @@ -1769,7 +1771,7 @@ * The integer width to use. * @return The fluent chain. * @see #integerWidth - * @draft ICU 62 + * @stable ICU 62 */ Derived integerWidth(const IntegerWidth &style) &&; @@ -1811,7 +1813,7 @@ * The DecimalFormatSymbols to use. * @return The fluent chain. * @see DecimalFormatSymbols - * @draft ICU 60 + * @stable ICU 60 */ Derived symbols(const DecimalFormatSymbols &symbols) const &; @@ -1822,7 +1824,7 @@ * The DecimalFormatSymbols to use. * @return The fluent chain. * @see #symbols - * @draft ICU 62 + * @stable ICU 62 */ Derived symbols(const DecimalFormatSymbols &symbols) &&; @@ -1857,7 +1859,7 @@ * The NumberingSystem to use. * @return The fluent chain. * @see NumberingSystem - * @draft ICU 60 + * @stable ICU 60 */ Derived adoptSymbols(NumberingSystem *symbols) const &; @@ -1868,7 +1870,7 @@ * The NumberingSystem to use. * @return The fluent chain. * @see #adoptSymbols - * @draft ICU 62 + * @stable ICU 62 */ Derived adoptSymbols(NumberingSystem *symbols) &&; @@ -1895,7 +1897,7 @@ * The width to use when rendering numbers. * @return The fluent chain * @see UNumberUnitWidth - * @draft ICU 60 + * @stable ICU 60 */ Derived unitWidth(UNumberUnitWidth width) const &; @@ -1906,7 +1908,7 @@ * The width to use when rendering numbers. * @return The fluent chain. * @see #unitWidth - * @draft ICU 62 + * @stable ICU 62 */ Derived unitWidth(UNumberUnitWidth width) &&; @@ -1933,7 +1935,7 @@ * The sign display strategy to use when rendering numbers. * @return The fluent chain * @see UNumberSignDisplay - * @draft ICU 60 + * @stable ICU 60 */ Derived sign(UNumberSignDisplay style) const &; @@ -1944,7 +1946,7 @@ * The sign display strategy to use when rendering numbers. * @return The fluent chain. * @see #sign - * @draft ICU 62 + * @stable ICU 62 */ Derived sign(UNumberSignDisplay style) &&; @@ -1971,7 +1973,7 @@ * The decimal separator display strategy to use when rendering numbers. * @return The fluent chain * @see UNumberDecimalSeparatorDisplay - * @draft ICU 60 + * @stable ICU 60 */ Derived decimal(UNumberDecimalSeparatorDisplay style) const &; @@ -1982,7 +1984,7 @@ * The decimal separator display strategy to use when rendering numbers. * @return The fluent chain. * @see #decimal - * @draft ICU 62 + * @stable ICU 62 */ Derived decimal(UNumberDecimalSeparatorDisplay style) &&; @@ -2008,7 +2010,7 @@ * @param scale * The scale to apply when rendering numbers. * @return The fluent chain - * @draft ICU 62 + * @stable ICU 62 */ Derived scale(const Scale &scale) const &; @@ -2019,7 +2021,7 @@ * The scale to apply when rendering numbers. * @return The fluent chain. * @see #scale - * @draft ICU 62 + * @stable ICU 62 */ Derived scale(const Scale &scale) &&; @@ -2076,10 +2078,11 @@ * behavior should produce the same skeleton. * * @return A number skeleton string with behavior corresponding to this number formatter. - * @draft ICU 62 + * @stable ICU 62 */ UnicodeString toSkeleton(UErrorCode& status) const; +#ifndef U_HIDE_DRAFT_API /** * Returns the current (Un)LocalizedNumberFormatter as a LocalPointer * wrapping a heap-allocated copy of the current object. @@ -2101,12 +2104,13 @@ * @draft ICU 64 */ LocalPointer clone() &&; +#endif /* U_HIDE_DRAFT_API */ /** * Sets the UErrorCode if an error occurred in the fluent chain. * Preserves older error codes in the outErrorCode. * @return TRUE if U_FAILURE(outErrorCode) - * @draft ICU 60 + * @stable ICU 60 */ UBool copyErrorTo(UErrorCode &outErrorCode) const { if (U_FAILURE(outErrorCode)) { @@ -2139,7 +2143,7 @@ * Instances of this class are immutable and thread-safe. * * @see NumberFormatter - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API UnlocalizedNumberFormatter : public NumberFormatterSettings, public UMemory { @@ -2152,7 +2156,7 @@ * @param locale * The locale to use when loading data for number formatting. * @return The fluent chain. - * @draft ICU 60 + * @stable ICU 60 */ LocalizedNumberFormatter locale(const icu::Locale &locale) const &; @@ -2163,40 +2167,40 @@ * The locale to use when loading data for number formatting. * @return The fluent chain. * @see #locale - * @draft ICU 62 + * @stable ICU 62 */ LocalizedNumberFormatter locale(const icu::Locale &locale) &&; /** * Default constructor: puts the formatter into a valid but undefined state. * - * @draft ICU 62 + * @stable ICU 62 */ UnlocalizedNumberFormatter() = default; /** * Returns a copy of this UnlocalizedNumberFormatter. - * @draft ICU 60 + * @stable ICU 60 */ UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter &other); /** * Move constructor: * The source UnlocalizedNumberFormatter will be left in a valid but undefined state. - * @draft ICU 62 + * @stable ICU 62 */ UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&& src) U_NOEXCEPT; /** * Copy assignment operator. - * @draft ICU 62 + * @stable ICU 62 */ UnlocalizedNumberFormatter& operator=(const UnlocalizedNumberFormatter& other); /** * Move assignment operator: * The source UnlocalizedNumberFormatter will be left in a valid but undefined state. - * @draft ICU 62 + * @stable ICU 62 */ UnlocalizedNumberFormatter& operator=(UnlocalizedNumberFormatter&& src) U_NOEXCEPT; @@ -2219,7 +2223,7 @@ * Instances of this class are immutable and thread-safe. * * @see NumberFormatter - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API LocalizedNumberFormatter : public NumberFormatterSettings, public UMemory { @@ -2233,7 +2237,7 @@ * @param status * Set to an ErrorCode if one occurred in the setter chain or during formatting. * @return A FormattedNumber object; call .toString() to get the string. - * @draft ICU 60 + * @stable ICU 60 */ FormattedNumber formatInt(int64_t value, UErrorCode &status) const; @@ -2246,7 +2250,7 @@ * @param status * Set to an ErrorCode if one occurred in the setter chain or during formatting. * @return A FormattedNumber object; call .toString() to get the string. - * @draft ICU 60 + * @stable ICU 60 */ FormattedNumber formatDouble(double value, UErrorCode &status) const; @@ -2262,7 +2266,7 @@ * @param status * Set to an ErrorCode if one occurred in the setter chain or during formatting. * @return A FormattedNumber object; call .toString() to get the string. - * @draft ICU 60 + * @stable ICU 60 */ FormattedNumber formatDecimal(StringPiece value, UErrorCode& status) const; @@ -2303,40 +2307,40 @@ * The caller owns the returned object and must delete it when finished. * * @return A Format wrapping this LocalizedNumberFormatter. - * @draft ICU 62 + * @stable ICU 62 */ Format* toFormat(UErrorCode& status) const; /** * Default constructor: puts the formatter into a valid but undefined state. * - * @draft ICU 62 + * @stable ICU 62 */ LocalizedNumberFormatter() = default; /** * Returns a copy of this LocalizedNumberFormatter. - * @draft ICU 60 + * @stable ICU 60 */ LocalizedNumberFormatter(const LocalizedNumberFormatter &other); /** * Move constructor: * The source LocalizedNumberFormatter will be left in a valid but undefined state. - * @draft ICU 62 + * @stable ICU 62 */ LocalizedNumberFormatter(LocalizedNumberFormatter&& src) U_NOEXCEPT; /** * Copy assignment operator. - * @draft ICU 62 + * @stable ICU 62 */ LocalizedNumberFormatter& operator=(const LocalizedNumberFormatter& other); /** * Move assignment operator: * The source LocalizedNumberFormatter will be left in a valid but undefined state. - * @draft ICU 62 + * @stable ICU 62 */ LocalizedNumberFormatter& operator=(LocalizedNumberFormatter&& src) U_NOEXCEPT; @@ -2360,7 +2364,7 @@ /** * Destruct this LocalizedNumberFormatter, cleaning up any memory it might own. - * @draft ICU 60 + * @stable ICU 60 */ ~LocalizedNumberFormatter(); @@ -2401,27 +2405,30 @@ * * Instances of this class are immutable and thread-safe. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { public: + // Default constructor cannot have #ifndef U_HIDE_DRAFT_API +#ifndef U_FORCE_HIDE_DRAFT_API /** * Default constructor; makes an empty FormattedNumber. * @draft ICU 64 */ FormattedNumber() : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} +#endif // U_FORCE_HIDE_DRAFT_API /** * Move constructor: Leaves the source FormattedNumber in an undefined state. - * @draft ICU 62 + * @stable ICU 62 */ FormattedNumber(FormattedNumber&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedNumber. - * @draft ICU 60 + * @stable ICU 60 */ virtual ~FormattedNumber() U_OVERRIDE; @@ -2433,7 +2440,7 @@ /** * Move assignment: Leaves the source FormattedNumber in an undefined state. - * @draft ICU 62 + * @stable ICU 62 */ FormattedNumber& operator=(FormattedNumber&& src) U_NOEXCEPT; @@ -2443,7 +2450,7 @@ * * For more information, see FormattedValue::toString() * - * @draft ICU 62 + * @stable ICU 62 */ UnicodeString toString(UErrorCode& status) const U_OVERRIDE; @@ -2457,7 +2464,7 @@ * * For more information, see FormattedValue::appendTo() * - * @draft ICU 62 + * @stable ICU 62 */ Appendable &appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE; @@ -2465,6 +2472,7 @@ /** @copydoc FormattedValue::nextPosition() */ UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; +#ifndef U_HIDE_DRAFT_API /** * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given * field in the output string. This allows you to determine the locations of, for example, @@ -2516,6 +2524,30 @@ * @see UNumberFormatFields */ void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Export the formatted number as a "numeric string" conforming to the + * syntax defined in the Decimal Arithmetic Specification, available at + * http://speleotrove.com/decimal + * + * This endpoint is useful for obtaining the exact number being printed + * after scaling and rounding have been applied by the number formatter. + * + * Example call site: + * + * auto decimalNumber = fn.toDecimalNumber(status); + * + * @tparam StringClass A string class compatible with StringByteSink; + * for example, std::string. + * @param status Set if an error occurs. + * @return A StringClass containing the numeric string. + * @draft ICU 65 + */ + template + inline StringClass toDecimalNumber(UErrorCode& status) const; +#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_INTERNAL_API @@ -2550,6 +2582,9 @@ explicit FormattedNumber(UErrorCode errorCode) : fData(nullptr), fErrorCode(errorCode) {} + // TODO(ICU-20775): Propose this as API. + void toDecimalNumber(ByteSink& sink, UErrorCode& status) const; + // To give LocalizedNumberFormatter format methods access to this class's constructor: friend class LocalizedNumberFormatter; @@ -2557,10 +2592,21 @@ friend struct impl::UFormattedNumberImpl; }; +#ifndef U_HIDE_DRAFT_API +// Note: This is draft ICU 65 +template +StringClass FormattedNumber::toDecimalNumber(UErrorCode& status) const { + StringClass result; + StringByteSink sink(&result); + toDecimalNumber(sink, status); + return result; +}; +#endif // U_HIDE_DRAFT_API + /** * See the main description in numberformatter.h for documentation and examples. * - * @draft ICU 60 + * @stable ICU 60 */ class U_I18N_API NumberFormatter final { public: @@ -2569,7 +2615,7 @@ * the call site. * * @return An {@link UnlocalizedNumberFormatter}, to be used for chaining. - * @draft ICU 60 + * @stable ICU 60 */ static UnlocalizedNumberFormatter with(); @@ -2580,7 +2626,7 @@ * @param locale * The locale from which to load formats and symbols for number formatting. * @return A {@link LocalizedNumberFormatter}, to be used for chaining. - * @draft ICU 60 + * @stable ICU 60 */ static LocalizedNumberFormatter withLocale(const Locale &locale); @@ -2596,10 +2642,11 @@ * @param status * Set to U_NUMBER_SKELETON_SYNTAX_ERROR if the skeleton was invalid. * @return An UnlocalizedNumberFormatter, to be used for chaining. - * @draft ICU 62 + * @stable ICU 62 */ static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UErrorCode& status); +#ifndef U_HIDE_DRAFT_API /** * Call this method at the beginning of a NumberFormatter fluent chain to create an instance based * on a given number skeleton string. @@ -2619,6 +2666,7 @@ */ static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UParseError& perror, UErrorCode& status); +#endif /** * Use factory methods instead of the constructor to create a NumberFormatter. @@ -2629,8 +2677,9 @@ } // namespace number U_NAMESPACE_END -#endif // U_HIDE_DRAFT_API +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ #endif // __NUMBERFORMATTER_H__ -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/unicode/numberrangeformatter.h icu-65.1/source/i18n/unicode/numberrangeformatter.h --- icu-64.2/source/i18n/unicode/numberrangeformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/numberrangeformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -1,10 +1,15 @@ // © 2018 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html -#if !UCONFIG_NO_FORMATTING #ifndef __NUMBERRANGEFORMATTER_H__ #define __NUMBERRANGEFORMATTER_H__ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#if !UCONFIG_NO_FORMATTING + #include #include "unicode/appendable.h" #include "unicode/fieldpos.h" @@ -12,8 +17,6 @@ #include "unicode/fpositer.h" #include "unicode/numberformatter.h" -#ifndef U_HIDE_DRAFT_API - /** * \file * \brief C++ API: Library for localized formatting of number, currency, and unit ranges. @@ -44,7 +47,7 @@ /** * Defines how to merge fields that are identical across the range sign. * - * @draft ICU 63 + * @stable ICU 63 */ typedef enum UNumberRangeCollapse { /** @@ -53,14 +56,14 @@ * * The heuristics used for this option are subject to change over time. * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_RANGE_COLLAPSE_AUTO, /** * Do not collapse any part of the number. Example: "3.2 thousand kilograms – 5.3 thousand kilograms" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_RANGE_COLLAPSE_NONE, @@ -68,7 +71,7 @@ * Collapse the unit part of the number, but not the notation, if present. Example: "3.2 thousand – 5.3 thousand * kilograms" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_RANGE_COLLAPSE_UNIT, @@ -76,7 +79,7 @@ * Collapse any field that is equal across the range sign. May introduce ambiguity on the magnitude of the * number. Example: "3.2 – 5.3 thousand kilograms" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_RANGE_COLLAPSE_ALL } UNumberRangeCollapse; @@ -85,14 +88,14 @@ * Defines the behavior when the two numbers in the range are identical after rounding. To programmatically detect * when the identity fallback is used, compare the lower and upper BigDecimals via FormattedNumber. * - * @draft ICU 63 + * @stable ICU 63 * @see NumberRangeFormatter */ typedef enum UNumberRangeIdentityFallback { /** * Show the number as a single value rather than a range. Example: "$5" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, @@ -100,7 +103,7 @@ * Show the number using a locale-sensitive approximation pattern. If the numbers were the same before rounding, * show the single value. Example: "~$5" or "$5" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, @@ -108,7 +111,7 @@ * Show the number using a locale-sensitive approximation pattern. Use the range pattern always, even if the * inputs are the same. Example: "~$5" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_IDENTITY_FALLBACK_APPROXIMATELY, @@ -116,7 +119,7 @@ * Show the number as the range of two equal values. Use the range pattern always, even if the inputs are the * same. Example (with RangeCollapse.NONE): "$5 – $5" * - * @draft ICU 63 + * @stable ICU 63 */ UNUM_IDENTITY_FALLBACK_RANGE } UNumberRangeIdentityFallback; @@ -125,14 +128,14 @@ * Used in the result class FormattedNumberRange to indicate to the user whether the numbers formatted in the range * were equal or not, and whether or not the identity fallback was applied. * - * @draft ICU 63 + * @stable ICU 63 * @see NumberRangeFormatter */ typedef enum UNumberRangeIdentityResult { /** * Used to indicate that the two numbers in the range were equal, even before any rounding rules were applied. * - * @draft ICU 63 + * @stable ICU 63 * @see NumberRangeFormatter */ UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING, @@ -140,7 +143,7 @@ /** * Used to indicate that the two numbers in the range were equal, but only after rounding rules were applied. * - * @draft ICU 63 + * @stable ICU 63 * @see NumberRangeFormatter */ UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING, @@ -148,7 +151,7 @@ /** * Used to indicate that the two numbers in the range were not equal, even after rounding rules were applied. * - * @draft ICU 63 + * @stable ICU 63 * @see NumberRangeFormatter */ UNUM_IDENTITY_RESULT_NOT_EQUAL, @@ -254,7 +257,7 @@ * @param formatter * The formatter to use for both numbers in the range. * @return The fluent chain. - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &; @@ -265,7 +268,7 @@ * The formatter to use for both numbers in the range. * @return The fluent chain. * @see #numberFormatterBoth - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&; @@ -276,7 +279,7 @@ * The formatter to use for both numbers in the range. * @return The fluent chain. * @see #numberFormatterBoth - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &; @@ -287,7 +290,7 @@ * The formatter to use for both numbers in the range. * @return The fluent chain. * @see #numberFormatterBoth - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&; @@ -300,7 +303,7 @@ * @param formatterFirst * The formatter to use for the first number in the range. * @return The fluent chain. - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &; @@ -311,7 +314,7 @@ * The formatter to use for the first number in the range. * @return The fluent chain. * @see #numberFormatterFirst - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&; @@ -322,7 +325,7 @@ * The formatter to use for the first number in the range. * @return The fluent chain. * @see #numberFormatterFirst - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &; @@ -333,7 +336,7 @@ * The formatter to use for the first number in the range. * @return The fluent chain. * @see #numberFormatterFirst - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&; @@ -346,7 +349,7 @@ * @param formatterSecond * The formatter to use for the second number in the range. * @return The fluent chain. - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &; @@ -357,7 +360,7 @@ * The formatter to use for the second number in the range. * @return The fluent chain. * @see #numberFormatterSecond - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&; @@ -368,7 +371,7 @@ * The formatter to use for the second number in the range. * @return The fluent chain. * @see #numberFormatterSecond - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &; @@ -379,7 +382,7 @@ * The formatter to use for the second number in the range. * @return The fluent chain. * @see #numberFormatterSecond - * @draft ICU 63 + * @stable ICU 63 */ Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&; @@ -398,7 +401,7 @@ * @param collapse * The collapsing strategy to use for this range. * @return The fluent chain. - * @draft ICU 63 + * @stable ICU 63 */ Derived collapse(UNumberRangeCollapse collapse) const &; @@ -409,7 +412,7 @@ * The collapsing strategy to use for this range. * @return The fluent chain. * @see #collapse - * @draft ICU 63 + * @stable ICU 63 */ Derived collapse(UNumberRangeCollapse collapse) &&; @@ -431,7 +434,7 @@ * @param identityFallback * The strategy to use when formatting two numbers that end up being the same. * @return The fluent chain. - * @draft ICU 63 + * @stable ICU 63 */ Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &; @@ -442,10 +445,11 @@ * The strategy to use when formatting two numbers that end up being the same. * @return The fluent chain. * @see #identityFallback - * @draft ICU 63 + * @stable ICU 63 */ Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&; +#ifndef U_HIDE_DRAFT_API /** * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer * wrapping a heap-allocated copy of the current object. @@ -467,12 +471,13 @@ * @draft ICU 64 */ LocalPointer clone() &&; +#endif /* U_HIDE_DRAFT_API */ /** * Sets the UErrorCode if an error occurred in the fluent chain. * Preserves older error codes in the outErrorCode. * @return TRUE if U_FAILURE(outErrorCode) - * @draft ICU 63 + * @stable ICU 63 */ UBool copyErrorTo(UErrorCode &outErrorCode) const { if (U_FAILURE(outErrorCode)) { @@ -501,7 +506,7 @@ * Instances of this class are immutable and thread-safe. * * @see NumberRangeFormatter - * @draft ICU 63 + * @stable ICU 63 */ class U_I18N_API UnlocalizedNumberRangeFormatter : public NumberRangeFormatterSettings, public UMemory { @@ -514,7 +519,7 @@ * @param locale * The locale to use when loading data for number formatting. * @return The fluent chain. - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &; @@ -525,40 +530,40 @@ * The locale to use when loading data for number formatting. * @return The fluent chain. * @see #locale - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&; /** * Default constructor: puts the formatter into a valid but undefined state. * - * @draft ICU 63 + * @stable ICU 63 */ UnlocalizedNumberRangeFormatter() = default; /** * Returns a copy of this UnlocalizedNumberRangeFormatter. - * @draft ICU 63 + * @stable ICU 63 */ UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other); /** * Move constructor: * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. - * @draft ICU 63 + * @stable ICU 63 */ UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; /** * Copy assignment operator. - * @draft ICU 63 + * @stable ICU 63 */ UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other); /** * Move assignment operator: * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. - * @draft ICU 63 + * @stable ICU 63 */ UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; @@ -582,7 +587,7 @@ * Instances of this class are immutable and thread-safe. * * @see NumberFormatter - * @draft ICU 63 + * @stable ICU 63 */ class U_I18N_API LocalizedNumberRangeFormatter : public NumberRangeFormatterSettings, public UMemory { @@ -598,7 +603,7 @@ * @param status * Set if an error occurs while formatting. * @return A FormattedNumberRange object; call .toString() to get the string. - * @draft ICU 63 + * @stable ICU 63 */ FormattedNumberRange formatFormattableRange( const Formattable& first, const Formattable& second, UErrorCode& status) const; @@ -606,33 +611,33 @@ /** * Default constructor: puts the formatter into a valid but undefined state. * - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter() = default; /** * Returns a copy of this LocalizedNumberRangeFormatter. - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other); /** * Move constructor: * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; /** * Copy assignment operator. - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other); /** * Move assignment operator: * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. - * @draft ICU 63 + * @stable ICU 63 */ LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; @@ -651,11 +656,11 @@ void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding, UErrorCode& status) const; -#endif +#endif /* U_HIDE_INTERNAL_API */ /** * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own. - * @draft ICU 63 + * @stable ICU 63 */ ~LocalizedNumberRangeFormatter(); @@ -690,7 +695,7 @@ * * Instances of this class are immutable and thread-safe. * - * @draft ICU 63 + * @stable ICU 63 */ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue { public: @@ -700,7 +705,7 @@ * * For more information, see FormattedValue::toString() * - * @draft ICU 63 + * @stable ICU 63 */ UnicodeString toString(UErrorCode& status) const U_OVERRIDE; @@ -714,7 +719,7 @@ * * For more information, see FormattedValue::appendTo() * - * @draft ICU 63 + * @stable ICU 63 */ Appendable &appendTo(Appendable &appendable, UErrorCode& status) const U_OVERRIDE; @@ -722,6 +727,7 @@ /** @copydoc FormattedValue::nextPosition() */ UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; +#ifndef U_HIDE_DRAFT_API /** * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given * field in the output string. This allows you to determine the locations of, for example, @@ -799,6 +805,7 @@ * @see #getFirstDecimal */ UnicodeString getSecondDecimal(UErrorCode& status) const; +#endif // U_HIDE_DRAFT_API /** * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was @@ -806,7 +813,7 @@ * identity fallback was used. * * @return An indication the resulting identity situation in the formatted number range. - * @draft ICU 63 + * @stable ICU 63 * @see UNumberRangeIdentityFallback */ UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const; @@ -824,20 +831,20 @@ /** * Move constructor: * Leaves the source FormattedNumberRange in an undefined state. - * @draft ICU 63 + * @stable ICU 63 */ FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT; /** * Move assignment: * Leaves the source FormattedNumberRange in an undefined state. - * @draft ICU 63 + * @stable ICU 63 */ FormattedNumberRange& operator=(FormattedNumberRange&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own. - * @draft ICU 63 + * @stable ICU 63 */ ~FormattedNumberRange(); @@ -850,7 +857,6 @@ /** * Internal constructor from data type. Adopts the data pointer. - * @internal */ explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results) : fData(results), fErrorCode(U_ZERO_ERROR) {} @@ -867,7 +873,7 @@ /** * See the main description in numberrangeformatter.h for documentation and examples. * - * @draft ICU 63 + * @stable ICU 63 */ class U_I18N_API NumberRangeFormatter final { public: @@ -876,7 +882,7 @@ * known at the call site. * * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining. - * @draft ICU 63 + * @stable ICU 63 */ static UnlocalizedNumberRangeFormatter with(); @@ -887,7 +893,7 @@ * @param locale * The locale from which to load formats and symbols for number range formatting. * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining. - * @draft ICU 63 + * @stable ICU 63 */ static LocalizedNumberRangeFormatter withLocale(const Locale &locale); @@ -900,8 +906,9 @@ } // namespace number U_NAMESPACE_END -#endif // U_HIDE_DRAFT_API +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ #endif // __NUMBERRANGEFORMATTER_H__ -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/i18n/unicode/numfmt.h icu-65.1/source/i18n/unicode/numfmt.h --- icu-64.2/source/i18n/unicode/numfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/numfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -26,6 +26,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Compatibility APIs for number formatting. @@ -261,6 +263,14 @@ virtual ~NumberFormat(); /** + * Clones this object polymorphically. + * The caller owns the result and should delete it when done. + * @return clone, or nullptr if an error occurred + * @stable ICU 2.0 + */ + virtual NumberFormat* clone() const = 0; + + /** * Return true if the given Format objects are semantically equal. * Objects of different subclasses are considered unequal. * @return true if the given Format objects are semantically equal. @@ -639,7 +649,9 @@ * @param result Formattable to be set to the parse result. * If parse fails, return contents are undefined. * @param status Output parameter set to a failure error code - * when a failure occurs. + * when a failure occurs. The error code when the + * string fails to parse is U_INVALID_FORMAT_ERROR, + * unless overridden by a subclass. * @see NumberFormat::isParseIntegerOnly * @stable ICU 2.0 */ @@ -1255,5 +1267,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _NUMFMT //eof diff -Nru icu-64.2/source/i18n/unicode/numsys.h icu-65.1/source/i18n/unicode/numsys.h --- icu-64.2/source/i18n/unicode/numsys.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/numsys.h 2019-10-03 11:16:41.000000000 +0000 @@ -20,6 +20,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: NumberingSystem object @@ -210,5 +212,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _NUMSYS //eof diff -Nru icu-64.2/source/i18n/unicode/plurfmt.h icu-65.1/source/i18n/unicode/plurfmt.h --- icu-64.2/source/i18n/unicode/plurfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/plurfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: PluralFormat object @@ -448,7 +450,7 @@ * result and should delete it when done. * @stable ICU 4.0 */ - virtual Format* clone(void) const; + virtual PluralFormat* clone() const; /** * Formats a plural message for a number taken from a Formattable object. @@ -522,7 +524,7 @@ private: /** - * @internal + * @internal (private) */ class U_I18N_API PluralSelector : public UMemory { public: @@ -534,14 +536,11 @@ * @param number The number to be plural-formatted. * @param ec Error code. * @return The selected PluralFormat keyword. - * @internal + * @internal (private) */ virtual UnicodeString select(void *context, double number, UErrorCode& ec) const = 0; }; - /** - * @internal - */ class U_I18N_API PluralSelectorAdapter : public PluralSelector { public: PluralSelectorAdapter() : pluralRules(NULL) { @@ -549,7 +548,7 @@ virtual ~PluralSelectorAdapter(); - virtual UnicodeString select(void *context, double number, UErrorCode& /*ec*/) const; /**< @internal */ + virtual UnicodeString select(void *context, double number, UErrorCode& /*ec*/) const; void reset(); @@ -573,7 +572,7 @@ UnicodeString& format(const Formattable& numberObject, double number, UnicodeString& appendTo, FieldPosition& pos, - UErrorCode& status) const; /**< @internal */ + UErrorCode& status) const; /** * Finds the PluralFormat sub-message for the given number, or the "other" sub-message. @@ -601,5 +600,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _PLURFMT //eof diff -Nru icu-64.2/source/i18n/unicode/plurrule.h icu-65.1/source/i18n/unicode/plurrule.h --- icu-64.2/source/i18n/unicode/plurrule.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/plurrule.h 2019-10-03 11:16:41.000000000 +0000 @@ -20,6 +20,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: PluralRules object @@ -533,5 +535,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _PLURRULE //eof diff -Nru icu-64.2/source/i18n/unicode/rbnf.h icu-65.1/source/i18n/unicode/rbnf.h --- icu-64.2/source/i18n/unicode/rbnf.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/rbnf.h 2019-10-03 11:16:41.000000000 +0000 @@ -12,6 +12,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Rule Based Number Format @@ -696,7 +698,7 @@ * @return A copy of the object. * @stable ICU 2.6 */ - virtual Format* clone(void) const; + virtual RuleBasedNumberFormat* clone() const; /** * Return true if the given Format objects are semantically equal. @@ -877,28 +879,6 @@ * @param number The number, a DigitList format Decimal Floating Point. * @param appendTo Output parameter to receive result. * Result is appended to existing contents. - * @param posIter On return, can be used to iterate over positions - * of fields generated by this format call. - * @param status Output param filled with success/failure status. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(const number::impl::DecimalQuantity &number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const; - - /** - * Format a decimal number. - * The number is a DigitList wrapper onto a floating point decimal number. - * The default implementation in NumberFormat converts the decimal number - * to a double and formats that. Subclasses of NumberFormat that want - * to specifically handle big decimal numbers must override this method. - * class DecimalFormat does so. - * - * @param number The number, a DigitList format Decimal Floating Point. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. * @param pos On input: an alignment field, if desired. * On output: the offsets of the alignment field. * @param status Output param filled with success/failure status. @@ -1135,5 +1115,7 @@ /* U_HAVE_RBNF */ #endif +#endif /* U_SHOW_CPLUSPLUS_API */ + /* RBNF_H */ #endif diff -Nru icu-64.2/source/i18n/unicode/rbtz.h icu-65.1/source/i18n/unicode/rbtz.h --- icu-64.2/source/i18n/unicode/rbtz.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/rbtz.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Rule based customizable time zone @@ -121,7 +123,7 @@ * @return A new copy of this TimeZone object. * @stable ICU 3.8 */ - virtual TimeZone* clone(void) const; + virtual RuleBasedTimeZone* clone() const; /** * Returns the TimeZone's adjusted GMT offset (i.e., the number of milliseconds to add @@ -224,6 +226,7 @@ */ virtual UBool useDaylightTime(void) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Queries if the given date is in daylight savings time in * this time zone. @@ -238,6 +241,7 @@ * @deprecated ICU 2.4. Use Calendar::inDaylightTime() instead. */ virtual UBool inDaylightTime(UDate date, UErrorCode& status) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Returns true if this zone has the same rule and offset as another zone. @@ -359,6 +363,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // RBTZ_H //eof diff -Nru icu-64.2/source/i18n/unicode/regex.h icu-65.1/source/i18n/unicode/regex.h --- icu-64.2/source/i18n/unicode/regex.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/regex.h 2019-10-03 11:16:41.000000000 +0000 @@ -44,6 +44,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_REGULAR_EXPRESSIONS #include "unicode/uobject.h" @@ -1876,4 +1878,7 @@ U_NAMESPACE_END #endif // UCONFIG_NO_REGULAR_EXPRESSIONS + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/region.h icu-65.1/source/i18n/unicode/region.h --- icu-64.2/source/i18n/unicode/region.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/region.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,10 +16,12 @@ */ #include "unicode/utypes.h" -#include "unicode/uregion.h" + +#if U_SHOW_CPLUSPLUS_API #if !UCONFIG_NO_FORMATTING +#include "unicode/uregion.h" #include "unicode/uobject.h" #include "unicode/uniset.h" #include "unicode/unistr.h" @@ -219,6 +221,9 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // REGION_H //eof diff -Nru icu-64.2/source/i18n/unicode/reldatefmt.h icu-65.1/source/i18n/unicode/reldatefmt.h --- icu-64.2/source/i18n/unicode/reldatefmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/reldatefmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,9 @@ #define __RELDATEFMT_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/udisplaycontext.h" #include "unicode/ureldatefmt.h" @@ -166,12 +169,24 @@ */ UDAT_ABSOLUTE_NOW, -#ifndef U_HIDE_DRAFT_API /** * Quarter - * @draft ICU 63 + * @stable ICU 63 */ UDAT_ABSOLUTE_QUARTER, + +#ifndef U_HIDE_DRAFT_API + /** + * Hour + * @draft ICU 65 + */ + UDAT_ABSOLUTE_HOUR, + + /** + * Minute + * @draft ICU 65 + */ + UDAT_ABSOLUTE_MINUTE, #endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DEPRECATED_API @@ -179,7 +194,7 @@ * One more than the highest normal UDateAbsoluteUnit value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UDAT_ABSOLUTE_UNIT_COUNT = UDAT_ABSOLUTE_NOW + 2 + UDAT_ABSOLUTE_UNIT_COUNT = UDAT_ABSOLUTE_NOW + 4 #endif // U_HIDE_DEPRECATED_API } UDateAbsoluteUnit; @@ -246,6 +261,7 @@ class SharedBreakIterator; class NumberFormat; class UnicodeString; +class FormattedRelativeDateTime; class FormattedRelativeDateTimeData; #ifndef U_HIDE_DRAFT_API @@ -743,4 +759,7 @@ #endif /* !UCONFIG_NO_BREAK_ITERATION */ #endif /* !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif /* __RELDATEFMT_H */ diff -Nru icu-64.2/source/i18n/unicode/scientificnumberformatter.h icu-65.1/source/i18n/unicode/scientificnumberformatter.h --- icu-64.2/source/i18n/unicode/scientificnumberformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/scientificnumberformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING @@ -157,7 +159,7 @@ class U_I18N_API SuperscriptStyle : public Style { public: - virtual Style *clone() const; + virtual SuperscriptStyle *clone() const; protected: virtual UnicodeString &format( const UnicodeString &original, @@ -175,7 +177,7 @@ : Style(), fBeginMarkup(beginMarkup), fEndMarkup(endMarkup) { } - virtual Style *clone() const; + virtual MarkupStyle *clone() const; protected: virtual UnicodeString &format( const UnicodeString &original, @@ -214,4 +216,7 @@ #endif /* !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/search.h icu-65.1/source/i18n/unicode/search.h --- icu-64.2/source/i18n/unicode/search.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/search.h 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: SearchIterator object. @@ -70,8 +72,7 @@ * UErrorCode error = U_ZERO_ERROR; * for (int pos = iter->first(error); pos != USEARCH_DONE; * pos = iter->next(error)) { - * printf("Found match at %d pos, length is %d\n", pos, - * iter.getMatchLength()); + * printf("Found match at %d pos, length is %d\n", pos, iter.getMatchedLength()); * } * * @@ -573,5 +574,7 @@ #endif /* #if !UCONFIG_NO_COLLATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/selfmt.h icu-65.1/source/i18n/unicode/selfmt.h --- icu-64.2/source/i18n/unicode/selfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/selfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,9 +18,12 @@ #ifndef SELFMT #define SELFMT +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/messagepattern.h" #include "unicode/numfmt.h" -#include "unicode/utypes.h" /** * \file @@ -272,7 +275,7 @@ * result and should delete it when done. * @stable ICU 4.4 */ - virtual Format* clone(void) const; + virtual SelectFormat* clone() const; /** * Format an object to produce a string. @@ -365,5 +368,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _SELFMT //eof diff -Nru icu-64.2/source/i18n/unicode/simpletz.h icu-65.1/source/i18n/unicode/simpletz.h --- icu-64.2/source/i18n/unicode/simpletz.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/simpletz.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: SimpleTimeZone is a concrete subclass of TimeZone. @@ -672,6 +674,7 @@ */ virtual UBool useDaylightTime(void) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Returns true if the given date is within the period when daylight savings time * is in effect; false otherwise. If the TimeZone doesn't observe daylight savings @@ -687,6 +690,7 @@ * @deprecated ICU 2.4. Use Calendar::inDaylightTime() instead. */ virtual UBool inDaylightTime(UDate date, UErrorCode& status) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Return true if this zone has the same rules and offset as another zone. @@ -703,7 +707,7 @@ * @return A new copy of this TimeZone object. * @stable ICU 2.0 */ - virtual TimeZone* clone(void) const; + virtual SimpleTimeZone* clone() const; /** * Gets the first time zone transition after the base time. @@ -929,4 +933,6 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _SIMPLETZ diff -Nru icu-64.2/source/i18n/unicode/smpdtfmt.h icu-65.1/source/i18n/unicode/smpdtfmt.h --- icu-64.2/source/i18n/unicode/smpdtfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/smpdtfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Format and parse dates in a language-independent manner. @@ -865,7 +867,7 @@ * @return A copy of the object. * @stable ICU 2.0 */ - virtual Format* clone(void) const; + virtual SimpleDateFormat* clone() const; /** * Return true if the given Format objects are semantically equal. Objects @@ -1643,7 +1645,7 @@ UBool fHaveDefaultCentury; - BreakIterator* fCapitalizationBrkIter; + const BreakIterator* fCapitalizationBrkIter; }; inline UDate @@ -1656,5 +1658,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // _SMPDTFMT //eof diff -Nru icu-64.2/source/i18n/unicode/sortkey.h icu-65.1/source/i18n/unicode/sortkey.h --- icu-64.2/source/i18n/unicode/sortkey.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/sortkey.h 2019-10-03 11:16:41.000000000 +0000 @@ -25,6 +25,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Keys for comparing strings multiple times. @@ -337,4 +339,6 @@ #endif /* #if !UCONFIG_NO_COLLATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/stsearch.h icu-65.1/source/i18n/unicode/stsearch.h --- icu-64.2/source/i18n/unicode/stsearch.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/stsearch.h 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Service for searching text based on RuleBasedCollator. @@ -119,8 +121,7 @@ * pos != USEARCH_DONE; * pos = iter.next(error)) * { - * printf("Found match at %d pos, length is %d\n", pos, - * iter.getMatchLength()); + * printf("Found match at %d pos, length is %d\n", pos, iter.getMatchedLength()); * } * *

    @@ -412,7 +413,7 @@ * @return cloned object * @stable ICU 2.0 */ - virtual SearchIterator * safeClone(void) const; + virtual StringSearch * safeClone() const; /** * ICU "poor man's RTTI", returns a UClassID for the actual class. @@ -502,5 +503,7 @@ #endif /* #if !UCONFIG_NO_COLLATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/tblcoll.h icu-65.1/source/i18n/unicode/tblcoll.h --- icu-64.2/source/i18n/unicode/tblcoll.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tblcoll.h 2019-10-03 11:16:41.000000000 +0000 @@ -64,6 +64,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_COLLATION #include "unicode/coll.h" @@ -228,7 +230,7 @@ * @return a copy of this object, owned by the caller * @stable ICU 2.0 */ - virtual Collator* clone(void) const; + virtual RuleBasedCollator* clone() const; /** * Creates a collation element iterator for the source string. The caller of @@ -389,6 +391,7 @@ */ virtual int32_t hashCode() const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Gets the locale of the Collator * @param type can be either requested, valid or actual locale. For more @@ -400,6 +403,7 @@ * @deprecated ICU 2.8 likely to change in ICU 3.0, based on feedback */ virtual Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the tailoring rules for this collator. @@ -545,6 +549,7 @@ */ virtual UColReorderCode getMaxVariable() const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Sets the variable top to the primary weight of the specified string. * @@ -592,6 +597,7 @@ * @deprecated ICU 53 Call setMaxVariable() instead. */ virtual void setVariableTop(uint32_t varTop, UErrorCode &status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Gets the variable top value of a Collator. @@ -874,4 +880,7 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_COLLATION + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // TBLCOLL_H diff -Nru icu-64.2/source/i18n/unicode/timezone.h icu-65.1/source/i18n/unicode/timezone.h --- icu-64.2/source/i18n/unicode/timezone.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/timezone.h 2019-10-03 11:16:41.000000000 +0000 @@ -31,6 +31,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: TimeZone object @@ -321,10 +323,6 @@ * zone is set to the default host time zone. This call adopts the TimeZone object * passed in; the client is no longer responsible for deleting it. * - *

    This function is not thread safe. It is an error for multiple threads - * to concurrently attempt to set the default time zone, or for any thread - * to attempt to reference the default zone while another thread is setting it. - * * @param zone A pointer to the new TimeZone object to use as the default. * @stable ICU 2.0 */ @@ -335,8 +333,6 @@ * Same as adoptDefault(), except that the TimeZone object passed in is NOT adopted; * the caller remains responsible for deleting it. * - *

    See the thread safety note under adoptDefault(). - * * @param zone The given timezone. * @system * @stable ICU 2.0 @@ -726,6 +722,7 @@ */ virtual UBool useDaylightTime(void) const = 0; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Queries if the given date is in daylight savings time in * this time zone. @@ -740,6 +737,7 @@ * @deprecated ICU 2.4. Use Calendar::inDaylightTime() instead. */ virtual UBool inDaylightTime(UDate date, UErrorCode& status) const = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Returns true if this zone has the same rule and offset as another zone. @@ -758,7 +756,7 @@ * @return A new copy of this TimeZone object. * @stable ICU 2.0 */ - virtual TimeZone* clone(void) const = 0; + virtual TimeZone* clone() const = 0; /** * Return the class ID for this class. This is useful only for @@ -972,5 +970,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif //_TIMEZONE //eof diff -Nru icu-64.2/source/i18n/unicode/tmunit.h icu-65.1/source/i18n/unicode/tmunit.h --- icu-64.2/source/i18n/unicode/tmunit.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tmunit.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,9 @@ * \brief C++ API: time unit object */ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API #include "unicode/measunit.h" @@ -70,7 +73,7 @@ * Override clone. * @stable ICU 4.2 */ - virtual UObject* clone() const; + virtual TimeUnit* clone() const; /** * Copy operator. @@ -132,6 +135,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __TMUNIT_H__ //eof // diff -Nru icu-64.2/source/i18n/unicode/tmutamt.h icu-65.1/source/i18n/unicode/tmutamt.h --- icu-64.2/source/i18n/unicode/tmutamt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tmutamt.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,11 +16,15 @@ * \brief C++ API: time unit amount object. */ -#include "unicode/measure.h" -#include "unicode/tmunit.h" +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API #if !UCONFIG_NO_FORMATTING +#include "unicode/measure.h" +#include "unicode/tmunit.h" + U_NAMESPACE_BEGIN @@ -83,7 +87,7 @@ * @return a polymorphic clone of this object. The result will have the same class as returned by getDynamicClassID(). * @stable ICU 4.2 */ - virtual UObject* clone() const; + virtual TimeUnitAmount* clone() const; /** @@ -165,6 +169,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __TMUTAMT_H__ //eof // diff -Nru icu-64.2/source/i18n/unicode/tmutfmt.h icu-65.1/source/i18n/unicode/tmutfmt.h --- icu-64.2/source/i18n/unicode/tmutfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tmutfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,8 +18,9 @@ */ +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DEPRECATED_API #include "unicode/unistr.h" #include "unicode/tmunit.h" @@ -28,6 +29,7 @@ #include "unicode/numfmt.h" #include "unicode/plurrule.h" +#ifndef U_HIDE_DEPRECATED_API /** * Constants for various styles. @@ -124,7 +126,7 @@ * @return A copy of the object. * @deprecated ICU 53 */ - virtual Format* clone(void) const; + virtual TimeUnitFormat* clone() const; /** * Assignment operator @@ -244,5 +246,7 @@ #endif /* U_HIDE_DEPRECATED_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __TMUTFMT_H__ //eof diff -Nru icu-64.2/source/i18n/unicode/translit.h icu-65.1/source/i18n/unicode/translit.h --- icu-64.2/source/i18n/unicode/translit.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/translit.h 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Tranforms text from one format to another. @@ -1588,4 +1590,6 @@ #endif /* #if !UCONFIG_NO_TRANSLITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/tzfmt.h icu-65.1/source/i18n/unicode/tzfmt.h --- icu-64.2/source/i18n/unicode/tzfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tzfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/format.h" @@ -305,7 +307,7 @@ * @return A copy of the object * @stable ICU 50 */ - virtual Format* clone() const; + virtual TimeZoneFormat* clone() const; /** * Creates an instance of TimeZoneFormat for the given locale. @@ -1094,4 +1096,7 @@ U_NAMESPACE_END #endif /* !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/tznames.h icu-65.1/source/i18n/unicode/tznames.h --- icu-64.2/source/i18n/unicode/tznames.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tznames.h 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ */ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/uloc.h" @@ -411,4 +413,7 @@ U_NAMESPACE_END #endif + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/tzrule.h icu-65.1/source/i18n/unicode/tzrule.h --- icu-64.2/source/i18n/unicode/tzrule.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tzrule.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/uobject.h" @@ -45,7 +47,7 @@ * @return A copy of the object. * @stable ICU 3.8 */ - virtual TimeZoneRule* clone(void) const = 0; + virtual TimeZoneRule* clone() const = 0; /** * Return true if the given TimeZoneRule objects are semantically equal. Objects @@ -229,7 +231,7 @@ * @return A copy of the object. * @stable ICU 3.8 */ - virtual InitialTimeZoneRule* clone(void) const; + virtual InitialTimeZoneRule* clone() const; /** * Assignment operator. @@ -440,7 +442,7 @@ * @return A copy of the object. * @stable ICU 3.8 */ - virtual AnnualTimeZoneRule* clone(void) const; + virtual AnnualTimeZoneRule* clone() const; /** * Assignment operator. @@ -656,7 +658,7 @@ * @return A copy of the object. * @stable ICU 3.8 */ - virtual TimeArrayTimeZoneRule* clone(void) const; + virtual TimeArrayTimeZoneRule* clone() const; /** * Assignment operator. @@ -825,6 +827,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // TZRULE_H //eof diff -Nru icu-64.2/source/i18n/unicode/tztrans.h icu-65.1/source/i18n/unicode/tztrans.h --- icu-64.2/source/i18n/unicode/tztrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/tztrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/uobject.h" @@ -68,7 +70,7 @@ * @return A copy of the object. * @stable ICU 3.8 */ - TimeZoneTransition* clone(void) const; + TimeZoneTransition* clone() const; /** * Assignment operator. @@ -192,6 +194,8 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // TZTRANS_H //eof diff -Nru icu-64.2/source/i18n/unicode/ucal.h icu-65.1/source/i18n/unicode/ucal.h --- icu-64.2/source/i18n/unicode/ucal.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/ucal.h 2019-10-03 11:16:41.000000000 +0000 @@ -441,11 +441,13 @@ /* Do not conditionalize the following with #ifndef U_HIDE_DEPRECATED_API, * it is needed for layout of Calendar, DateFormat, and other objects */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * One more than the highest normal UCalendarDateFields value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UCAL_FIELD_COUNT, + UCAL_FIELD_COUNT, +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Field number indicating the @@ -657,6 +659,42 @@ U_STABLE void U_EXPORT2 ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec); +#ifndef U_HIDE_DRAFT_API + +/** + * Return the current host time zone. The host time zone is detected from + * the current host system configuration by querying the host operating + * system. If the host system detection routines fail, or if they specify + * a TimeZone or TimeZone offset which is not recognized, then the special + * TimeZone "Etc/Unknown" is returned. + * + * Note that host time zone and the ICU default time zone can be different. + * + * The ICU default time zone does not change once initialized unless modified + * by calling `ucal_setDefaultTimeZone()` or with the C++ TimeZone API, + * `TimeZone::adoptDefault(TimeZone*)`. + * + * If the host operating system configuration has changed since ICU has + * initialized then the returned value can be different than the ICU default + * time zone, even if the default has not changed. + * + *

    This function is not thread safe.

    + * + * @param result A buffer to receive the result, or NULL + * @param resultCapacity The capacity of the result buffer + * @param ec input/output error code + * @return The result string length, not including the terminating + * null + * + * @see #UCAL_UNKNOWN_ZONE_ID + * + * @draft ICU 65 + */ +U_DRAFT int32_t U_EXPORT2 +ucal_getHostTimeZone(UChar *result, int32_t resultCapacity, UErrorCode *ec); + +#endif // U_HIDE_DRAFT_API + /** * Return the amount of time in milliseconds that the clock is * advanced during daylight savings time for the given time zone, or diff -Nru icu-64.2/source/i18n/unicode/ucol.h icu-65.1/source/i18n/unicode/ucol.h --- icu-64.2/source/i18n/unicode/ucol.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/ucol.h 2019-10-03 11:16:41.000000000 +0000 @@ -344,11 +344,13 @@ /* Do not conditionalize the following with #ifndef U_HIDE_DEPRECATED_API, * it is needed for layout of RuleBasedCollator object. */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * One more than the highest normal UColAttribute value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ UCOL_ATTRIBUTE_COUNT +#endif // U_FORCE_HIDE_DEPRECATED_API } UColAttribute; /** Options for retrieving the rule string diff -Nru icu-64.2/source/i18n/unicode/udat.h icu-65.1/source/i18n/unicode/udat.h --- icu-64.2/source/i18n/unicode/udat.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/udat.h 2019-10-03 11:16:41.000000000 +0000 @@ -923,11 +923,13 @@ /* Do not conditionalize the following with #ifndef U_HIDE_DEPRECATED_API, * it is needed for layout of DateFormat object. */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * One more than the highest normal UDateFormatBooleanAttribute value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ UDAT_BOOLEAN_ATTRIBUTE_COUNT = 4 +#endif // U_FORCE_HIDE_DEPRECATED_API } UDateFormatBooleanAttribute; /** diff -Nru icu-64.2/source/i18n/unicode/udatpg.h icu-65.1/source/i18n/unicode/udatpg.h --- icu-64.2/source/i18n/unicode/udatpg.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/udatpg.h 2019-10-03 11:16:41.000000000 +0000 @@ -88,11 +88,13 @@ /* Do not conditionalize the following with #ifndef U_HIDE_DEPRECATED_API, * it is needed for layout of DateTimePatternGenerator object. */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * One more than the highest normal UDateTimePatternField value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ UDATPG_FIELD_COUNT +#endif // U_FORCE_HIDE_DEPRECATED_API } UDateTimePatternField; /** diff -Nru icu-64.2/source/i18n/unicode/uformattedvalue.h icu-65.1/source/i18n/unicode/uformattedvalue.h --- icu-64.2/source/i18n/unicode/uformattedvalue.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/uformattedvalue.h 2019-10-03 11:16:41.000000000 +0000 @@ -7,10 +7,11 @@ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING -#ifndef U_HIDE_DRAFT_API #include "unicode/ufieldpositer.h" +#ifndef U_HIDE_DRAFT_API + /** * \file * \brief C API: Abstract operations for localized strings. diff -Nru icu-64.2/source/i18n/unicode/ulistformatter.h icu-65.1/source/i18n/unicode/ulistformatter.h --- icu-64.2/source/i18n/unicode/ulistformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/ulistformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -41,7 +41,7 @@ * @draft ICU 64 */ typedef struct UFormattedList UFormattedList; -#endif /* U_HIDE_DRAFT_API */ +#endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API /** @@ -61,7 +61,7 @@ */ ULISTFMT_ELEMENT_FIELD } UListFormatterField; -#endif // U_HIDE_DRAFT_API +#endif /* U_HIDE_DRAFT_API */ /** * Open a new UListFormatter object using the rules for a given locale. diff -Nru icu-64.2/source/i18n/unicode/unirepl.h icu-65.1/source/i18n/unicode/unirepl.h --- icu-64.2/source/i18n/unicode/unirepl.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/unirepl.h 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: UnicodeReplacer @@ -96,4 +98,6 @@ U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/i18n/unicode/unumberformatter.h icu-65.1/source/i18n/unicode/unumberformatter.h --- icu-64.2/source/i18n/unicode/unumberformatter.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/unumberformatter.h 2019-10-03 11:16:41.000000000 +0000 @@ -77,8 +77,6 @@ * */ - -#ifndef U_HIDE_DRAFT_API /** * An enum declaring how to render units, including currencies. Example outputs when formatting 123 USD and 123 * meters in en-CA: @@ -95,7 +93,7 @@ *

    * This enum is similar to {@link UMeasureFormatWidth}. * - * @draft ICU 60 + * @stable ICU 60 */ typedef enum UNumberUnitWidth { /** @@ -107,7 +105,7 @@ * In CLDR, this option corresponds to the "Narrow" format for measure units and the "¤¤¤¤¤" placeholder for * currencies. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_UNIT_WIDTH_NARROW, @@ -123,7 +121,7 @@ * In CLDR, this option corresponds to the "Short" format for measure units and the "¤" placeholder for * currencies. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_UNIT_WIDTH_SHORT, @@ -134,7 +132,7 @@ * In CLDR, this option corresponds to the default format for measure units and the "¤¤¤" placeholder for * currencies. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_UNIT_WIDTH_FULL_NAME, @@ -145,7 +143,7 @@ *

    * In CLDR, this option corresponds to the "¤¤" placeholder for currencies. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_UNIT_WIDTH_ISO_CODE, @@ -154,7 +152,7 @@ * monetary symbols and formats as with SHORT, but omit the currency symbol. For measure units, the behavior is * equivalent to not specifying the unit at all. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_UNIT_WIDTH_HIDDEN, @@ -165,9 +163,7 @@ */ UNUM_UNIT_WIDTH_COUNT } UNumberUnitWidth; -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * An enum declaring the strategy for when and how to display grouping separators (i.e., the * separator, often a comma or period, after every 2-3 powers of ten). The choices are several @@ -192,13 +188,13 @@ * Note: This enum specifies the strategy for grouping sizes. To set which character to use as the * grouping separator, use the "symbols" setter. * - * @draft ICU 63 + * @stable ICU 63 */ typedef enum UNumberGroupingStrategy { /** * Do not display grouping separators in any locale. * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_GROUPING_OFF, @@ -214,7 +210,7 @@ * Locale data is used to determine whether to separate larger numbers into groups of 2 * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_GROUPING_MIN2, @@ -229,7 +225,7 @@ * Locale data is used to determine whether to separate larger numbers into groups of 2 * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_GROUPING_AUTO, @@ -245,7 +241,7 @@ * Locale data is used to determine whether to separate larger numbers into groups of 2 * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_GROUPING_ON_ALIGNED, @@ -253,7 +249,7 @@ * Use the Western defaults: groups of 3 and enabled for all numbers 1000 or greater. Do not use * locale data for determining the grouping strategy. * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_GROUPING_THOUSANDS @@ -269,10 +265,6 @@ } UNumberGroupingStrategy; - -#endif /* U_HIDE_DRAFT_API */ - -#ifndef U_HIDE_DRAFT_API /** * An enum declaring how to denote positive and negative numbers. Example outputs when formatting * 123, 0, and -123 in en-US: @@ -290,14 +282,14 @@ *

    * The exact format, including the position and the code point of the sign, differ by locale. * - * @draft ICU 60 + * @stable ICU 60 */ typedef enum UNumberSignDisplay { /** * Show the minus sign on negative numbers, and do not show the sign on positive numbers. This is the default * behavior. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_SIGN_AUTO, @@ -305,14 +297,14 @@ * Show the minus sign on negative numbers and the plus sign on positive numbers, including zero. * To hide the sign on zero, see {@link UNUM_SIGN_EXCEPT_ZERO}. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_SIGN_ALWAYS, /** * Do not show the sign on positive or negative numbers. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_SIGN_NEVER, @@ -328,7 +320,7 @@ * AUTO sign display strategy when formatting without a currency unit. This limitation may be lifted in the * future. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_SIGN_ACCOUNTING, @@ -338,24 +330,25 @@ * ACCOUNTING sign display strategy. To hide the sign on zero, see * {@link UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO}. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_SIGN_ACCOUNTING_ALWAYS, /** * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a - * sign on zero. + * sign on zero or NaN, unless the sign bit is set (-0.0 gets a sign). * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_SIGN_EXCEPT_ZERO, /** * Use the locale-dependent accounting format on negative numbers, and show the plus sign on - * positive numbers. Do not show a sign on zero. For more information on the accounting format, - * see the ACCOUNTING sign display strategy. + * positive numbers. Do not show a sign on zero or NaN, unless the sign bit is set (-0.0 gets a + * sign). For more information on the accounting format, see the ACCOUNTING sign display + * strategy. * - * @draft ICU 61 + * @stable ICU 61 */ UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO, @@ -366,9 +359,7 @@ */ UNUM_SIGN_COUNT } UNumberSignDisplay; -#endif /* U_HIDE_DRAFT_API */ -#ifndef U_HIDE_DRAFT_API /** * An enum declaring how to render the decimal separator. * @@ -378,21 +369,21 @@ *

  • UNUM_DECIMAL_SEPARATOR_ALWAYS: "1.", "1.1" * * - * @draft ICU 60 + * @stable ICU 60 */ typedef enum UNumberDecimalSeparatorDisplay { /** * Show the decimal separator when there are one or more digits to display after the separator, and do not show * it otherwise. This is the default behavior. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_DECIMAL_SEPARATOR_AUTO, /** * Always show the decimal separator, even if there are no digits to display after the separator. * - * @draft ICU 60 + * @stable ICU 60 */ UNUM_DECIMAL_SEPARATOR_ALWAYS, @@ -403,7 +394,6 @@ */ UNUM_DECIMAL_SEPARATOR_COUNT } UNumberDecimalSeparatorDisplay; -#endif /* U_HIDE_DRAFT_API */ struct UNumberFormatter; /** @@ -649,6 +639,13 @@ UErrorCode* ec); +// TODO(ICU-20775): Propose this as API. +// NOTE: This is not currently implemented. +// U_DRAFT int32_t U_EXPORT2 +// unumf_resultToDecimalNumber(const UFormattedNumber* uresult, char* buffer, int32_t bufferCapacity, +// UErrorCode* ec); + + /** * Releases the UNumberFormatter created by unumf_openForSkeletonAndLocale(). * diff -Nru icu-64.2/source/i18n/unicode/unum.h icu-65.1/source/i18n/unicode/unum.h --- icu-64.2/source/i18n/unicode/unum.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/unum.h 2019-10-03 11:16:41.000000000 +0000 @@ -338,11 +338,13 @@ /* Do not conditionalize the following with #ifndef U_HIDE_DEPRECATED_API, * it is needed for layout of DecimalFormatSymbols object. */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * One more than the highest normal UCurrencySpacing value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ UNUM_CURRENCY_SPACING_COUNT +#endif // U_FORCE_HIDE_DEPRECATED_API }; typedef enum UCurrencySpacing UCurrencySpacing; /**< @stable ICU 4.8 */ @@ -409,7 +411,7 @@ * respectively. * *

    NOTE:: New users with are strongly encouraged to - * use unumf_openWithSkeletonAndLocale instead of unum_open. + * use unumf_openForSkeletonAndLocale instead of unum_open. * * @param pattern A pattern specifying the format to use. * This parameter is ignored unless the style is diff -Nru icu-64.2/source/i18n/unicode/usearch.h icu-65.1/source/i18n/unicode/usearch.h --- icu-64.2/source/i18n/unicode/usearch.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/usearch.h 2019-10-03 11:16:41.000000000 +0000 @@ -24,7 +24,7 @@ * \file * \brief C API: StringSearch * - * C Apis for an engine that provides language-sensitive text searching based + * C APIs for an engine that provides language-sensitive text searching based * on the comparison rules defined in a UCollator data struct, * see ucol.h. This ensures that language eccentricity can be * handled, e.g. for the German collator, characters ß and SS will be matched @@ -55,7 +55,7 @@ *

    * This search has APIs similar to that of other text iteration mechanisms * such as the break iterators in ubrk.h. Using these - * APIs, it is easy to scan through text looking for all occurances of + * APIs, it is easy to scan through text looking for all occurrences of * a given pattern. This search iterator allows changing of direction by * calling a reset followed by a next or previous. * Though a direction change can occur without calling reset first, @@ -130,7 +130,7 @@ * pos = usearch_next(search, &status)) * { * printf("Found match at %d pos, length is %d\n", pos, - * usearch_getMatchLength(search)); + * usearch_getMatchedLength(search)); * } * } * @@ -479,7 +479,7 @@ * possible. If the buffer fits the matched text exactly, a null-termination * is not possible, then a U_STRING_NOT_TERMINATED_ERROR set in status. * Pre-flighting can be either done with length = 0 or the API -* usearch_getMatchLength. +* usearch_getMatchedLength. * @param strsrch search iterator data struct * @param result UChar buffer to store the matched string * @param resultCapacity length of the result buffer @@ -766,7 +766,7 @@ #ifndef U_HIDE_INTERNAL_API /** * Simple forward search for the pattern, starting at a specified index, - * and using using a default set search options. + * and using a default set search options. * * This is an experimental function, and is not an official part of the * ICU API. @@ -783,7 +783,7 @@ * are part of a combining sequence, as described below. * * A match will not include a partial combining sequence. Combining - * character sequences are considered to be inseperable units, + * character sequences are considered to be inseparable units, * and either match the pattern completely, or are considered to not match * at all. Thus, for example, an A followed a combining accent mark will * not be found when searching for a plain (unaccented) A. (unless @@ -792,7 +792,7 @@ * When beginning a search, the initial starting position, startIdx, * is assumed to be an acceptable match boundary with respect to * combining characters. A combining sequence that spans across the - * starting point will not supress a match beginning at startIdx. + * starting point will not suppress a match beginning at startIdx. * * Characters that expand to multiple collation elements * (German sharp-S becoming 'ss', or the composed forms of accented @@ -843,7 +843,7 @@ * are part of a combining sequence, as described below. * * A match will not include a partial combining sequence. Combining - * character sequences are considered to be inseperable units, + * character sequences are considered to be inseparable units, * and either match the pattern completely, or are considered to not match * at all. Thus, for example, an A followed a combining accent mark will * not be found when searching for a plain (unaccented) A. (unless @@ -852,7 +852,7 @@ * When beginning a search, the initial starting position, startIdx, * is assumed to be an acceptable match boundary with respect to * combining characters. A combining sequence that spans across the - * starting point will not supress a match beginning at startIdx. + * starting point will not suppress a match beginning at startIdx. * * Characters that expand to multiple collation elements * (German sharp-S becoming 'ss', or the composed forms of accented diff -Nru icu-64.2/source/i18n/unicode/uspoof.h icu-65.1/source/i18n/unicode/uspoof.h --- icu-64.2/source/i18n/unicode/uspoof.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/uspoof.h 2019-10-03 11:16:41.000000000 +0000 @@ -353,6 +353,8 @@ * @stable ICU 4.6 */ +U_CDECL_BEGIN + struct USpoofChecker; /** * @stable ICU 4.2 @@ -471,7 +473,6 @@ */ USPOOF_MIXED_NUMBERS = 128, -#ifndef U_HIDE_DRAFT_API /** * Check that an identifier does not have a combining character following a character in which that * combining character would be hidden; for example 'i' followed by a U+0307 combining dot. @@ -489,10 +490,9 @@ * * This list and the number of combing characters considered by this check may grow over time. * - * @draft ICU 62 + * @stable ICU 62 */ USPOOF_HIDDEN_OVERLAY = 256, -#endif /* U_HIDE_DRAFT_API */ /** * Enable all spoof checks. @@ -674,25 +674,6 @@ U_STABLE void U_EXPORT2 uspoof_close(USpoofChecker *sc); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUSpoofCheckerPointer - * "Smart pointer" class, closes a USpoofChecker via uspoof_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckerPointer, USpoofChecker, uspoof_close); - -U_NAMESPACE_END - -#endif - /** * Clone a Spoof Checker. The clone will be set to perform the same checks * as the original source. @@ -901,54 +882,6 @@ uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status); -#if U_SHOW_CPLUSPLUS_API -/** - * Limit the acceptable characters to those specified by a Unicode Set. - * Any previously specified character limit is - * is replaced by the new settings. This includes limits on - * characters that were set with the uspoof_setAllowedLocales() function. - * - * The USPOOF_CHAR_LIMIT test is automatically enabled for this - * USoofChecker by this function. - * - * @param sc The USpoofChecker - * @param chars A Unicode Set containing the list of - * characters that are permitted. Ownership of the set - * remains with the caller. The incoming set is cloned by - * this function, so there are no restrictions on modifying - * or deleting the UnicodeSet after calling this function. - * @param status The error code, set if this function encounters a problem. - * @stable ICU 4.2 - */ -U_STABLE void U_EXPORT2 -uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const icu::UnicodeSet *chars, UErrorCode *status); - - -/** - * Get a UnicodeSet for the characters permitted in an identifier. - * This corresponds to the limits imposed by the Set Allowed Characters / - * UnicodeSet functions. Limitations imposed by other checks will not be - * reflected in the set returned by this function. - * - * The returned set will be frozen, meaning that it cannot be modified - * by the caller. - * - * Ownership of the returned set remains with the Spoof Detector. The - * returned set will become invalid if the spoof detector is closed, - * or if a new set of allowed characters is specified. - * - * - * @param sc The USpoofChecker - * @param status The error code, set if this function encounters a problem. - * @return A UnicodeSet containing the characters that are permitted by - * the USPOOF_CHAR_LIMIT test. - * @stable ICU 4.2 - */ -U_STABLE const icu::UnicodeSet * U_EXPORT2 -uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status); -#endif - - /** * Check the specified string for possible security issues. * The text to be checked will typically be an identifier of some sort. @@ -1027,43 +960,6 @@ UErrorCode *status); -#if U_SHOW_CPLUSPLUS_API -/** - * Check the specified string for possible security issues. - * The text to be checked will typically be an identifier of some sort. - * The set of checks to be performed is specified with uspoof_setChecks(). - * - * \note - * Consider using the newer API, {@link uspoof_check2UnicodeString}, instead. - * The newer API exposes additional information from the check procedure - * and is otherwise identical to this method. - * - * @param sc The USpoofChecker - * @param id A identifier to be checked for possible security issues. - * @param position Deprecated in ICU 51. Always returns zero. - * Originally, an out parameter for the index of the first - * string position that failed a check. - * This parameter may be NULL. - * @param status The error code, set if an error occurred while attempting to - * perform the check. - * Spoofing or security issues detected with the input string are - * not reported here, but through the function's return value. - * @return An integer value with bits set for any potential security - * or spoofing issues detected. The bits are defined by - * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) - * will be zero if the input string passes all of the - * enabled checks. - * @see uspoof_check2UnicodeString - * @stable ICU 4.2 - */ -U_STABLE int32_t U_EXPORT2 -uspoof_checkUnicodeString(const USpoofChecker *sc, - const icu::UnicodeString &id, - int32_t *position, - UErrorCode *status); -#endif - - /** * Check the specified string for possible security issues. * The text to be checked will typically be an identifier of some sort. @@ -1135,39 +1031,6 @@ USpoofCheckResult* checkResult, UErrorCode *status); -#if U_SHOW_CPLUSPLUS_API -/** - * Check the specified string for possible security issues. - * The text to be checked will typically be an identifier of some sort. - * The set of checks to be performed is specified with uspoof_setChecks(). - * - * @param sc The USpoofChecker - * @param id A identifier to be checked for possible security issues. - * @param checkResult An instance of USpoofCheckResult to be filled with - * details about the identifier. Can be NULL. - * @param status The error code, set if an error occurred while attempting to - * perform the check. - * Spoofing or security issues detected with the input string are - * not reported here, but through the function's return value. - * @return An integer value with bits set for any potential security - * or spoofing issues detected. The bits are defined by - * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) - * will be zero if the input string passes all of the - * enabled checks. Any information in this bitmask will be - * consistent with the information saved in the optional - * checkResult parameter. - * @see uspoof_openCheckResult - * @see uspoof_check2 - * @see uspoof_check2UTF8 - * @stable ICU 58 - */ -U_STABLE int32_t U_EXPORT2 -uspoof_check2UnicodeString(const USpoofChecker *sc, - const icu::UnicodeString &id, - USpoofCheckResult* checkResult, - UErrorCode *status); -#endif - /** * Create a USpoofCheckResult, used by the {@link uspoof_check2} class of functions to return * information about the identifier. Information includes: @@ -1199,32 +1062,6 @@ U_STABLE void U_EXPORT2 uspoof_closeCheckResult(USpoofCheckResult *checkResult); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUSpoofCheckResultPointer - * "Smart pointer" class, closes a USpoofCheckResult via `uspoof_closeCheckResult()`. - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 58 - */ - -/** - * \cond - * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER. - * For now, suppress with a Doxygen cond - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckResultPointer, USpoofCheckResult, uspoof_closeCheckResult); -/** \endcond */ - -U_NAMESPACE_END - -#endif - /** * Indicates which of the spoof check(s) have failed. The value is a bitwise OR of the constants for the tests * in question: USPOOF_RESTRICTION_LEVEL, USPOOF_CHAR_LIMIT, and so on. @@ -1355,36 +1192,6 @@ -#if U_SHOW_CPLUSPLUS_API -/** - * A version of {@link uspoof_areConfusable} accepting UnicodeStrings. - * - * @param sc The USpoofChecker - * @param s1 The first of the two identifiers to be compared for - * confusability. The strings are in UTF-8 format. - * @param s2 The second of the two identifiers to be compared for - * confusability. The strings are in UTF-8 format. - * @param status The error code, set if an error occurred while attempting to - * perform the check. - * Confusability of the identifiers is not reported here, - * but through this function's return value. - * @return An integer value with bit(s) set corresponding to - * the type of confusability found, as defined by - * enum USpoofChecks. Zero is returned if the identifiers - * are not confusable. - * - * @stable ICU 4.2 - * - * @see uspoof_areConfusable - */ -U_STABLE int32_t U_EXPORT2 -uspoof_areConfusableUnicodeString(const USpoofChecker *sc, - const icu::UnicodeString &s1, - const icu::UnicodeString &s2, - UErrorCode *status); -#endif - - /** * Get the "skeleton" for an identifier. * Skeletons are a transformation of the input identifier; @@ -1463,38 +1270,6 @@ char *dest, int32_t destCapacity, UErrorCode *status); -#if U_SHOW_CPLUSPLUS_API -/** - * Get the "skeleton" for an identifier. - * Skeletons are a transformation of the input identifier; - * Two identifiers are confusable if their skeletons are identical. - * See Unicode UAX #39 for additional information. - * - * Using skeletons directly makes it possible to quickly check - * whether an identifier is confusable with any of some large - * set of existing identifiers, by creating an efficiently - * searchable collection of the skeletons. - * - * @param sc The USpoofChecker. - * @param type Deprecated in ICU 58. You may pass any number. - * Originally, controlled which of the Unicode confusable data - * tables to use. - * @param id The input identifier whose skeleton will be computed. - * @param dest The output identifier, to receive the skeleton string. - * @param status The error code, set if an error occurred while attempting to - * perform the check. - * @return A reference to the destination (skeleton) string. - * - * @stable ICU 4.2 - */ -U_I18N_API icu::UnicodeString & U_EXPORT2 -uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, - uint32_t type, - const icu::UnicodeString &id, - icu::UnicodeString &dest, - UErrorCode *status); -#endif /* U_SHOW_CPLUSPLUS_API */ - /** * Get the set of Candidate Characters for Inclusion in Identifiers, as defined * in http://unicode.org/Public/security/latest/xidmodifications.txt @@ -1525,8 +1300,243 @@ U_STABLE const USet * U_EXPORT2 uspoof_getRecommendedSet(UErrorCode *status); +/** + * Serialize the data for a spoof detector into a chunk of memory. + * The flattened spoof detection tables can later be used to efficiently + * instantiate a new Spoof Detector. + * + * The serialized spoof checker includes only the data compiled from the + * Unicode data tables by uspoof_openFromSource(); it does not include + * include any other state or configuration that may have been set. + * + * @param sc the Spoof Detector whose data is to be serialized. + * @param data a pointer to 32-bit-aligned memory to be filled with the data, + * can be NULL if capacity==0 + * @param capacity the number of bytes available at data, + * or 0 for preflighting + * @param status an in/out ICU UErrorCode; possible errors include: + * - U_BUFFER_OVERFLOW_ERROR if the data storage block is too small for serialization + * - U_ILLEGAL_ARGUMENT_ERROR the data or capacity parameters are bad + * @return the number of bytes written or needed for the spoof data + * + * @see utrie2_openFromSerialized() + * @stable ICU 4.2 + */ +U_STABLE int32_t U_EXPORT2 +uspoof_serialize(USpoofChecker *sc, + void *data, int32_t capacity, + UErrorCode *status); + +U_CDECL_END + #if U_SHOW_CPLUSPLUS_API +U_NAMESPACE_BEGIN + +/** + * \class LocalUSpoofCheckerPointer + * "Smart pointer" class, closes a USpoofChecker via uspoof_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 4.4 + */ +/** + * \cond + * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER. + * For now, suppress with a Doxygen cond + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckerPointer, USpoofChecker, uspoof_close); +/** \endcond */ + +/** + * \class LocalUSpoofCheckResultPointer + * "Smart pointer" class, closes a USpoofCheckResult via `uspoof_closeCheckResult()`. + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 58 + */ + +/** + * \cond + * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER. + * For now, suppress with a Doxygen cond + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckResultPointer, USpoofCheckResult, uspoof_closeCheckResult); +/** \endcond */ + +U_NAMESPACE_END + +/** + * Limit the acceptable characters to those specified by a Unicode Set. + * Any previously specified character limit is + * is replaced by the new settings. This includes limits on + * characters that were set with the uspoof_setAllowedLocales() function. + * + * The USPOOF_CHAR_LIMIT test is automatically enabled for this + * USoofChecker by this function. + * + * @param sc The USpoofChecker + * @param chars A Unicode Set containing the list of + * characters that are permitted. Ownership of the set + * remains with the caller. The incoming set is cloned by + * this function, so there are no restrictions on modifying + * or deleting the UnicodeSet after calling this function. + * @param status The error code, set if this function encounters a problem. + * @stable ICU 4.2 + */ +U_STABLE void U_EXPORT2 +uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const icu::UnicodeSet *chars, UErrorCode *status); + + +/** + * Get a UnicodeSet for the characters permitted in an identifier. + * This corresponds to the limits imposed by the Set Allowed Characters / + * UnicodeSet functions. Limitations imposed by other checks will not be + * reflected in the set returned by this function. + * + * The returned set will be frozen, meaning that it cannot be modified + * by the caller. + * + * Ownership of the returned set remains with the Spoof Detector. The + * returned set will become invalid if the spoof detector is closed, + * or if a new set of allowed characters is specified. + * + * + * @param sc The USpoofChecker + * @param status The error code, set if this function encounters a problem. + * @return A UnicodeSet containing the characters that are permitted by + * the USPOOF_CHAR_LIMIT test. + * @stable ICU 4.2 + */ +U_STABLE const icu::UnicodeSet * U_EXPORT2 +uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status); + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * \note + * Consider using the newer API, {@link uspoof_check2UnicodeString}, instead. + * The newer API exposes additional information from the check procedure + * and is otherwise identical to this method. + * + * @param sc The USpoofChecker + * @param id A identifier to be checked for possible security issues. + * @param position Deprecated in ICU 51. Always returns zero. + * Originally, an out parameter for the index of the first + * string position that failed a check. + * This parameter may be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. + * @see uspoof_check2UnicodeString + * @stable ICU 4.2 + */ +U_STABLE int32_t U_EXPORT2 +uspoof_checkUnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id, + int32_t *position, + UErrorCode *status); + +/** + * Check the specified string for possible security issues. + * The text to be checked will typically be an identifier of some sort. + * The set of checks to be performed is specified with uspoof_setChecks(). + * + * @param sc The USpoofChecker + * @param id A identifier to be checked for possible security issues. + * @param checkResult An instance of USpoofCheckResult to be filled with + * details about the identifier. Can be NULL. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Spoofing or security issues detected with the input string are + * not reported here, but through the function's return value. + * @return An integer value with bits set for any potential security + * or spoofing issues detected. The bits are defined by + * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS) + * will be zero if the input string passes all of the + * enabled checks. Any information in this bitmask will be + * consistent with the information saved in the optional + * checkResult parameter. + * @see uspoof_openCheckResult + * @see uspoof_check2 + * @see uspoof_check2UTF8 + * @stable ICU 58 + */ +U_STABLE int32_t U_EXPORT2 +uspoof_check2UnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &id, + USpoofCheckResult* checkResult, + UErrorCode *status); + +/** + * A version of {@link uspoof_areConfusable} accepting UnicodeStrings. + * + * @param sc The USpoofChecker + * @param s1 The first of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param s2 The second of the two identifiers to be compared for + * confusability. The strings are in UTF-8 format. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * Confusability of the identifiers is not reported here, + * but through this function's return value. + * @return An integer value with bit(s) set corresponding to + * the type of confusability found, as defined by + * enum USpoofChecks. Zero is returned if the identifiers + * are not confusable. + * + * @stable ICU 4.2 + * + * @see uspoof_areConfusable + */ +U_STABLE int32_t U_EXPORT2 +uspoof_areConfusableUnicodeString(const USpoofChecker *sc, + const icu::UnicodeString &s1, + const icu::UnicodeString &s2, + UErrorCode *status); + +/** + * Get the "skeleton" for an identifier. + * Skeletons are a transformation of the input identifier; + * Two identifiers are confusable if their skeletons are identical. + * See Unicode UAX #39 for additional information. + * + * Using skeletons directly makes it possible to quickly check + * whether an identifier is confusable with any of some large + * set of existing identifiers, by creating an efficiently + * searchable collection of the skeletons. + * + * @param sc The USpoofChecker. + * @param type Deprecated in ICU 58. You may pass any number. + * Originally, controlled which of the Unicode confusable data + * tables to use. + * @param id The input identifier whose skeleton will be computed. + * @param dest The output identifier, to receive the skeleton string. + * @param status The error code, set if an error occurred while attempting to + * perform the check. + * @return A reference to the destination (skeleton) string. + * + * @stable ICU 4.2 + */ +U_I18N_API icu::UnicodeString & U_EXPORT2 +uspoof_getSkeletonUnicodeString(const USpoofChecker *sc, + uint32_t type, + const icu::UnicodeString &id, + icu::UnicodeString &dest, + UErrorCode *status); + /** * Get the set of Candidate Characters for Inclusion in Identifiers, as defined * in http://unicode.org/Public/security/latest/xidmodifications.txt @@ -1559,34 +1569,6 @@ #endif /* U_SHOW_CPLUSPLUS_API */ -/** - * Serialize the data for a spoof detector into a chunk of memory. - * The flattened spoof detection tables can later be used to efficiently - * instantiate a new Spoof Detector. - * - * The serialized spoof checker includes only the data compiled from the - * Unicode data tables by uspoof_openFromSource(); it does not include - * include any other state or configuration that may have been set. - * - * @param sc the Spoof Detector whose data is to be serialized. - * @param data a pointer to 32-bit-aligned memory to be filled with the data, - * can be NULL if capacity==0 - * @param capacity the number of bytes available at data, - * or 0 for preflighting - * @param status an in/out ICU UErrorCode; possible errors include: - * - U_BUFFER_OVERFLOW_ERROR if the data storage block is too small for serialization - * - U_ILLEGAL_ARGUMENT_ERROR the data or capacity parameters are bad - * @return the number of bytes written or needed for the spoof data - * - * @see utrie2_openFromSerialized() - * @stable ICU 4.2 - */ -U_STABLE int32_t U_EXPORT2 -uspoof_serialize(USpoofChecker *sc, - void *data, int32_t capacity, - UErrorCode *status); - - -#endif +#endif /* UCONFIG_NO_NORMALIZATION */ #endif /* USPOOF_H */ diff -Nru icu-64.2/source/i18n/unicode/utrans.h icu-65.1/source/i18n/unicode/utrans.h --- icu-64.2/source/i18n/unicode/utrans.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/utrans.h 2019-10-03 11:16:41.000000000 +0000 @@ -142,7 +142,7 @@ int32_t contextLimit; /** - * Beginning index, inclusive, of the text to be transliteratd. + * Beginning index, inclusive, of the text to be transliterated. * INPUT/OUTPUT parameter: This parameter is advanced past * characters that have already been transliterated by a * transliteration operation. @@ -151,7 +151,7 @@ int32_t start; /** - * Ending index, exclusive, of the text to be transliteratd. + * Ending index, exclusive, of the text to be transliterated. * INPUT/OUTPUT parameter: This parameter is updated to reflect * changes in the length of the text, but points to the same * logical position in the text. @@ -389,7 +389,7 @@ /** * Transliterate the portion of the UReplaceable text buffer that can - * be transliterated unambiguosly. This method is typically called + * be transliterated unambiguously. This method is typically called * after new text has been inserted, e.g. as a result of a keyboard * event. The transliterator will try to transliterate characters of * rep between index.cursor and @@ -454,8 +454,7 @@ * zero-terminated. Upon return, the new length is stored in * *textLength. If textLength is NULL then the string is assumed to * be zero-terminated. - * @param textCapacity a pointer to the length of the text buffer. - * Upon return, + * @param textCapacity the length of the text buffer * @param start the beginning index, inclusive; 0 <= start <= * limit. * @param limit pointer to the ending index, exclusive; start <= @@ -479,7 +478,7 @@ /** * Transliterate the portion of the UChar* text buffer that can be - * transliterated unambiguosly. See utrans_transIncremental(). The + * transliterated unambiguously. See utrans_transIncremental(). The * string is passed in in a UChar* buffer. The string is modified in * place. If the result is longer than textCapacity, it is truncated. * The actual length of the result is returned in *textLength, if diff -Nru icu-64.2/source/i18n/unicode/vtzone.h icu-65.1/source/i18n/unicode/vtzone.h --- icu-64.2/source/i18n/unicode/vtzone.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unicode/vtzone.h 2019-10-03 11:16:41.000000000 +0000 @@ -11,6 +11,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: RFC2445 VTIMEZONE support @@ -185,7 +187,7 @@ * @return A new copy of this TimeZone object. * @stable ICU 3.8 */ - virtual TimeZone* clone(void) const; + virtual VTimeZone* clone() const; /** * Returns the TimeZone's adjusted GMT offset (i.e., the number of milliseconds to add @@ -288,6 +290,7 @@ */ virtual UBool useDaylightTime(void) const; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Queries if the given date is in daylight savings time in * this time zone. @@ -302,6 +305,7 @@ * @deprecated ICU 2.4. Use Calendar::inDaylightTime() instead. */ virtual UBool inDaylightTime(UDate date, UErrorCode& status) const; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Returns true if this zone has the same rule and offset as another zone. @@ -453,5 +457,7 @@ #endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // VTZONE_H //eof diff -Nru icu-64.2/source/i18n/unum.cpp icu-65.1/source/i18n/unum.cpp --- icu-64.2/source/i18n/unum.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/unum.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -135,6 +135,11 @@ *status = U_MEMORY_ALLOCATION_ERROR; } + if (U_FAILURE(*status) && retVal != NULL) { + delete retVal; + retVal = NULL; + } + return reinterpret_cast(retVal); } diff -Nru icu-64.2/source/i18n/usearch.cpp icu-65.1/source/i18n/usearch.cpp --- icu-64.2/source/i18n/usearch.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/usearch.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -317,7 +317,7 @@ uprv_free(pattern->ces); } - uint16_t offset = 0; + uint32_t offset = 0; uint16_t result = 0; int32_t ce; @@ -388,7 +388,7 @@ uprv_free(pattern->pces); } - uint16_t offset = 0; + uint32_t offset = 0; uint16_t result = 0; int64_t pce; @@ -1351,7 +1351,7 @@ * @param destinationlength target array size, returning the appended length * @param source1 null-terminated first array * @param source2 second array -* @param source2length length of seond array +* @param source2length length of second array * @param source3 null-terminated third array * @param status error status if any * @return new destination array, destination if there was no new allocation @@ -1560,7 +1560,7 @@ /** * Take the rearranged end accents and tries matching. If match failed at -* a seperate preceding set of accents (seperated from the rearranged on by +* a separate preceding set of accents (separated from the rearranged on by * at least a base character) then we rearrange the preceding accents and * tries matching again. * We allow skipping of the ends of the accent set if the ces do not match. @@ -2220,7 +2220,7 @@ /** * Take the rearranged start accents and tries matching. If match failed at -* a seperate following set of accents (seperated from the rearranged on by +* a separate following set of accents (separated from the rearranged on by * at least a base character) then we rearrange the preceding accents and * tries matching again. * We allow skipping of the ends of the accent set if the ces do not match. @@ -3544,7 +3544,12 @@ // Verify that it is the next one in sequence, which is all // that is allowed. if (index != limitIx) { - UPRV_UNREACHABLE; + U_ASSERT(FALSE); + // TODO: In ICU 64 the above assert was changed to use UPRV_UNREACHABLE instead + // which unconditionally calls abort(). However, there were cases where this was + // being hit. This change is reverted for now, restoring the existing behavior. + // ICU-20792 tracks the follow-up work/further investigation on this. + return NULL; } // Manage the circular CE buffer indexing @@ -3581,7 +3586,12 @@ // Verify that it is the next one in sequence, which is all // that is allowed. if (index != limitIx) { - UPRV_UNREACHABLE; + U_ASSERT(FALSE); + // TODO: In ICU 64 the above assert was changed to use UPRV_UNREACHABLE instead + // which unconditionally calls abort(). However, there were cases where this was + // being hit. This change is reverted for now, restoring the existing behavior. + // ICU-20792 tracks the follow-up work/further investigation on this. + return NULL; } // Manage the circular CE buffer indexing @@ -3852,7 +3862,7 @@ #endif // Input parameter sanity check. - // TODO: should input indicies clip to the text length + // TODO: should input indices clip to the text length // in the same way that UText does. if(strsrch->pattern.cesLength == 0 || startIdx < 0 || @@ -4014,7 +4024,7 @@ // Check for the start of the match being within an Collation Element Expansion, // meaning that the first char of the match is only partially matched. - // With exapnsions, the first CE will report the index of the source + // With expansions, the first CE will report the index of the source // character, and all subsequent (expansions) CEs will report the source index of the // _following_ character. int32_t secondIx = firstCEI->highIndex; diff -Nru icu-64.2/source/i18n/uspoof.cpp icu-65.1/source/i18n/uspoof.cpp --- icu-64.2/source/i18n/uspoof.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/uspoof.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -349,7 +349,7 @@ *status = U_ILLEGAL_ARGUMENT_ERROR; return; } - UnicodeSet *clonedSet = static_cast(chars->clone()); + UnicodeSet *clonedSet = chars->clone(); if (clonedSet == NULL || clonedSet->isBogus()) { *status = U_MEMORY_ALLOCATION_ERROR; return; diff -Nru icu-64.2/source/i18n/uspoof_impl.cpp icu-65.1/source/i18n/uspoof_impl.cpp --- icu-64.2/source/i18n/uspoof_impl.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/uspoof_impl.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -82,7 +82,7 @@ if (src.fSpoofData != NULL) { fSpoofData = src.fSpoofData->addReference(); } - fAllowedCharsSet = static_cast(src.fAllowedCharsSet->clone()); + fAllowedCharsSet = src.fAllowedCharsSet->clone(); fAllowedLocales = uprv_strdup(src.fAllowedLocales); if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) { status = U_MEMORY_ALLOCATION_ERROR; @@ -193,7 +193,7 @@ } // Store the updated spoof checker state. - tmpSet = static_cast(allowedChars.clone()); + tmpSet = allowedChars.clone(); const char *tmpLocalesList = uprv_strdup(localesList); if (tmpSet == NULL || tmpLocalesList == NULL) { status = U_MEMORY_ALLOCATION_ERROR; diff -Nru icu-64.2/source/i18n/vtzone.cpp icu-65.1/source/i18n/vtzone.cpp --- icu-64.2/source/i18n/vtzone.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/vtzone.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -965,7 +965,7 @@ tzurl(source.tzurl), lastmod(source.lastmod), olsonzid(source.olsonzid), icutzver(source.icutzver) { if (source.tz != NULL) { - tz = (BasicTimeZone*)source.tz->clone(); + tz = source.tz->clone(); } if (source.vtzlines != NULL) { UErrorCode status = U_ZERO_ERROR; @@ -1007,7 +1007,7 @@ tz = NULL; } if (right.tz != NULL) { - tz = (BasicTimeZone*)right.tz->clone(); + tz = right.tz->clone(); } if (vtzlines != NULL) { delete vtzlines; @@ -1092,7 +1092,7 @@ status = U_MEMORY_ALLOCATION_ERROR; return NULL; } - vtz->tz = (BasicTimeZone *)basic_time_zone.clone(); + vtz->tz = basic_time_zone.clone(); if (vtz->tz == NULL) { status = U_MEMORY_ALLOCATION_ERROR; delete vtz; @@ -1177,8 +1177,8 @@ writeSimple(time, writer, status); } -TimeZone* -VTimeZone::clone(void) const { +VTimeZone* +VTimeZone::clone() const { return new VTimeZone(*this); } @@ -1957,7 +1957,7 @@ && (atzrule = dynamic_cast(tzt.getTo())) != NULL && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR ) { - finalDstRule = (AnnualTimeZoneRule*)tzt.getTo()->clone(); + finalDstRule = atzrule->clone(); } if (dstCount > 0) { if (year == dstStartYear + dstCount @@ -2008,7 +2008,7 @@ && (atzrule = dynamic_cast(tzt.getTo())) != NULL && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR ) { - finalStdRule = (AnnualTimeZoneRule*)tzt.getTo()->clone(); + finalStdRule = atzrule->clone(); } if (stdCount > 0) { if (year == stdStartYear + stdCount diff -Nru icu-64.2/source/i18n/windtfmt.cpp icu-65.1/source/i18n/windtfmt.cpp --- icu-64.2/source/i18n/windtfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/windtfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -213,7 +213,7 @@ return *this; } -Format *Win32DateFormat::clone(void) const +Win32DateFormat *Win32DateFormat::clone() const { return new Win32DateFormat(*this); } diff -Nru icu-64.2/source/i18n/windtfmt.h icu-65.1/source/i18n/windtfmt.h --- icu-64.2/source/i18n/windtfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/windtfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -48,7 +48,7 @@ virtual ~Win32DateFormat(); - virtual Format *clone(void) const; + virtual Win32DateFormat *clone() const; Win32DateFormat &operator=(const Win32DateFormat &other); diff -Nru icu-64.2/source/i18n/winnmfmt.cpp icu-65.1/source/i18n/winnmfmt.cpp --- icu-64.2/source/i18n/winnmfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/winnmfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -294,7 +294,7 @@ return *this; } -Format *Win32NumberFormat::clone(void) const +Win32NumberFormat *Win32NumberFormat::clone() const { return new Win32NumberFormat(*this); } diff -Nru icu-64.2/source/i18n/winnmfmt.h icu-65.1/source/i18n/winnmfmt.h --- icu-64.2/source/i18n/winnmfmt.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/winnmfmt.h 2019-10-03 11:16:41.000000000 +0000 @@ -44,7 +44,7 @@ virtual ~Win32NumberFormat(); - virtual Format *clone(void) const; + virtual Win32NumberFormat *clone() const; Win32NumberFormat &operator=(const Win32NumberFormat &other); diff -Nru icu-64.2/source/i18n/zonemeta.cpp icu-65.1/source/i18n/zonemeta.cpp --- icu-64.2/source/i18n/zonemeta.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/i18n/zonemeta.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -30,10 +30,7 @@ #include "olsontz.h" #include "uinvchar.h" -static icu::UMutex *gZoneMetaLock() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UMutex gZoneMetaLock; // CLDR Canonical ID mapping table static UHashtable *gCanonicalIDCache = NULL; @@ -266,11 +263,11 @@ } // Check if it was already cached - umtx_lock(gZoneMetaLock()); + umtx_lock(&gZoneMetaLock); { canonicalID = (const UChar *)uhash_get(gCanonicalIDCache, utzid); } - umtx_unlock(gZoneMetaLock()); + umtx_unlock(&gZoneMetaLock); if (canonicalID != NULL) { return canonicalID; @@ -351,7 +348,7 @@ U_ASSERT(canonicalID != NULL); // canocanilD must be non-NULL here // Put the resolved canonical ID to the cache - umtx_lock(gZoneMetaLock()); + umtx_lock(&gZoneMetaLock); { const UChar* idInCache = (const UChar *)uhash_get(gCanonicalIDCache, utzid); if (idInCache == NULL) { @@ -371,7 +368,7 @@ } } } - umtx_unlock(gZoneMetaLock()); + umtx_unlock(&gZoneMetaLock); } return canonicalID; @@ -449,14 +446,14 @@ // Check if it was already cached UBool cached = FALSE; UBool singleZone = FALSE; - umtx_lock(gZoneMetaLock()); + umtx_lock(&gZoneMetaLock); { singleZone = cached = gSingleZoneCountries->contains((void*)region); if (!cached) { cached = gMultiZonesCountries->contains((void*)region); } } - umtx_unlock(gZoneMetaLock()); + umtx_unlock(&gZoneMetaLock); if (!cached) { // We need to go through all zones associated with the region. @@ -475,7 +472,7 @@ delete ids; // Cache the result - umtx_lock(gZoneMetaLock()); + umtx_lock(&gZoneMetaLock); { UErrorCode ec = U_ZERO_ERROR; if (singleZone) { @@ -488,7 +485,7 @@ } } } - umtx_unlock(gZoneMetaLock()); + umtx_unlock(&gZoneMetaLock); } if (singleZone) { @@ -575,11 +572,11 @@ // get the mapping from cache const UVector *result = NULL; - umtx_lock(gZoneMetaLock()); + umtx_lock(&gZoneMetaLock); { result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); } - umtx_unlock(gZoneMetaLock()); + umtx_unlock(&gZoneMetaLock); if (result != NULL) { return result; @@ -593,7 +590,7 @@ } // put the new one into the cache - umtx_lock(gZoneMetaLock()); + umtx_lock(&gZoneMetaLock); { // make sure it's already created result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); @@ -621,7 +618,7 @@ delete tmpResult; } } - umtx_unlock(gZoneMetaLock()); + umtx_unlock(&gZoneMetaLock); return result; } diff -Nru icu-64.2/source/io/io.vcxproj icu-65.1/source/io/io.vcxproj --- icu-64.2/source/io/io.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/io/io.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -35,126 +35,64 @@ <_ProjectFileVersion>10.0.30319.1 - .\..\..\lib\ - .\x86\Release\ - false - .\..\..\lib\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false + + $(OutDir)\icuio.tlb + ..\..\include;..\common;%(AdditionalIncludeDirectories) U_IO_IMPLEMENTATION;%(PreprocessorDefinitions) false Level3 + Default + ProgramDatabase + $(OutDir)/icuio.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/icuio.pdb ..\common;%(AdditionalIncludeDirectories) - 0x4ab00000 + ..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - .\..\..\lib\icuio.tlb - + + - MultiThreadedDLL - true - .\x86\Release/icuio.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - Default - - - ..\..\bin\icuio64.dll - icuuc.lib;icuin.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\lib\icuio.pdb - false - - - ..\..\lib\icuio.lib - - - - - .\..\..\lib\icuio.tlb - - - MultiThreadedDebugDLL - .\x86\Debug/icuio.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - EditAndContinue - Default + MultiThreadedDebugDLL - ..\..\bin\icuio64d.dll - icuucd.lib;icuind.lib;%(AdditionalDependencies) - ..\..\lib;%(AdditionalLibraryDirectories) true - .\..\..\lib\icuiod.pdb - false - - - ..\..\lib\icuiod.lib + ..\..\$(IcuBinOutputDir)\icuio65d.dll + ..\..\$(IcuLibOutputDir)\icuiod.pdb + ..\..\$(IcuLibOutputDir)\icuiod.lib + icuucd.lib;icuind.lib;%(AdditionalDependencies) - - - .\..\..\lib64\icuio.tlb - + + MultiThreadedDLL true - .\x64\Release/icuio.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default - ..\..\bin64\icuio64.dll + ..\..\$(IcuBinOutputDir)\icuio65.dll + ..\..\$(IcuLibOutputDir)\icuio.pdb + ..\..\$(IcuLibOutputDir)\icuio.lib icuuc.lib;icuin.lib;%(AdditionalDependencies) - ..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\lib64\icuio.pdb - ..\..\lib64\icuio.lib - - - - - .\..\..\lib64\icuio.tlb - - - MultiThreadedDebugDLL - .\x64\Debug/icuio.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - ProgramDatabase - Default - - - ..\..\bin64\icuio64d.dll - icuucd.lib;icuind.lib;%(AdditionalDependencies) - ..\..\lib64;%(AdditionalLibraryDirectories) - true - .\..\..\lib64\icuiod.pdb - ..\..\lib64\icuiod.lib diff -Nru icu-64.2/source/io/locbund.cpp icu-65.1/source/io/locbund.cpp --- icu-64.2/source/io/locbund.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/io/locbund.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -47,7 +47,7 @@ static inline UNumberFormat * copyInvariantFormatter(ULocaleBundle *result, UNumberFormatStyle style) { U_NAMESPACE_USE - static UMutex gLock = U_MUTEX_INITIALIZER; + static UMutex gLock; Mutex lock(&gLock); if (result->fNumberFormat[style-1] == NULL) { if (gPosixNumberFormat[style-1] == NULL) { diff -Nru icu-64.2/source/io/ucln_io.cpp icu-65.1/source/io/ucln_io.cpp --- icu-64.2/source/io/ucln_io.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/io/ucln_io.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -16,6 +16,7 @@ * created by: George Rhoten */ +#include "unicode/utypes.h" #include "mutex.h" #include "ucln.h" #include "ucln_io.h" diff -Nru icu-64.2/source/io/unicode/ustream.h icu-65.1/source/io/unicode/ustream.h --- icu-64.2/source/io/unicode/ustream.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/io/unicode/ustream.h 2019-10-03 11:16:41.000000000 +0000 @@ -17,6 +17,10 @@ #ifndef USTREAM_H #define USTREAM_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unistr.h" #if !UCONFIG_NO_CONVERSION // not available without conversion @@ -60,4 +64,6 @@ /* No operator for UChar because it can conflict with wchar_t */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff -Nru icu-64.2/source/layoutex/layoutex.vcxproj icu-65.1/source/layoutex/layoutex.vcxproj --- icu-64.2/source/layoutex/layoutex.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/layoutex/layoutex.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -54,9 +54,6 @@ U_LAYOUTEX_IMPLEMENTATION;%(PreprocessorDefinitions) Level3 - - 0x4ac80000 - @@ -73,11 +70,10 @@ Default - ..\..\bin\iculx64.dll + ..\..\bin\iculx65.dll icuuc.lib;%(AdditionalDependencies) .\..\..\lib;%(AdditionalLibraryDirectories) .\..\..\lib\iculx.pdb - false ..\..\lib\iculx.lib @@ -99,12 +95,11 @@ Default - ..\..\bin\iculx64d.dll + ..\..\bin\iculx65d.dll icuucd.lib;%(AdditionalDependencies) .\..\..\lib;%(AdditionalLibraryDirectories) true .\..\..\lib\iculxd.pdb - false ..\..\lib\iculxd.lib @@ -125,7 +120,7 @@ Default - ..\..\bin64\iculx64.dll + ..\..\bin64\iculx65.dll icuuc.lib;%(AdditionalDependencies) .\..\..\lib64;%(AdditionalLibraryDirectories) .\..\..\lib64\iculx.pdb @@ -148,7 +143,7 @@ Default - ..\..\bin64\iculx64d.dll + ..\..\bin64\iculx65d.dll icuucd.lib;%(AdditionalDependencies) .\..\..\lib64;%(AdditionalLibraryDirectories) true diff -Nru icu-64.2/source/python/icutools/databuilder/comment_stripper.py icu-65.1/source/python/icutools/databuilder/comment_stripper.py --- icu-64.2/source/python/icutools/databuilder/comment_stripper.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/comment_stripper.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,51 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +import io + +class CommentStripper(object): + """Removes lines starting with "//" from a file stream.""" + + def __init__(self, f): + self.f = f + self.state = 0 + + def read(self, size=-1): + bytes = self.f.read(size) + # TODO: Do we need to read more bytes if comments were stripped + # in order to obey the size request? + return "".join(self._strip_comments(bytes)) + + def _strip_comments(self, bytes): + for byte in bytes: + if self.state == 0: + # state 0: start of a line + if byte == "/": + self.state = 1 + elif byte == "\n": + self.state = 0 + yield byte + else: + self.state = 2 + yield byte + elif self.state == 1: + # state 1: read a single '/' + if byte == "/": + self.state = 3 + elif byte == "\n": + self.state = 0 + yield "/" # the one that was skipped + yield "\n" + else: + self.state = 2 + yield "/" # the one that was skipped + yield byte + elif self.state == 2: + # state 2: middle of a line, no comment + if byte == "\n": + self.state = 0 + yield byte + elif self.state == 3: + # state 3: inside a comment + if byte == "\n": + self.state = 0 diff -Nru icu-64.2/source/python/icutools/databuilder/filtration.py icu-65.1/source/python/icutools/databuilder/filtration.py --- icu-64.2/source/python/icutools/databuilder/filtration.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/filtration.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,401 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# Python 2/3 Compatibility (ICU-20299) +# TODO(ICU-20301): Remove this. +from __future__ import print_function + +from abc import abstractmethod +from collections import defaultdict +import re +import sys + +from . import * +from . import utils +from .locale_dependencies import data as DEPENDENCY_DATA +from .request_types import * + + +# Note: for this to be a proper abstract class, it should extend abc.ABC. +# There is no nice way to do this that works in both Python 2 and 3. +# TODO(ICU-20301): Make this inherit from abc.ABC. +class Filter(object): + @staticmethod + def create_from_json(json_data): + if "filterType" in json_data: + filter_type = json_data["filterType"] + else: + filter_type = "file-stem" + + if filter_type == "file-stem": + return FileStemFilter(json_data) + elif filter_type == "language": + return LanguageFilter(json_data) + elif filter_type == "regex": + return RegexFilter(json_data) + elif filter_type == "exclude": + return ExclusionFilter() + elif filter_type == "union": + return UnionFilter(json_data) + elif filter_type == "locale": + return LocaleFilter(json_data) + else: + print("Error: Unknown filterType option: %s" % filter_type, file=sys.stderr) + return None + + def filter(self, request): + if not request.apply_file_filter(self): + return [] + for file in request.all_input_files(): + assert self.match(file) + return [request] + + @classmethod + def _file_to_file_stem(cls, file): + start = file.filename.rfind("/") + limit = file.filename.rfind(".") + return file.filename[start+1:limit] + + @abstractmethod + def match(self, file): + pass + + +class InclusionFilter(Filter): + def match(self, file): + return True + + +class ExclusionFilter(Filter): + def match(self, file): + return False + + +class WhitelistBlacklistFilter(Filter): + def __init__(self, json_data): + if "whitelist" in json_data: + self.is_whitelist = True + self.whitelist = json_data["whitelist"] + else: + assert "blacklist" in json_data, "Need either whitelist or blacklist: %s" % str(json_data) + self.is_whitelist = False + self.blacklist = json_data["blacklist"] + + def match(self, file): + file_stem = self._file_to_file_stem(file) + return self._should_include(file_stem) + + @abstractmethod + def _should_include(self, file_stem): + pass + + +class FileStemFilter(WhitelistBlacklistFilter): + def _should_include(self, file_stem): + if self.is_whitelist: + return file_stem in self.whitelist + else: + return file_stem not in self.blacklist + + +class LanguageFilter(WhitelistBlacklistFilter): + def _should_include(self, file_stem): + language = file_stem.split("_")[0] + if language == "root": + # Always include root.txt + return True + if self.is_whitelist: + return language in self.whitelist + else: + return language not in self.blacklist + + +class RegexFilter(WhitelistBlacklistFilter): + def __init__(self, *args): + # TODO(ICU-20301): Change this to: super().__init__(*args) + super(RegexFilter, self).__init__(*args) + if self.is_whitelist: + self.whitelist = [re.compile(pat) for pat in self.whitelist] + else: + self.blacklist = [re.compile(pat) for pat in self.blacklist] + + def _should_include(self, file_stem): + if self.is_whitelist: + for pattern in self.whitelist: + if pattern.match(file_stem): + return True + return False + else: + for pattern in self.blacklist: + if pattern.match(file_stem): + return False + return True + + +class UnionFilter(Filter): + def __init__(self, json_data): + # Collect the sub-filters. + self.sub_filters = [] + for filter_json in json_data["unionOf"]: + self.sub_filters.append(Filter.create_from_json(filter_json)) + + def match(self, file): + """Match iff any of the sub-filters match.""" + for filter in self.sub_filters: + if filter.match(file): + return True + return False + + +LANGUAGE_SCRIPT_REGEX = re.compile(r"^([a-z]{2,3})_[A-Z][a-z]{3}$") +LANGUAGE_ONLY_REGEX = re.compile(r"^[a-z]{2,3}$") + +class LocaleFilter(Filter): + def __init__(self, json_data): + self.locales_requested = set() + self.locales_required = set() + self.include_children = json_data.get("includeChildren", True) + self.include_scripts = json_data.get("includeScripts", False) + + # Compute the requested and required locales. + for locale in json_data["whitelist"]: + self._add_locale_and_parents(locale) + + def _add_locale_and_parents(self, locale): + # Store the locale as *requested* + self.locales_requested.add(locale) + # Store the locale and its dependencies as *required* + while locale is not None: + self.locales_required.add(locale) + locale = self._get_parent_locale(locale) + + def match(self, file): + locale = self._file_to_file_stem(file) + + # A locale is *required* if it is *requested* or an ancestor of a + # *requested* locale. + if locale in self.locales_required: + return True + + # Resolve include_scripts and include_children. + return self._match_recursive(locale) + + def _match_recursive(self, locale): + # Base case: return True if we reached a *requested* locale, + # or False if we ascend out of the locale tree. + if locale is None: + return False + if locale in self.locales_requested: + return True + + # Check for alternative scripts. + # This causes sr_Latn to check sr instead of going directly to root. + if self.include_scripts: + match = LANGUAGE_SCRIPT_REGEX.match(locale) + if match and self._match_recursive(match.group(1)): + return True + + # Check if we are a descendant of a *requested* locale. + if self.include_children: + parent = self._get_parent_locale(locale) + if self._match_recursive(parent): + return True + + # No matches. + return False + + @classmethod + def _get_parent_locale(cls, locale): + if locale in DEPENDENCY_DATA["parents"]: + return DEPENDENCY_DATA["parents"][locale] + if locale in DEPENDENCY_DATA["aliases"]: + return DEPENDENCY_DATA["aliases"][locale] + if LANGUAGE_ONLY_REGEX.match(locale): + return "root" + i = locale.rfind("_") + if i < 0: + return None + return locale[:i] + + +def apply_filters(requests, config): + """Runs the filters and returns a new list of requests.""" + requests = _apply_file_filters(requests, config) + requests = _apply_resource_filters(requests, config) + return requests + + +def _apply_file_filters(old_requests, config): + """Filters out entire files.""" + filters = _preprocess_file_filters(old_requests, config) + new_requests = [] + for request in old_requests: + category = request.category + if category in filters: + new_requests += filters[category].filter(request) + else: + new_requests.append(request) + return new_requests + + +def _preprocess_file_filters(requests, config): + all_categories = set( + request.category + for request in requests + ) + all_categories.remove(None) + all_categories = list(sorted(all_categories)) + json_data = config.filters_json_data + filters = {} + default_filter_json = "exclude" if config.strategy == "additive" else "include" + for category in all_categories: + filter_json = default_filter_json + # Figure out the correct filter to create + if "featureFilters" in json_data and category in json_data["featureFilters"]: + filter_json = json_data["featureFilters"][category] + if filter_json == "include" and "localeFilter" in json_data and category.endswith("_tree"): + filter_json = json_data["localeFilter"] + # Resolve the filter JSON into a filter object + if filter_json == "exclude": + filters[category] = ExclusionFilter() + elif filter_json == "include": + pass # no-op + else: + filters[category] = Filter.create_from_json(filter_json) + if "featureFilters" in json_data: + for category in json_data["featureFilters"]: + if category not in all_categories: + print("Warning: category %s is not known" % category, file=sys.stderr) + return filters + + +class ResourceFilterInfo(object): + def __init__(self, category, strategy): + self.category = category + self.strategy = strategy + self.filter_tmp_dir = "filters/%s" % category + self.input_files = None + self.filter_files = None + self.rules_by_file = None + + def apply_to_requests(self, all_requests): + # Call this method only once per list of requests. + assert self.input_files is None + for request in all_requests: + if request.category != self.category: + continue + if not isinstance(request, AbstractExecutionRequest): + continue + if request.tool != IcuTool("genrb"): + continue + if not request.input_files: + continue + self._set_files(request.input_files) + request.dep_targets += [self.filter_files[:]] + arg_str = "--filterDir {TMP_DIR}/%s" % self.filter_tmp_dir + request.args = "%s %s" % (arg_str, request.args) + + # Make sure we found the target request + if self.input_files is None: + print("WARNING: Category not found: %s" % self.category, file=sys.stderr) + self.input_files = [] + self.filter_files = [] + self.rules_by_file = [] + + def _set_files(self, files): + # Note: The input files to genrb for a certain category should always + # be the same. For example, there are often two genrb calls: one for + # --writePoolBundle, and the other for --usePoolBundle. They are both + # expected to have the same list of input files. + if self.input_files is not None: + assert self.input_files == files + return + self.input_files = list(files) + self.filter_files = [ + TmpFile("%s/%s" % (self.filter_tmp_dir, basename)) + for basename in ( + file.filename[file.filename.rfind("/")+1:] + for file in files + ) + ] + if self.strategy == "additive": + self.rules_by_file = [ + [r"-/", r"+/%%ALIAS", r"+/%%Parent"] + for _ in range(len(files)) + ] + else: + self.rules_by_file = [ + [r"+/"] + for _ in range(len(files)) + ] + + def add_rules(self, file_filter, rules): + for file, rule_list in zip(self.input_files, self.rules_by_file): + if file_filter.match(file): + rule_list += rules + + def make_requests(self): + # Map from rule list to filter files with that rule list + unique_rules = defaultdict(list) + for filter_file, rules in zip(self.filter_files, self.rules_by_file): + unique_rules[tuple(rules)].append(filter_file) + + new_requests = [] + i = 0 + for rules, filter_files in unique_rules.items(): + base_filter_file = filter_files[0] + new_requests += [ + PrintFileRequest( + name = "%s_print_%d" % (self.category, i), + output_file = base_filter_file, + content = self._generate_resource_filter_txt(rules) + ) + ] + i += 1 + for filter_file in filter_files[1:]: + new_requests += [ + CopyRequest( + name = "%s_copy_%d" % (self.category, i), + input_file = base_filter_file, + output_file = filter_file + ) + ] + i += 1 + return new_requests + + @classmethod + def _generate_resource_filter_txt(cls, rules): + result = "# Caution: This file is automatically generated\n\n" + result += "\n".join(rules) + return result + + +def _apply_resource_filters(all_requests, config): + """Creates filters for looking within resource bundle files.""" + json_data = config.filters_json_data + if "resourceFilters" not in json_data: + return all_requests + + collected = {} + for entry in json_data["resourceFilters"]: + if "files" in entry: + file_filter = Filter.create_from_json(entry["files"]) + else: + file_filter = InclusionFilter() + for category in entry["categories"]: + # not defaultdict because we need to pass arguments to the constructor + if category not in collected: + filter_info = ResourceFilterInfo(category, config.strategy) + filter_info.apply_to_requests(all_requests) + collected[category] = filter_info + else: + filter_info = collected[category] + filter_info.add_rules(file_filter, entry["rules"]) + + # Add the filter generation requests to the beginning so that by default + # they are made before genrb gets run (order is required by windirect) + new_requests = [] + for filter_info in collected.values(): + new_requests += filter_info.make_requests() + new_requests += all_requests + return new_requests diff -Nru icu-64.2/source/python/icutools/databuilder/filtration_schema.json icu-65.1/source/python/icutools/databuilder/filtration_schema.json --- icu-64.2/source/python/icutools/databuilder/filtration_schema.json 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/filtration_schema.json 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,169 @@ +// Copyright (C) 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +{ + "$id": "http://unicode.org/icu-filter-schema", + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "JSON Schema for an ICU data filter file", + "type": "object", + "properties": { + "strategy": { + "type": "string", + "enum": ["additive", "subtractive"] + }, + "localeFilter": { "$ref": "#/definitions/filter" }, + "featureFilters": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { "$ref": "#/definitions/filter" }, + { + "type": "string", + "enum": ["include", "exclude"] + } + ] + } + }, + "resourceFilters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "categories": { + "type": "array", + "items": { "type": "string" } + }, + "files": { "$ref": "#/definitions/filter" }, + "rules": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[+-]/[\\S]*$" + } + } + }, + "required": ["categories", "rules"], + "additionalProperties": false + } + }, + "fileReplacements": { + "type": "object", + "properties": { + "directory": { + "type": "string", + "pattern": "^(\\$SRC|\\$FILTERS|\\$CWD|/$|/[^/]+)(/[^/]+)*$" + }, + "replacements": { + "type": "array", + "items": { + "oneOf": [ + { "type": "string" }, + { + "type": "object", + "properties": { + "src": { "type": "string" }, + "dest": { "type": "string" } + }, + "additionalProperties": false, + "required": ["src", "dest"] + } + ] + } + } + }, + "additionalProperties": false, + "required": ["directory", "replacements"] + }, + "collationUCAData": { + "type": "string", + "enum": ["unihan", "implicithan"] + }, + "usePoolBundle": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "filter": { + "type": "object", + "oneOf": [ + { + "properties": { + "filterType": { + "$ref": "#/definitions/blacklistWhitelistFilterTypes" + }, + "whitelist": { "$ref": "#/definitions/stringList" } + }, + "required": ["whitelist"], + "additionalProperties": false + }, + { + "properties": { + "filterType": { + "$ref": "#/definitions/blacklistWhitelistFilterTypes" + }, + "blacklist": { "$ref": "#/definitions/stringList" } + }, + "required": ["blacklist"], + "additionalProperties": false + }, + { + "properties": { + "filterType": { + "type": "string", + "enum": ["exclude"] + } + }, + "required": ["filterType"], + "additionalProperties": false + }, + { + "properties": { + "filterType": { + "type": "string", + "enum": ["locale"] + }, + "includeChildren": { + "type": "boolean" + }, + "includeScripts": { + "type": "boolean" + }, + "whitelist": { "$ref": "#/definitions/stringList" } + }, + "required": ["filterType", "whitelist"], + "additionalProperties": false + }, + { + "properties": { + "filterType": { + "type": "string", + "enum": ["union"] + }, + "unionOf": { + "type": "array", + "items": { "$ref": "#/definitions/filter" } + } + }, + "required": ["filterType", "unionOf"], + "additionalProperties": false + } + ] + }, + "blacklistWhitelistFilterTypes": { + "type": "string", + "enum": [ + "language", + "regex" + ] + }, + "stringList": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + } + } +} diff -Nru icu-64.2/source/python/icutools/databuilder/__init__.py icu-65.1/source/python/icutools/databuilder/__init__.py --- icu-64.2/source/python/icutools/databuilder/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/__init__.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,16 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +from collections import namedtuple + +LocalFile = namedtuple("LocalFile", ["dirname", "filename"]) +SrcFile = namedtuple("SrcFile", ["filename"]) +InFile = namedtuple("InFile", ["filename"]) +TmpFile = namedtuple("TmpFile", ["filename"]) +OutFile = namedtuple("OutFile", ["filename"]) +PkgFile = namedtuple("PkgFile", ["filename"]) + +IcuTool = namedtuple("IcuTool", ["name"]) +SystemTool = namedtuple("SystemTool", ["name"]) + +DepTarget = namedtuple("DepTarget", ["name"]) diff -Nru icu-64.2/source/python/icutools/databuilder/locale_dependencies.py icu-65.1/source/python/icutools/databuilder/locale_dependencies.py --- icu-64.2/source/python/icutools/databuilder/locale_dependencies.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/locale_dependencies.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# © 2019 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html#License + +data = { + "cldrVersion": "36", + "aliases": { + "ars": "ar_SA", + "az_AZ": "az_Latn_AZ", + "bs_BA": "bs_Latn_BA", + "en_NH": "en_VU", + "en_RH": "en_ZW", + "ff_CM": "ff_Latn_CM", + "ff_GN": "ff_Latn_GN", + "ff_MR": "ff_Latn_MR", + "ff_SN": "ff_Latn_SN", + "in": "id", + "in_ID": "id_ID", + "iw": "he", + "iw_IL": "he_IL", + "mo": "ro", + "no_NO": "nb_NO", + "no_NO_NY": "nn_NO", + "no": "nb", + "pa_IN": "pa_Guru_IN", + "pa_PK": "pa_Arab_PK", + "sh": "sr_Latn", + "sh_BA": "sr_Latn_BA", + "sh_CS": "sr_Latn_RS", + "sh_YU": "sr_Latn_RS", + "shi_MA": "shi_Tfng_MA", + "sr_BA": "sr_Cyrl_BA", + "sr_CS": "sr_Cyrl_RS", + "sr_ME": "sr_Latn_ME", + "sr_RS": "sr_Cyrl_RS", + "sr_XK": "sr_Cyrl_XK", + "sr_YU": "sr_Cyrl_RS", + "sr_Cyrl_YU": "sr_Cyrl_RS", + "sr_Cyrl_CS": "sr_Cyrl_RS", + "sr_Latn_YU": "sr_Latn_RS", + "sr_Latn_CS": "sr_Latn_RS", + "tl": "fil", + "tl_PH": "fil_PH", + "uz_AF": "uz_Arab_AF", + "uz_UZ": "uz_Latn_UZ", + "vai_LR": "vai_Vaii_LR", + "yue_CN": "yue_Hans_CN", + "yue_HK": "yue_Hant_HK", + "zh_CN": "zh_Hans_CN", + "zh_HK": "zh_Hant_HK", + "zh_MO": "zh_Hant_MO", + "zh_SG": "zh_Hans_SG", + "zh_TW": "zh_Hant_TW" + }, + "parents": { + "ff_Adlm": "root", + "en_CM": "en_001", + "so_Arab": "root", + "en_KY": "en_001", + "en_TC": "en_001", + "yue_Hans": "root", + "en_CX": "en_001", + "es_EC": "es_419", + "es_US": "es_419", + "byn_Latn": "root", + "en_CY": "en_001", + "en_LC": "en_001", + "en_TK": "en_001", + "tg_Arab": "root", + "es_UY": "es_419", + "ky_Latn": "root", + "en_TO": "en_001", + "en_TT": "en_001", + "en_DE": "en_150", + "es_MX": "es_419", + "en_TV": "en_001", + "en_DG": "en_001", + "pt_ST": "pt_PT", + "en_DM": "en_001", + "en_LR": "en_001", + "en_TZ": "en_001", + "en_LS": "en_001", + "en_DK": "en_150", + "blt_Latn": "root", + "es_VE": "es_419", + "es_NI": "es_419", + "sd_Khoj": "root", + "pt_AO": "pt_PT", + "en_UG": "en_001", + "yo_Arab": "root", + "dje_Arab": "root", + "en_MG": "en_001", + "en_MO": "en_001", + "en_MU": "en_001", + "en_MS": "en_001", + "en_MT": "en_001", + "shi_Latn": "root", + "es_BR": "es_419", + "en_AU": "en_001", + "en_ZM": "en_001", + "en_AT": "en_150", + "es_BZ": "es_419", + "uz_Arab": "root", + "az_Cyrl": "root", + "es_SV": "es_419", + "en_ZW": "en_001", + "en_JE": "en_001", + "en_BB": "en_001", + "sd_Deva": "root", + "pa_Arab": "root", + "en_RW": "en_001", + "es_CO": "es_419", + "en_JM": "en_001", + "en_BE": "en_150", + "dyo_Arab": "root", + "es_CL": "es_419", + "en_BM": "en_001", + "en_SC": "en_001", + "es_CR": "es_419", + "en_150": "en_001", + "en_BS": "en_001", + "en_SD": "en_001", + "pt_GQ": "pt_PT", + "en_SB": "en_001", + "es_CU": "es_419", + "en_SG": "en_001", + "uz_Cyrl": "root", + "en_BW": "en_001", + "en_SH": "en_001", + "en_SE": "en_150", + "pt_GW": "pt_PT", + "ky_Arab": "root", + "en_BZ": "en_001", + "en_SL": "en_001", + "en_SI": "en_150", + "ff_Arab": "root", + "en_KE": "en_001", + "bm_Nkoo": "root", + "en_CC": "en_001", + "en_SS": "en_001", + "iu_Latn": "root", + "en_CA": "en_001", + "en_KI": "en_001", + "es_DO": "es_419", + "en_SX": "en_001", + "en_CH": "en_150", + "en_KN": "en_001", + "en_CK": "en_001", + "ml_Arab": "root", + "en_SZ": "en_001", + "pt_FR": "pt_PT", + "ug_Cyrl": "root", + "en_GY": "en_001", + "en_PH": "en_001", + "en_PG": "en_001", + "en_PK": "en_001", + "cu_Glag": "root", + "en_PN": "en_001", + "kk_Arab": "root", + "en_HK": "en_001", + "zh_Hant": "root", + "en_PW": "en_001", + "es_AR": "es_419", + "pt_MZ": "pt_PT", + "sd_Sind": "root", + "en_Shaw": "root", + "en_IE": "en_001", + "ms_Arab": "root", + "en_IM": "en_001", + "en_IN": "en_001", + "es_BO": "es_419", + "en_IL": "en_001", + "en_AI": "en_001", + "az_Arab": "root", + "en_AG": "en_001", + "en_IO": "en_001", + "en_ZA": "en_001", + "en_MY": "en_001", + "en_ER": "en_001", + "en_VC": "en_001", + "mn_Mong": "root", + "vai_Latn": "root", + "en_MW": "en_001", + "pt_LU": "pt_PT", + "bs_Cyrl": "root", + "en_VG": "en_001", + "en_NA": "en_001", + "en_NF": "en_001", + "en_NG": "en_001", + "ha_Arab": "root", + "en_NL": "en_150", + "zh_Hant_MO": "zh_Hant_HK", + "en_VU": "en_001", + "en_FJ": "en_001", + "en_NR": "en_001", + "en_FK": "en_001", + "es_GT": "es_419", + "en_FI": "en_150", + "ku_Arab": "root", + "pt_MO": "pt_PT", + "en_FM": "en_001", + "en_NU": "en_001", + "en_NZ": "en_001", + "pt_CH": "pt_PT", + "en_Dsrt": "root", + "es_PE": "es_419", + "es_PA": "es_419", + "pt_CV": "pt_PT", + "wo_Arab": "root", + "en_WS": "en_001", + "en_GD": "en_001", + "en_GB": "en_001", + "es_HN": "es_419", + "pt_TL": "pt_PT", + "en_GG": "en_001", + "en_GH": "en_001", + "es_PR": "es_419", + "sw_Arab": "root", + "en_GI": "en_001", + "sr_Latn": "root", + "en_GM": "en_001", + "es_PY": "es_419" + } +} diff -Nru icu-64.2/source/python/icutools/databuilder/__main__.py icu-65.1/source/python/icutools/databuilder/__main__.py --- icu-64.2/source/python/icutools/databuilder/__main__.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/__main__.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,347 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# Python 2/3 Compatibility (ICU-20299) +# TODO(ICU-20301): Remove this. +from __future__ import print_function + +import argparse +import glob as pyglob +import json +import os +import sys + +from . import * +from .comment_stripper import CommentStripper +from .request_types import CopyRequest +from .renderers import makefile, common_exec +from . import filtration, utils + +flag_parser = argparse.ArgumentParser( + description = """Generates rules for building ICU binary data files from text +and other input files in source control. + +Use the --mode option to declare how to execute those rules, either exporting +the rules to a Makefile or spawning child processes to run them immediately: + + --mode=gnumake prints a Makefile to standard out. + --mode=unix-exec spawns child processes in a Unix-like environment. + --mode=windows-exec spawns child processes in a Windows-like environment. + +Tips for --mode=unix-exec +========================= + +Create two empty directories for out_dir and tmp_dir. They will get filled +with a lot of intermediate files. + +Set LD_LIBRARY_PATH to include the lib directory. e.g., from icu4c/source: + + $ LD_LIBRARY_PATH=lib PYTHONPATH=python python3 -m icutools.databuilder ... + +Once icutools.databuilder finishes, you have compiled the data, but you have +not packaged it into a .dat or .so file. This is done by the separate pkgdata +tool in bin. Read the docs of pkgdata: + + $ LD_LIBRARY_PATH=lib ./bin/pkgdata --help + +Example command line to call pkgdata: + + $ LD_LIBRARY_PATH=lib ./bin/pkgdata -m common -p icudt63l -c \\ + -O data/icupkg.inc -s $OUTDIR -d $TMPDIR $TMPDIR/icudata.lst + +where $OUTDIR and $TMPDIR are your out and tmp directories, respectively. +The above command will create icudt63l.dat in the tmpdir. + +Command-Line Arguments +====================== +""", + formatter_class = argparse.RawDescriptionHelpFormatter +) + +arg_group_required = flag_parser.add_argument_group("required arguments") +arg_group_required.add_argument( + "--mode", + help = "What to do with the generated rules.", + choices = ["gnumake", "unix-exec", "windows-exec", "bazel-exec"], + required = True +) + +flag_parser.add_argument( + "--src_dir", + help = "Path to data source folder (icu4c/source/data).", + default = "." +) +flag_parser.add_argument( + "--filter_file", + metavar = "PATH", + help = "Path to an ICU data filter JSON file.", + default = None +) +flag_parser.add_argument( + "--include_uni_core_data", + help = "Include the full Unicode core data in the dat file.", + default = False, + action = "store_true" +) +flag_parser.add_argument( + "--seqmode", + help = "Whether to optimize rules to be run sequentially (fewer threads) or in parallel (many threads). Defaults to 'sequential', which is better for unix-exec and windows-exec modes. 'parallel' is often better for massively parallel build systems.", + choices = ["sequential", "parallel"], + default = "sequential" +) +flag_parser.add_argument( + "--verbose", + help = "Print more verbose output (default false).", + default = False, + action = "store_true" +) + +arg_group_exec = flag_parser.add_argument_group("arguments for unix-exec and windows-exec modes") +arg_group_exec.add_argument( + "--out_dir", + help = "Path to where to save output data files.", + default = "icudata" +) +arg_group_exec.add_argument( + "--tmp_dir", + help = "Path to where to save temporary files.", + default = "icutmp" +) +arg_group_exec.add_argument( + "--tool_dir", + help = "Path to where to find binary tools (genrb, etc).", + default = "../bin" +) +arg_group_exec.add_argument( + "--tool_cfg", + help = "The build configuration of the tools. Used in 'windows-exec' mode only.", + default = "x86/Debug" +) + + +class Config(object): + + def __init__(self, args): + # Process arguments + self.max_parallel = (args.seqmode == "parallel") + + # Boolean: Whether to include core Unicode data files in the .dat file + self.include_uni_core_data = args.include_uni_core_data + + # Default fields before processing filter file + self.filters_json_data = {} + self.filter_dir = "ERROR_NO_FILTER_FILE" + + # Process filter file + if args.filter_file: + try: + with open(args.filter_file, "r") as f: + print("Note: Applying filters from %s." % args.filter_file, file=sys.stderr) + self._parse_filter_file(f) + except IOError: + print("Error: Could not read filter file %s." % args.filter_file, file=sys.stderr) + exit(1) + self.filter_dir = os.path.abspath(os.path.dirname(args.filter_file)) + + # Either "unihan" or "implicithan" + self.coll_han_type = "unihan" + if "collationUCAData" in self.filters_json_data: + self.coll_han_type = self.filters_json_data["collationUCAData"] + + # Either "additive" or "subtractive" + self.strategy = "subtractive" + if "strategy" in self.filters_json_data: + self.strategy = self.filters_json_data["strategy"] + + # True or False (could be extended later to support enum/list) + self.use_pool_bundle = True + if "usePoolBundle" in self.filters_json_data: + self.use_pool_bundle = self.filters_json_data["usePoolBundle"] + + def _parse_filter_file(self, f): + # Use the Hjson parser if it is available; otherwise, use vanilla JSON. + try: + import hjson + self.filters_json_data = hjson.load(f) + except ImportError: + self.filters_json_data = json.load(CommentStripper(f)) + + # Optionally pre-validate the JSON schema before further processing. + # Some schema errors will be caught later, but this step ensures + # maximal validity. + try: + import jsonschema + schema_path = os.path.join(os.path.dirname(__file__), "filtration_schema.json") + with open(schema_path) as schema_f: + schema = json.load(CommentStripper(schema_f)) + validator = jsonschema.Draft4Validator(schema) + for error in validator.iter_errors(self.filters_json_data, schema): + print("WARNING: ICU data filter JSON file:", error.message, + "at", "".join( + "[%d]" % part if isinstance(part, int) else ".%s" % part + for part in error.absolute_path + ), + file=sys.stderr) + except ImportError: + print("Tip: to validate your filter file, install the Pip package 'jsonschema'", file=sys.stderr) + pass + + +def add_copy_input_requests(requests, config, common_vars): + files_to_copy = set() + for request in requests: + request_files = request.all_input_files() + # Also add known dependency txt files as possible inputs. + # This is required for translit rule files. + if hasattr(request, "dep_targets"): + request_files += [ + f for f in request.dep_targets if isinstance(f, InFile) + ] + for f in request_files: + if isinstance(f, InFile): + files_to_copy.add(f) + + result = [] + id = 0 + + json_data = config.filters_json_data["fileReplacements"] + dirname = json_data["directory"] + for directive in json_data["replacements"]: + if type(directive) == str: + input_file = LocalFile(dirname, directive) + output_file = InFile(directive) + else: + input_file = LocalFile(dirname, directive["src"]) + output_file = InFile(directive["dest"]) + result += [ + CopyRequest( + name = "input_copy_%d" % id, + input_file = input_file, + output_file = output_file + ) + ] + files_to_copy.remove(output_file) + id += 1 + + for f in files_to_copy: + result += [ + CopyRequest( + name = "input_copy_%d" % id, + input_file = SrcFile(f.filename), + output_file = f + ) + ] + id += 1 + + result += requests + return result + + +def main(argv): + args = flag_parser.parse_args(argv) + config = Config(args) + + if args.mode == "gnumake": + makefile_vars = { + "SRC_DIR": "$(srcdir)", + "IN_DIR": "$(srcdir)", + "INDEX_NAME": "res_index" + } + makefile_env = ["ICUDATA_CHAR", "OUT_DIR", "TMP_DIR"] + common = { + key: "$(%s)" % key + for key in list(makefile_vars.keys()) + makefile_env + } + common["GLOB_DIR"] = args.src_dir + common["FILTERS_DIR"] = config.filter_dir + common["CWD_DIR"] = os.getcwd() + else: + makefile_vars = None + common = { + # GLOB_DIR is used now, whereas IN_DIR is used during execution phase. + # There is no useful distinction in unix-exec or windows-exec mode. + "GLOB_DIR": args.src_dir, + "SRC_DIR": args.src_dir, + "IN_DIR": args.src_dir, + "OUT_DIR": args.out_dir, + "TMP_DIR": args.tmp_dir, + "FILTERS_DIR": config.filter_dir, + "CWD_DIR": os.getcwd(), + "INDEX_NAME": "res_index", + # TODO: Pull this from configure script: + "ICUDATA_CHAR": "l" + } + + def glob(pattern): + result_paths = pyglob.glob("{GLOB_DIR}/{PATTERN}".format( + GLOB_DIR = args.src_dir, + PATTERN = pattern + )) + # For the purposes of icutools.databuilder, force Unix-style directory separators. + return [v.replace("\\", "/")[len(args.src_dir)+1:] for v in sorted(result_paths)] + + # Automatically load BUILDRULES from the src_dir + sys.path.append(args.src_dir) + try: + import BUILDRULES + except ImportError: + print("Cannot find BUILDRULES! Did you set your --src_dir?", file=sys.stderr) + sys.exit(1) + + requests = BUILDRULES.generate(config, glob, common) + + if "fileReplacements" in config.filters_json_data: + tmp_in_dir = "{TMP_DIR}/in".format(**common) + if makefile_vars: + makefile_vars["IN_DIR"] = tmp_in_dir + else: + common["IN_DIR"] = tmp_in_dir + requests = add_copy_input_requests(requests, config, common) + + requests = filtration.apply_filters(requests, config) + requests = utils.flatten_requests(requests, config, common) + + build_dirs = utils.compute_directories(requests) + + if args.mode == "gnumake": + print(makefile.get_gnumake_rules( + build_dirs, + requests, + makefile_vars, + common_vars = common + )) + elif args.mode == "windows-exec": + return common_exec.run( + platform = "windows", + build_dirs = build_dirs, + requests = requests, + common_vars = common, + tool_dir = args.tool_dir, + tool_cfg = args.tool_cfg, + verbose = args.verbose, + ) + elif args.mode == "unix-exec": + return common_exec.run( + platform = "unix", + build_dirs = build_dirs, + requests = requests, + common_vars = common, + tool_dir = args.tool_dir, + verbose = args.verbose, + ) + elif args.mode == "bazel-exec": + return common_exec.run( + platform = "bazel", + build_dirs = build_dirs, + requests = requests, + common_vars = common, + tool_dir = args.tool_dir, + verbose = args.verbose, + ) + else: + print("Mode not supported: %s" % args.mode) + return 1 + return 0 + +if __name__ == "__main__": + exit(main(sys.argv[1:])) diff -Nru icu-64.2/source/python/icutools/databuilder/renderers/common_exec.py icu-65.1/source/python/icutools/databuilder/renderers/common_exec.py --- icu-64.2/source/python/icutools/databuilder/renderers/common_exec.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/renderers/common_exec.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,146 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +from . import * +from .. import * +from .. import utils +from ..request_types import * + +import os +import shutil +import subprocess +import sys + +def run(build_dirs, requests, common_vars, verbose=True, **kwargs): + for bd in build_dirs: + makedirs(bd.format(**common_vars)) + for request in requests: + status = run_helper(request, common_vars, verbose=verbose, **kwargs) + if status != 0: + print("!!! ERROR executing above command line: exit code %d" % status) + return 1 + if verbose: + print("All data build commands executed") + return 0 + +def makedirs(dirs): + """makedirs compatible between Python 2 and 3""" + try: + # Python 3 version + os.makedirs(dirs, exist_ok=True) + except TypeError as e: + # Python 2 version + try: + os.makedirs(dirs) + except OSError as e: + if e.errno != errno.EEXIST: + raise e + +def run_helper(request, common_vars, platform, tool_dir, verbose, tool_cfg=None, **kwargs): + if isinstance(request, PrintFileRequest): + output_path = "{DIRNAME}/{FILENAME}".format( + DIRNAME = utils.dir_for(request.output_file).format(**common_vars), + FILENAME = request.output_file.filename, + ) + if verbose: + print("Printing to file: %s" % output_path) + with open(output_path, "w") as f: + f.write(request.content) + return 0 + if isinstance(request, CopyRequest): + input_path = "{DIRNAME}/{FILENAME}".format( + DIRNAME = utils.dir_for(request.input_file).format(**common_vars), + FILENAME = request.input_file.filename, + ) + output_path = "{DIRNAME}/{FILENAME}".format( + DIRNAME = utils.dir_for(request.output_file).format(**common_vars), + FILENAME = request.output_file.filename, + ) + if verbose: + print("Copying file to: %s" % output_path) + shutil.copyfile(input_path, output_path) + return 0 + if isinstance(request, VariableRequest): + # No-op + return 0 + + assert isinstance(request.tool, IcuTool) + if platform == "windows": + cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL_CFG}/{TOOL}.exe {{ARGS}}".format( + TOOL_DIR = tool_dir, + TOOL_CFG = tool_cfg, + TOOL = request.tool.name, + **common_vars + ) + elif platform == "unix": + cmd_template = "{TOOL_DIR}/{TOOL} {{ARGS}}".format( + TOOL_DIR = tool_dir, + TOOL = request.tool.name, + **common_vars + ) + elif platform == "bazel": + cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL} {{ARGS}}".format( + TOOL_DIR = tool_dir, + TOOL = request.tool.name, + **common_vars + ) + else: + raise ValueError("Unknown platform: %s" % platform) + + if isinstance(request, RepeatedExecutionRequest): + for loop_vars in utils.repeated_execution_request_looper(request): + command_line = utils.format_repeated_request_command( + request, + cmd_template, + loop_vars, + common_vars + ) + if platform == "windows": + # Note: this / to \ substitution may be too aggressive? + command_line = command_line.replace("/", "\\") + returncode = run_shell_command(command_line, platform, verbose) + if returncode != 0: + return returncode + return 0 + if isinstance(request, SingleExecutionRequest): + command_line = utils.format_single_request_command( + request, + cmd_template, + common_vars + ) + if platform == "windows": + # Note: this / to \ substitution may be too aggressive? + command_line = command_line.replace("/", "\\") + returncode = run_shell_command(command_line, platform, verbose) + return returncode + assert False + +def run_shell_command(command_line, platform, verbose): + changed_windows_comspec = False + # If the command line length on Windows exceeds the absolute maximum that CMD supports (8191), then + # we temporarily switch over to use PowerShell for the command, and then switch back to CMD. + # We don't want to use PowerShell for everything though, as it tends to be slower. + if (platform == "windows") and (len(command_line) > 8190): + if verbose: + print("Command length exceeds the max length for CMD on Windows, using PowerShell instead.") + previous_comspec = os.environ["COMSPEC"] + os.environ["COMSPEC"] = 'powershell' + changed_windows_comspec = True + if verbose: + print("Running: %s" % command_line) + returncode = subprocess.call( + command_line, + shell = True + ) + else: + # Pipe output to /dev/null in quiet mode + with open(os.devnull, "w") as devnull: + returncode = subprocess.call( + command_line, + shell = True, + stdout = devnull, + stderr = devnull + ) + if changed_windows_comspec: + os.environ["COMSPEC"] = previous_comspec + return returncode diff -Nru icu-64.2/source/python/icutools/databuilder/renderers/__init__.py icu-65.1/source/python/icutools/databuilder/renderers/__init__.py --- icu-64.2/source/python/icutools/databuilder/renderers/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/renderers/__init__.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,10 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +from collections import namedtuple + +MakeRule = namedtuple("MakeRule", ["name", "dep_literals", "dep_files", "output_file", "cmds"]) + +MakeFilesVar = namedtuple("MakeFilesVar", ["name", "files"]) + +MakeStringVar = namedtuple("MakeStringVar", ["name", "content"]) diff -Nru icu-64.2/source/python/icutools/databuilder/renderers/makefile.py icu-65.1/source/python/icutools/databuilder/renderers/makefile.py --- icu-64.2/source/python/icutools/databuilder/renderers/makefile.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/renderers/makefile.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,245 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# Python 2/3 Compatibility (ICU-20299) +# TODO(ICU-20301): Remove this. +from __future__ import print_function + +from . import * +from .. import * +from .. import utils +from ..request_types import * + +def get_gnumake_rules(build_dirs, requests, makefile_vars, **kwargs): + makefile_string = "" + + # Common Variables + common_vars = kwargs["common_vars"] + for key, value in sorted(makefile_vars.items()): + makefile_string += "{KEY} = {VALUE}\n".format( + KEY = key, + VALUE = value + ) + makefile_string += "\n" + + # Directories + dirs_timestamp_file = "{TMP_DIR}/dirs.timestamp".format(**common_vars) + makefile_string += "DIRS = {TIMESTAMP_FILE}\n\n".format( + TIMESTAMP_FILE = dirs_timestamp_file + ) + makefile_string += "{TIMESTAMP_FILE}:\n\t$(MKINSTALLDIRS) {ALL_DIRS}\n\techo timestamp > {TIMESTAMP_FILE}\n\n".format( + TIMESTAMP_FILE = dirs_timestamp_file, + ALL_DIRS = " ".join(build_dirs).format(**common_vars) + ) + + # Generate Rules + make_rules = [] + for request in requests: + make_rules += get_gnumake_rules_helper(request, **kwargs) + + # Main Commands + for rule in make_rules: + if isinstance(rule, MakeFilesVar): + makefile_string += "{NAME} = {FILE_LIST}\n\n".format( + NAME = rule.name, + FILE_LIST = files_to_makefile(rule.files, wrap = True, **kwargs), + ) + continue + + if isinstance(rule, MakeStringVar): + makefile_string += "define {NAME}\n{CONTENT}\nendef\nexport {NAME}\n\n".format( + NAME = rule.name, + CONTENT = rule.content + ) + continue + + assert isinstance(rule, MakeRule) + header_line = "{OUT_FILE}: {DEP_FILES} {DEP_LITERALS} | $(DIRS)".format( + OUT_FILE = files_to_makefile([rule.output_file], **kwargs), + DEP_FILES = files_to_makefile(rule.dep_files, wrap = True, **kwargs), + DEP_LITERALS = " ".join(rule.dep_literals) + ) + + if len(rule.cmds) == 0: + makefile_string += "%s\n\n" % header_line + continue + + makefile_string += "{HEADER_LINE}\n{RULE_LINES}\n\n".format( + HEADER_LINE = header_line, + RULE_LINES = "\n".join("\t%s" % cmd for cmd in rule.cmds) + ) + + return makefile_string + +def files_to_makefile(files, common_vars, wrap = False, **kwargs): + if len(files) == 0: + return "" + dirnames = [utils.dir_for(file).format(**common_vars) for file in files] + join_str = " \\\n\t\t" if wrap and len(files) > 2 else " " + if len(files) == 1: + return "%s/%s" % (dirnames[0], files[0].filename) + elif len(set(dirnames)) == 1: + return "$(addprefix %s/,%s)" % (dirnames[0], join_str.join(file.filename for file in files)) + else: + return join_str.join("%s/%s" % (d, f.filename) for d,f in zip(dirnames, files)) + +def get_gnumake_rules_helper(request, common_vars, **kwargs): + + if isinstance(request, PrintFileRequest): + var_name = "%s_CONTENT" % request.name.upper() + return [ + MakeStringVar( + name = var_name, + content = request.content + ), + MakeRule( + name = request.name, + dep_literals = [], + dep_files = [], + output_file = request.output_file, + cmds = [ + "echo \"$${VAR_NAME}\" > {MAKEFILENAME}".format( + VAR_NAME = var_name, + MAKEFILENAME = files_to_makefile([request.output_file], common_vars), + **common_vars + ) + ] + ) + ] + + + if isinstance(request, CopyRequest): + return [ + MakeRule( + name = request.name, + dep_literals = [], + dep_files = [request.input_file], + output_file = request.output_file, + cmds = ["cp %s %s" % ( + files_to_makefile([request.input_file], common_vars), + files_to_makefile([request.output_file], common_vars)) + ] + ) + ] + + if isinstance(request, VariableRequest): + return [ + MakeFilesVar( + name = request.name.upper(), + files = request.input_files + ) + ] + + if request.tool.name == "make": + cmd_template = "$(MAKE) {ARGS}" + elif request.tool.name == "gentest": + cmd_template = "$(INVOKE) $(GENTEST) {ARGS}" + else: + assert isinstance(request.tool, IcuTool) + cmd_template = "$(INVOKE) $(TOOLBINDIR)/{TOOL} {{ARGS}}".format( + TOOL = request.tool.name + ) + + if isinstance(request, SingleExecutionRequest): + cmd = utils.format_single_request_command(request, cmd_template, common_vars) + dep_files = request.all_input_files() + + if len(request.output_files) > 1: + # Special case for multiple output files: Makefile rules should have only one + # output file apiece. More information: + # https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html + timestamp_var_name = "%s_ALL" % request.name.upper() + timestamp_file = TmpFile("%s.timestamp" % request.name) + rules = [ + MakeFilesVar( + name = timestamp_var_name, + files = [timestamp_file] + ), + MakeRule( + name = "%s_all" % request.name, + dep_literals = [], + dep_files = dep_files, + output_file = timestamp_file, + cmds = [ + cmd, + "echo timestamp > {MAKEFILENAME}".format( + MAKEFILENAME = files_to_makefile([timestamp_file], common_vars) + ) + ] + ) + ] + for i, file in enumerate(request.output_files): + rules += [ + MakeRule( + name = "%s_%d" % (request.name, i), + dep_literals = ["$(%s)" % timestamp_var_name], + dep_files = [], + output_file = file, + cmds = [] + ) + ] + return rules + + elif len(dep_files) > 5: + # For nicer printing, for long input lists, use a helper variable. + dep_var_name = "%s_DEPS" % request.name.upper() + return [ + MakeFilesVar( + name = dep_var_name, + files = dep_files + ), + MakeRule( + name = request.name, + dep_literals = ["$(%s)" % dep_var_name], + dep_files = [], + output_file = request.output_files[0], + cmds = [cmd] + ) + ] + + else: + return [ + MakeRule( + name = request.name, + dep_literals = [], + dep_files = dep_files, + output_file = request.output_files[0], + cmds = [cmd] + ) + ] + + if isinstance(request, RepeatedExecutionRequest): + rules = [] + dep_literals = [] + # To keep from repeating the same dep files many times, make a variable. + if len(request.common_dep_files) > 0: + dep_var_name = "%s_DEPS" % request.name.upper() + dep_literals = ["$(%s)" % dep_var_name] + rules += [ + MakeFilesVar( + name = dep_var_name, + files = request.common_dep_files + ) + ] + # Add a rule for each individual file. + for loop_vars in utils.repeated_execution_request_looper(request): + (_, specific_dep_files, input_file, output_file) = loop_vars + name_suffix = input_file[input_file.filename.rfind("/")+1:input_file.filename.rfind(".")] + cmd = utils.format_repeated_request_command( + request, + cmd_template, + loop_vars, + common_vars + ) + rules += [ + MakeRule( + name = "%s_%s" % (request.name, name_suffix), + dep_literals = dep_literals, + dep_files = specific_dep_files + [input_file], + output_file = output_file, + cmds = [cmd] + ) + ] + return rules + + assert False diff -Nru icu-64.2/source/python/icutools/databuilder/request_types.py icu-65.1/source/python/icutools/databuilder/request_types.py --- icu-64.2/source/python/icutools/databuilder/request_types.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/request_types.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,364 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# Python 2/3 Compatibility (ICU-20299) +# TODO(ICU-20301): Remove this. +from __future__ import print_function + +from abc import abstractmethod +import copy +import sys + +from . import * +from . import utils + + +# TODO(ICU-20301): Remove arguments from all instances of super() in this file + +# Note: for this to be a proper abstract class, it should extend abc.ABC. +# There is no nice way to do this that works in both Python 2 and 3. +# TODO(ICU-20301): Make this inherit from abc.ABC. +class AbstractRequest(object): + def __init__(self, **kwargs): + + # Used for identification purposes + self.name = None + + # The filter category that applies to this request + self.category = None + + self._set_fields(kwargs) + + def _set_fields(self, kwargs): + for key, value in list(kwargs.items()): + if hasattr(self, key): + if isinstance(value, list): + value = copy.copy(value) + elif isinstance(value, dict): + value = copy.deepcopy(value) + setattr(self, key, value) + else: + raise ValueError("Unknown argument: %s" % key) + + def apply_file_filter(self, filter): + """ + Returns True if this request still has input files after filtering, + or False if the request is "empty" after filtering. + """ + return True + + def flatten(self, config, all_requests, common_vars): + return [self] + + def all_input_files(self): + return [] + + def all_output_files(self): + return [] + + +class AbstractExecutionRequest(AbstractRequest): + def __init__(self, **kwargs): + + # Names of targets (requests) or files that this request depends on. + # The entries of dep_targets may be any of the following types: + # + # 1. DepTarget, for the output of an execution request. + # 2. InFile, TmpFile, etc., for a specific file. + # 3. A list of InFile, TmpFile, etc., where the list is the same + # length as self.input_files and self.output_files. + # + # In cases 1 and 2, the dependency is added to all rules that the + # request generates. In case 3, the dependency is added only to the + # rule that generates the output file at the same array index. + self.dep_targets = [] + + # Computed during self.flatten(); don't edit directly. + self.common_dep_files = [] + + # Primary input files + self.input_files = [] + + # Output files; for some subclasses, this must be the same length + # as input_files + self.output_files = [] + + # What tool to execute + self.tool = None + + # Argument string to pass to the tool with optional placeholders + self.args = "" + + # Placeholders to substitute into the argument string; if any of these + # have a list type, the list must be equal in length to input_files + self.format_with = {} + + super(AbstractExecutionRequest, self).__init__(**kwargs) + + def apply_file_filter(self, filter): + i = 0 + while i < len(self.input_files): + if filter.match(self.input_files[i]): + i += 1 + else: + self._del_at(i) + return i > 0 + + def _del_at(self, i): + del self.input_files[i] + for _, v in self.format_with.items(): + if isinstance(v, list): + assert len(v) == len(self.input_files) + 1 + del v[i] + for v in self.dep_targets: + if isinstance(v, list): + assert len(v) == len(self.input_files) + 1 + del v[i] + + def flatten(self, config, all_requests, common_vars): + self._dep_targets_to_files(all_requests) + return super(AbstractExecutionRequest, self).flatten(config, all_requests, common_vars) + + def _dep_targets_to_files(self, all_requests): + if not self.dep_targets: + return + for dep_target in self.dep_targets: + if isinstance(dep_target, list): + if hasattr(self, "specific_dep_files"): + assert len(dep_target) == len(self.specific_dep_files) + for file, out_list in zip(dep_target, self.specific_dep_files): + assert hasattr(file, "filename") + out_list.append(file) + else: + self.common_dep_files += dep_target + continue + if not isinstance(dep_target, DepTarget): + # Copy file entries directly to dep_files. + assert hasattr(dep_target, "filename") + self.common_dep_files.append(dep_target) + continue + # For DepTarget entries, search for the target. + for request in all_requests: + if request.name == dep_target.name: + self.common_dep_files += request.all_output_files() + break + else: + print("Warning: Unable to find target %s, a dependency of %s" % ( + dep_target.name, + self.name + ), file=sys.stderr) + self.dep_targets = [] + + def all_input_files(self): + return self.common_dep_files + self.input_files + + def all_output_files(self): + return self.output_files + + +class SingleExecutionRequest(AbstractExecutionRequest): + def __init__(self, **kwargs): + super(SingleExecutionRequest, self).__init__(**kwargs) + + +class RepeatedExecutionRequest(AbstractExecutionRequest): + def __init__(self, **kwargs): + + # Placeholders to substitute into the argument string unique to each + # iteration; all values must be lists equal in length to input_files + self.repeat_with = {} + + # Lists for dep files that are specific to individual resource bundle files + self.specific_dep_files = [[] for _ in range(len(kwargs["input_files"]))] + + super(RepeatedExecutionRequest, self).__init__(**kwargs) + + def _del_at(self, i): + super(RepeatedExecutionRequest, self)._del_at(i) + del self.output_files[i] + del self.specific_dep_files[i] + for _, v in self.repeat_with.items(): + if isinstance(v, list): + del v[i] + + def all_input_files(self): + files = super(RepeatedExecutionRequest, self).all_input_files() + for specific_file_list in self.specific_dep_files: + files += specific_file_list + return files + + +class RepeatedOrSingleExecutionRequest(AbstractExecutionRequest): + def __init__(self, **kwargs): + self.repeat_with = {} + super(RepeatedOrSingleExecutionRequest, self).__init__(**kwargs) + + def flatten(self, config, all_requests, common_vars): + if config.max_parallel: + new_request = RepeatedExecutionRequest( + name = self.name, + category = self.category, + dep_targets = self.dep_targets, + input_files = self.input_files, + output_files = self.output_files, + tool = self.tool, + args = self.args, + format_with = self.format_with, + repeat_with = self.repeat_with + ) + else: + new_request = SingleExecutionRequest( + name = self.name, + category = self.category, + dep_targets = self.dep_targets, + input_files = self.input_files, + output_files = self.output_files, + tool = self.tool, + args = self.args, + format_with = utils.concat_dicts(self.format_with, self.repeat_with) + ) + return new_request.flatten(config, all_requests, common_vars) + + def _del_at(self, i): + super(RepeatedOrSingleExecutionRequest, self)._del_at(i) + del self.output_files[i] + for _, v in self.repeat_with.items(): + if isinstance(v, list): + del v[i] + + +class PrintFileRequest(AbstractRequest): + def __init__(self, **kwargs): + self.output_file = None + self.content = None + super(PrintFileRequest, self).__init__(**kwargs) + + def all_output_files(self): + return [self.output_file] + + +class CopyRequest(AbstractRequest): + def __init__(self, **kwargs): + self.input_file = None + self.output_file = None + super(CopyRequest, self).__init__(**kwargs) + + def all_input_files(self): + return [self.input_file] + + def all_output_files(self): + return [self.output_file] + + +class VariableRequest(AbstractRequest): + def __init__(self, **kwargs): + self.input_files = [] + super(VariableRequest, self).__init__(**kwargs) + + def all_input_files(self): + return self.input_files + + +class ListRequest(AbstractRequest): + def __init__(self, **kwargs): + self.variable_name = None + self.output_file = None + self.include_tmp = None + super(ListRequest, self).__init__(**kwargs) + + def flatten(self, config, all_requests, common_vars): + list_files = list(sorted(utils.get_all_output_files(all_requests))) + if self.include_tmp: + variable_files = list(sorted(utils.get_all_output_files(all_requests, include_tmp=True))) + else: + # Always include the list file itself + variable_files = list_files + [self.output_file] + return PrintFileRequest( + name = self.name, + output_file = self.output_file, + content = "\n".join(file.filename for file in list_files) + ).flatten(config, all_requests, common_vars) + VariableRequest( + name = self.variable_name, + input_files = variable_files + ).flatten(config, all_requests, common_vars) + + def all_output_files(self): + return [self.output_file] + + +class IndexRequest(AbstractRequest): + def __init__(self, **kwargs): + self.installed_files = [] + self.alias_files = [] + self.txt_file = None + self.output_file = None + self.cldr_version = "" + self.args = "" + self.format_with = {} + super(IndexRequest, self).__init__(**kwargs) + + def apply_file_filter(self, filter): + i = 0 + while i < len(self.installed_files): + if filter.match(self.installed_files[i]): + i += 1 + else: + del self.installed_files[i] + j = 0 + while j < len(self.alias_files): + if filter.match(self.alias_files[j]): + j += 1 + else: + del self.alias_files[j] + return i + j > 0 + + def flatten(self, config, all_requests, common_vars): + return ( + PrintFileRequest( + name = self.name, + output_file = self.txt_file, + content = self._generate_index_file(common_vars) + ).flatten(config, all_requests, common_vars) + + SingleExecutionRequest( + name = "%s_res" % self.name, + category = self.category, + input_files = [self.txt_file], + output_files = [self.output_file], + tool = IcuTool("genrb"), + args = self.args, + format_with = self.format_with + ).flatten(config, all_requests, common_vars) + ) + + def _generate_index_file(self, common_vars): + installed_locales = [IndexRequest.locale_file_stem(f) for f in self.installed_files] + alias_locales = [IndexRequest.locale_file_stem(f) for f in self.alias_files] + formatted_version = " CLDRVersion { \"%s\" }\n" % self.cldr_version if self.cldr_version else "" + formatted_installed_locales = "\n".join([" %s {\"\"}" % v for v in installed_locales]) + formatted_alias_locales = "\n".join([" %s {\"\"}" % v for v in alias_locales]) + # TODO: CLDRVersion is required only in the base file + return ("// Warning this file is automatically generated\n" + "{INDEX_NAME}:table(nofallback) {{\n" + "{FORMATTED_VERSION}" + " InstalledLocales:table {{\n" + "{FORMATTED_INSTALLED_LOCALES}\n" + " }}\n" + " AliasLocales:table {{\n" + "{FORMATTED_ALIAS_LOCALES}\n" + " }}\n" + "}}").format( + FORMATTED_VERSION = formatted_version, + FORMATTED_INSTALLED_LOCALES = formatted_installed_locales, + FORMATTED_ALIAS_LOCALES = formatted_alias_locales, + **common_vars + ) + + def all_input_files(self): + return self.installed_files + self.alias_files + + def all_output_files(self): + return [self.output_file] + + @staticmethod + def locale_file_stem(f): + return f.filename[f.filename.rfind("/")+1:-4] diff -Nru icu-64.2/source/python/icutools/databuilder/test/filtration_test.py icu-65.1/source/python/icutools/databuilder/test/filtration_test.py --- icu-64.2/source/python/icutools/databuilder/test/filtration_test.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/test/filtration_test.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,353 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +import unittest + +from .. import InFile +from ..filtration import Filter + +EXAMPLE_FILE_STEMS = [ + "af_NA", + "af_ZA", + "af", + "ar", + "ar_SA", + "ars", + "bs_BA", + "bs_Cyrl_BA", + "bs_Cyrl", + "bs_Latn_BA", + "bs_Latn", + "bs", + "en_001", + "en_150", + "en_DE", + "en_GB", + "en_US", + "root", + "sr_BA", + "sr_CS", + "sr_Cyrl_BA", + "sr_Cyrl_CS", + "sr_Cyrl_ME", + "sr_Cyrl", + "sr_Latn_BA", + "sr_Latn_CS", + "sr_Latn_ME", + "sr_Latn", + "sr_ME", + "sr", + "vai_Latn_LR", + "vai_Latn", + "vai_LR", + "vai_Vaii_LR", + "vai_Vaii", + "vai", + "zh_CN", + "zh_Hans_CN", + "zh_Hans_HK", + "zh_Hans_MO", + "zh_Hans_SG", + "zh_Hans", + "zh_Hant_HK", + "zh_Hant_MO", + "zh_Hant_TW", + "zh_Hant", + "zh_HK", + "zh_MO", + "zh_SG", + "zh_TW", + "zh" +] + +class FiltrationTest(unittest.TestCase): + + def test_exclude(self): + self._check_filter(Filter.create_from_json({ + "filterType": "exclude" + }), [ + ]) + + def test_default_whitelist(self): + self._check_filter(Filter.create_from_json({ + "whitelist": [ + "ars", + "zh_Hans" + ] + }), [ + "ars", + "zh_Hans" + ]) + + def test_default_blacklist(self): + expected_matches = set(EXAMPLE_FILE_STEMS) + expected_matches.remove("ars") + expected_matches.remove("zh_Hans") + self._check_filter(Filter.create_from_json({ + "blacklist": [ + "ars", + "zh_Hans" + ] + }), expected_matches) + + def test_language_whitelist(self): + self._check_filter(Filter.create_from_json({ + "filterType": "language", + "whitelist": [ + "af", + "bs" + ] + }), [ + "root", + "af_NA", + "af_ZA", + "af", + "bs_BA", + "bs_Cyrl_BA", + "bs_Cyrl", + "bs_Latn_BA", + "bs_Latn", + "bs" + ]) + + def test_language_blacklist(self): + expected_matches = set(EXAMPLE_FILE_STEMS) + expected_matches.remove("af_NA") + expected_matches.remove("af_ZA") + expected_matches.remove("af") + self._check_filter(Filter.create_from_json({ + "filterType": "language", + "blacklist": [ + "af" + ] + }), expected_matches) + + def test_regex_whitelist(self): + self._check_filter(Filter.create_from_json({ + "filterType": "regex", + "whitelist": [ + r"^ar.*$", + r"^zh$" + ] + }), [ + "ar", + "ar_SA", + "ars", + "zh" + ]) + + def test_regex_blacklist(self): + expected_matches = set(EXAMPLE_FILE_STEMS) + expected_matches.remove("ar") + expected_matches.remove("ar_SA") + expected_matches.remove("ars") + expected_matches.remove("zh") + self._check_filter(Filter.create_from_json({ + "filterType": "regex", + "blacklist": [ + r"^ar.*$", + r"^zh$" + ] + }), expected_matches) + + def test_locale_basic(self): + self._check_filter(Filter.create_from_json({ + "filterType": "locale", + "whitelist": [ + # Default scripts: + # sr => Cyrl + # vai => Vaii + # zh => Hans + "bs_BA", # is an alias to bs_Latn_BA + "en_DE", + "sr", # Language with no script + "vai_Latn", # Language with non-default script + "zh_Hans" # Language with default script + ] + }), [ + "root", + # bs: should include the full dependency tree of bs_BA + "bs_BA", + "bs_Latn_BA", + "bs_Latn", + "bs", + # en: should include the full dependency tree of en_DE + "en", + "en_DE", + "en_150", + "en_001", + # sr: include Cyrl, the default, but not Latn. + "sr", + "sr_BA", + "sr_CS", + "sr_Cyrl", + "sr_Cyrl_BA", + "sr_Cyrl_CS", + "sr_Cyrl_ME", + # vai: include Latn but NOT Vaii. + "vai_Latn", + "vai_Latn_LR", + # zh: include Hans but NOT Hant. + "zh", + "zh_CN", + "zh_SG", + "zh_Hans", + "zh_Hans_CN", + "zh_Hans_HK", + "zh_Hans_MO", + "zh_Hans_SG" + ]) + + def test_locale_no_children(self): + self._check_filter(Filter.create_from_json({ + "filterType": "locale", + "includeChildren": False, + "whitelist": [ + # See comments in test_locale_basic. + "bs_BA", + "en_DE", + "sr", + "vai_Latn", + "zh_Hans" + ] + }), [ + "root", + "bs_BA", + "bs_Latn_BA", + "bs_Latn", + "bs", + "en", + "en_DE", + "en_150", + "en_001", + "sr", + "vai_Latn", + "zh", + "zh_Hans", + ]) + + def test_locale_include_scripts(self): + self._check_filter(Filter.create_from_json({ + "filterType": "locale", + "includeScripts": True, + "whitelist": [ + # See comments in test_locale_basic. + "bs_BA", + "en_DE", + "sr", + "vai_Latn", + "zh_Hans" + ] + }), [ + "root", + # bs: includeScripts only works for language-only (without region) + "bs_BA", + "bs_Latn_BA", + "bs_Latn", + "bs", + # en: should include the full dependency tree of en_DE + "en", + "en_DE", + "en_150", + "en_001", + # sr: include Latn, since no particular script was requested. + "sr_BA", + "sr_CS", + "sr_Cyrl_BA", + "sr_Cyrl_CS", + "sr_Cyrl_ME", + "sr_Cyrl", + "sr_Latn_BA", + "sr_Latn_CS", + "sr_Latn_ME", + "sr_Latn", + "sr_ME", + "sr", + # vai: do NOT include Vaii; the script was explicitly requested. + "vai_Latn_LR", + "vai_Latn", + # zh: do NOT include Hant; the script was explicitly requested. + "zh_CN", + "zh_SG", + "zh_Hans_CN", + "zh_Hans_HK", + "zh_Hans_MO", + "zh_Hans_SG", + "zh_Hans", + "zh" + ]) + + def test_locale_no_children_include_scripts(self): + self._check_filter(Filter.create_from_json({ + "filterType": "locale", + "includeChildren": False, + "includeScripts": True, + "whitelist": [ + # See comments in test_locale_basic. + "bs_BA", + "en_DE", + "sr", + "vai_Latn", + "zh_Hans" + ] + }), [ + "root", + # bs: includeScripts only works for language-only (without region) + "bs_BA", + "bs_Latn_BA", + "bs_Latn", + "bs", + # en: should include the full dependency tree of en_DE + "en", + "en_DE", + "en_150", + "en_001", + # sr: include Cyrl and Latn but no other children + "sr", + "sr_Cyrl", + "sr_Latn", + # vai: include only the requested script + "vai_Latn", + # zh: include only the requested script + "zh", + "zh_Hans", + ]) + + def test_union(self): + self._check_filter(Filter.create_from_json({ + "filterType": "union", + "unionOf": [ + { + "whitelist": [ + "ars", + "zh_Hans" + ] + }, + { + "filterType": "regex", + "whitelist": [ + r"^bs.*$", + r"^zh$" + ] + } + ] + }), [ + "ars", + "zh_Hans", + "bs_BA", + "bs_Cyrl_BA", + "bs_Cyrl", + "bs_Latn_BA", + "bs_Latn", + "bs", + "zh" + ]) + + def _check_filter(self, filter, expected_matches): + for file_stem in EXAMPLE_FILE_STEMS: + is_match = filter.match(InFile("locales/%s.txt" % file_stem)) + expected_match = file_stem in expected_matches + self.assertEqual(is_match, expected_match, file_stem) + +# Export the test for the runner +suite = unittest.makeSuite(FiltrationTest) diff -Nru icu-64.2/source/python/icutools/databuilder/test/__init__.py icu-65.1/source/python/icutools/databuilder/test/__init__.py --- icu-64.2/source/python/icutools/databuilder/test/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/test/__init__.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,2 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html diff -Nru icu-64.2/source/python/icutools/databuilder/test/__main__.py icu-65.1/source/python/icutools/databuilder/test/__main__.py --- icu-64.2/source/python/icutools/databuilder/test/__main__.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/test/__main__.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,14 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +import unittest + +from . import filtration_test + +def load_tests(loader, tests, pattern): + suite = unittest.TestSuite() + suite.addTest(filtration_test.suite) + return suite + +if __name__ == '__main__': + unittest.main() diff -Nru icu-64.2/source/python/icutools/databuilder/utils.py icu-65.1/source/python/icutools/databuilder/utils.py --- icu-64.2/source/python/icutools/databuilder/utils.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/databuilder/utils.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,130 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# Python 2/3 Compatibility (ICU-20299) +# TODO(ICU-20301): Remove this. +from __future__ import print_function + +import sys + +from . import * + + +def dir_for(file): + if isinstance(file, LocalFile): + return get_local_dirname(file.dirname) + if isinstance(file, SrcFile): + return "{SRC_DIR}" + if isinstance(file, InFile): + return "{IN_DIR}" + if isinstance(file, TmpFile): + return "{TMP_DIR}" + if isinstance(file, OutFile): + return "{OUT_DIR}" + if isinstance(file, PkgFile): + return "{PKG_DIR}" + assert False + + +LOCAL_DIRNAME_SUBSTITUTIONS = { + "SRC": "{SRC_DIR}", + "FILTERS": "{FILTERS_DIR}", + "CWD": "{CWD_DIR}" +} + + +def get_local_dirname(dirname): + if dirname.startswith("/"): + return dirname + elif dirname.startswith("$"): + # Note: directory separator substitution happens later + sep_idx = dirname.find("/") + if sep_idx == -1: + sep_idx = len(dirname) + variable = dirname[1:sep_idx] + if variable in LOCAL_DIRNAME_SUBSTITUTIONS: + return LOCAL_DIRNAME_SUBSTITUTIONS[variable] + dirname[sep_idx:] + print( + "Error: Local directory must be absolute, or relative to one of: " + + (", ".join("$%s" % v for v in LOCAL_DIRNAME_SUBSTITUTIONS.keys())), + file=sys.stderr + ) + exit(1) + + +def concat_dicts(*dicts): + # There is not a super great way to do this in Python: + new_dict = {} + for dict in dicts: + new_dict.update(dict) + return new_dict + + +def repeated_execution_request_looper(request): + # dictionary of lists to list of dictionaries: + ld = [ + dict(zip(request.repeat_with, t)) + for t in zip(*request.repeat_with.values()) + ] + if not ld: + # No special options given in repeat_with + ld = [{} for _ in range(len(request.input_files))] + return zip(ld, request.specific_dep_files, request.input_files, request.output_files) + + +def format_single_request_command(request, cmd_template, common_vars): + return cmd_template.format( + ARGS = request.args.format( + INPUT_FILES = [file.filename for file in request.input_files], + OUTPUT_FILES = [file.filename for file in request.output_files], + **concat_dicts(common_vars, request.format_with) + ) + ) + + +def format_repeated_request_command(request, cmd_template, loop_vars, common_vars): + (iter_vars, _, input_file, output_file) = loop_vars + return cmd_template.format( + ARGS = request.args.format( + INPUT_FILE = input_file.filename, + OUTPUT_FILE = output_file.filename, + **concat_dicts(common_vars, request.format_with, iter_vars) + ) + ) + + +def flatten_requests(requests, config, common_vars): + result = [] + for request in requests: + result += request.flatten(config, requests, common_vars) + return result + + +def get_all_output_files(requests, include_tmp=False): + files = [] + for request in requests: + files += request.all_output_files() + + # Filter out all files but those in OUT_DIR if necessary. + # It is also easy to filter for uniqueness; do it right now and return. + if not include_tmp: + files = (file for file in files if isinstance(file, OutFile)) + return list(set(files)) + + # Filter for unique values. NOTE: Cannot use set() because we need to accept same filename as + # OutFile and TmpFile as different, and by default they evaluate as equal. + return [f for _, f in set((type(f), f) for f in files)] + + +def compute_directories(requests): + dirs = set() + for file in get_all_output_files(requests, include_tmp=True): + path = "%s/%s" % (dir_for(file), file.filename) + dirs.add(path[:path.rfind("/")]) + return list(sorted(dirs)) + + +class SpaceSeparatedList(list): + """A list that joins itself with spaces when converted to a string.""" + def __str__(self): + return " ".join(self) diff -Nru icu-64.2/source/python/icutools/__init__.py icu-65.1/source/python/icutools/__init__.py --- icu-64.2/source/python/icutools/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/python/icutools/__init__.py 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,4 @@ +# Copyright (C) 2018 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# This is the root ICU namespace for build tools. diff -Nru icu-64.2/source/samples/break/break.vcxproj icu-65.1/source/samples/break/break.vcxproj --- icu-64.2/source/samples/break/break.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/break/break.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -75,7 +75,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/break.pdb Console - false @@ -102,7 +101,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/break.pdb Console - false @@ -130,7 +128,6 @@ true .\x86\Debug/break.pdb Console - false @@ -158,7 +155,6 @@ true .\x64\Debug/break.pdb Console - false diff -Nru icu-64.2/source/samples/cal/cal.c icu-65.1/source/samples/cal/cal.c --- icu-64.2/source/samples/cal/cal.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/cal/cal.c 2019-10-03 11:16:41.000000000 +0000 @@ -697,7 +697,7 @@ if(left_current == 0) { break; } - }; + } /* If the current day isn't 0, indent to make up for missing days at the end of the month */ @@ -745,7 +745,7 @@ break; } - }; + } /* Output a newline */ putc('\n', stdout); diff -Nru icu-64.2/source/samples/cal/cal.vcxproj icu-65.1/source/samples/cal/cal.vcxproj --- icu-64.2/source/samples/cal/cal.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/cal/cal.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -76,7 +76,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\x86\Release/cal.pdb Console - false @@ -103,7 +102,6 @@ ../../../lib64;%(AdditionalLibraryDirectories) .\x64\Release/cal.pdb Console - false @@ -132,7 +130,6 @@ true .\x86\Debug/cal.pdb Console - false @@ -160,7 +157,6 @@ true .\x64\Debug/cal.pdb Console - false diff -Nru icu-64.2/source/samples/case/case.vcxproj icu-65.1/source/samples/case/case.vcxproj --- icu-64.2/source/samples/case/case.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/case/case.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -59,7 +59,7 @@ .\x86\Debug/case.tlb - MultiThreadedDebug + MultiThreadedDebugDLL .\x86\Debug/case.pch @@ -75,7 +75,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Debug/case.pdb Console - false @@ -85,7 +84,7 @@ .\x64\Debug/case.tlb - MultiThreadedDebug + MultiThreadedDebugDLL .\x64\Debug/case.pch @@ -103,7 +102,6 @@ true .\x64\Debug/case.pdb Console - false @@ -114,7 +112,7 @@ OnlyExplicitInline - MultiThreaded + MultiThreadedDLL true @@ -130,7 +128,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/case.pdb Console - false @@ -141,7 +138,7 @@ OnlyExplicitInline - MultiThreaded + MultiThreadedDLL true @@ -157,7 +154,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/case.pdb Console - false diff -Nru icu-64.2/source/samples/citer/citer.cpp icu-65.1/source/samples/citer/citer.cpp --- icu-64.2/source/samples/citer/citer.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/citer/citer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -59,7 +59,7 @@ const UChar *testText = testString.getTerminatedBuffer(); UCharCharacterIterator iter(testText, u_strlen(testText)); - UCharCharacterIterator* test2 = (UCharCharacterIterator*)iter.clone(); + UCharCharacterIterator* test2 = iter.clone(); u_fprintf(out, "testText = %s", testChars); @@ -126,7 +126,7 @@ const UChar *testText = testString.getTerminatedBuffer(); StringCharacterIterator iter(testText, u_strlen(testText)); - StringCharacterIterator* test2 = (StringCharacterIterator*)iter.clone(); + StringCharacterIterator* test2 = iter.clone(); if (iter != *test2 ) { u_fprintf(out, "clone() or equals() failed: Two clones tested unequal\n"); diff -Nru icu-64.2/source/samples/citer/citer.vcxproj icu-65.1/source/samples/citer/citer.vcxproj --- icu-64.2/source/samples/citer/citer.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/citer/citer.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -63,7 +63,6 @@ true $(OutDir)citer.pdb Console - false @@ -85,7 +84,6 @@ true $(OutDir)citer.pdb Console - false @@ -106,7 +104,6 @@ true Console true - false @@ -127,7 +124,6 @@ true Console true - false diff -Nru icu-64.2/source/samples/coll/coll.vcxproj icu-65.1/source/samples/coll/coll.vcxproj --- icu-64.2/source/samples/coll/coll.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/coll/coll.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -70,7 +70,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/coll.pdb Console - false @@ -99,7 +98,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/coll.pdb Console - false @@ -130,7 +128,6 @@ true .\x86\Debug/coll.pdb Console - false @@ -161,7 +158,6 @@ true .\x64\Debug/coll.pdb Console - false diff -Nru icu-64.2/source/samples/csdet/csdet.vcxproj icu-65.1/source/samples/csdet/csdet.vcxproj --- icu-64.2/source/samples/csdet/csdet.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/csdet/csdet.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -65,7 +65,6 @@ true $(OutDir)csdet.pdb Console - false @@ -92,7 +91,6 @@ true $(OutDir)csdet.pdb Console - false @@ -113,7 +111,6 @@ true Console true - false @@ -134,7 +131,6 @@ true Console true - false diff -Nru icu-64.2/source/samples/date/date.vcxproj icu-65.1/source/samples/date/date.vcxproj --- icu-64.2/source/samples/date/date.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/date/date.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -70,7 +70,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\x86\Release/date.pdb Console - false @@ -98,7 +97,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/date.pdb Console - false @@ -128,7 +126,6 @@ true .\x86\Debug/date.pdb Console - false @@ -156,7 +153,6 @@ true .\x64\Debug/date.pdb Console - false diff -Nru icu-64.2/source/samples/datefmt/datefmt.vcxproj icu-65.1/source/samples/datefmt/datefmt.vcxproj --- icu-64.2/source/samples/datefmt/datefmt.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/datefmt/datefmt.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -70,7 +70,6 @@ true .\x86\Debug/datefmt.pdb Console - false @@ -99,7 +98,6 @@ true .\x64\Debug/datefmt.pdb Console - false @@ -128,7 +126,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/datefmt.pdb Console - false @@ -157,7 +154,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/datefmt.pdb Console - false diff -Nru icu-64.2/source/samples/layout/layout.vcxproj icu-65.1/source/samples/layout/layout.vcxproj --- icu-64.2/source/samples/layout/layout.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/layout/layout.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -78,7 +78,6 @@ true .\x86\Release/layout.pdb Windows - false @@ -116,7 +115,6 @@ true .\x64\Release/layout.pdb Windows - false MachineX64 @@ -155,7 +153,6 @@ true .\x86\Debug/layout.pdb Windows - false @@ -194,7 +191,6 @@ true .\x64\Debug/layout.pdb Windows - false MachineX64 diff -Nru icu-64.2/source/samples/legacy/legacy.vcxproj icu-65.1/source/samples/legacy/legacy.vcxproj --- icu-64.2/source/samples/legacy/legacy.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/legacy/legacy.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -115,7 +115,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\x86\Release/legacy.pdb Console - false @@ -154,7 +153,6 @@ ../../../lib64;%(AdditionalLibraryDirectories) .\x64\Release/legacy.pdb Console - false MachineX64 @@ -194,7 +192,6 @@ true .\x86\Debug/legacy.pdb Console - false @@ -234,7 +231,6 @@ true .\x64\Debug/legacy.pdb Console - false MachineX64 diff -Nru icu-64.2/source/samples/msgfmt/msgfmt.vcxproj icu-65.1/source/samples/msgfmt/msgfmt.vcxproj --- icu-64.2/source/samples/msgfmt/msgfmt.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/msgfmt/msgfmt.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -71,7 +71,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/msgfmt.pdb Console - false @@ -100,7 +99,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/msgfmt.pdb Console - false @@ -130,7 +128,6 @@ true .\x86\Debug/msgfmt.pdb Console - false @@ -160,7 +157,6 @@ true .\x64\Debug/msgfmt.pdb Console - false diff -Nru icu-64.2/source/samples/numfmt/numfmt.vcxproj icu-65.1/source/samples/numfmt/numfmt.vcxproj --- icu-64.2/source/samples/numfmt/numfmt.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/numfmt/numfmt.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -70,7 +70,6 @@ true .\x86\Debug/numfmt.pdb Console - false @@ -103,7 +102,6 @@ true .\x64\Debug/numfmt.pdb Console - false @@ -132,7 +130,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\x86\Release/numfmt.pdb Console - false @@ -161,7 +158,6 @@ ../../../lib64;%(AdditionalLibraryDirectories) .\x64\Release/numfmt.pdb Console - false diff -Nru icu-64.2/source/samples/props/props.vcxproj icu-65.1/source/samples/props/props.vcxproj --- icu-64.2/source/samples/props/props.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/props/props.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -74,7 +74,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/props.pdb Console - false @@ -108,7 +107,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/props.pdb Console - false @@ -143,7 +141,6 @@ true .\x86\Debug/props.pdb Console - false @@ -178,7 +175,6 @@ true .\x64\Debug/props.pdb Console - false diff -Nru icu-64.2/source/samples/strsrch/strsrch.vcxproj icu-65.1/source/samples/strsrch/strsrch.vcxproj --- icu-64.2/source/samples/strsrch/strsrch.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/strsrch/strsrch.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -73,7 +73,6 @@ true .\x86\Debug/strsrch.pdb Console - false @@ -103,7 +102,6 @@ true .\x64\Debug/strsrch.pdb Console - false @@ -133,7 +131,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/strsrch.pdb Console - false @@ -164,7 +161,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/strsrch.pdb Console - false diff -Nru icu-64.2/source/samples/translit/translit.vcxproj icu-65.1/source/samples/translit/translit.vcxproj --- icu-64.2/source/samples/translit/translit.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/translit/translit.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -75,7 +75,6 @@ true .\x86\Debug/translit.pdb Console - false @@ -102,7 +101,6 @@ true .\x64\Debug/translit.pdb Console - false @@ -129,7 +127,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/translit.pdb Console - false @@ -156,7 +153,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/translit.pdb Console - false diff -Nru icu-64.2/source/samples/uciter8/uciter8.vcxproj icu-65.1/source/samples/uciter8/uciter8.vcxproj --- icu-64.2/source/samples/uciter8/uciter8.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/uciter8/uciter8.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -75,7 +75,6 @@ true .\x86\Debug/uciter8.pdb Console - false @@ -102,7 +101,6 @@ true .\x64\Debug/uciter8.pdb Console - false @@ -129,7 +127,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/uciter8.pdb Console - false @@ -156,7 +153,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/uciter8.pdb Console - false diff -Nru icu-64.2/source/samples/ucnv/ucnv.vcxproj icu-65.1/source/samples/ucnv/ucnv.vcxproj --- icu-64.2/source/samples/ucnv/ucnv.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/ucnv/ucnv.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -75,7 +75,6 @@ true .\x86\Debug/ucnv.pdb Console - false @@ -102,7 +101,6 @@ true .\x64\Debug/ucnv.pdb Console - false @@ -129,7 +127,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/ucnv.pdb Console - false @@ -156,7 +153,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/ucnv.pdb Console - false diff -Nru icu-64.2/source/samples/udata/reader.vcxproj icu-65.1/source/samples/udata/reader.vcxproj --- icu-64.2/source/samples/udata/reader.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/udata/reader.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -76,7 +76,6 @@ true .\reader_Win32_Debug/reader.pdb Console - false @@ -105,7 +104,6 @@ true .\reader_x64_Debug/reader.pdb Console - false @@ -134,7 +132,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\reader_Win32_Release/reader.pdb Console - false @@ -164,7 +161,6 @@ ../../../lib64;%(AdditionalLibraryDirectories) .\reader_x64_Release/reader.pdb Console - false diff -Nru icu-64.2/source/samples/udata/writer.vcxproj icu-65.1/source/samples/udata/writer.vcxproj --- icu-64.2/source/samples/udata/writer.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/udata/writer.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -76,7 +76,6 @@ true .\x86\Debug/writer.pdb Console - false @@ -107,7 +106,6 @@ true .\x64\Debug/writer.pdb Console - false @@ -136,7 +134,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\x86\Release/writer.pdb Console - false @@ -165,7 +162,6 @@ ../../../lib64;%(AdditionalLibraryDirectories) .\x64\Release\writer.pdb Console - false diff -Nru icu-64.2/source/samples/ufortune/ufortune.vcxproj icu-65.1/source/samples/ufortune/ufortune.vcxproj --- icu-64.2/source/samples/ufortune/ufortune.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/ufortune/ufortune.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -70,7 +70,6 @@ ../../../lib;%(AdditionalLibraryDirectories) true Console - false @@ -101,7 +100,6 @@ true ../../../lib;%(AdditionalLibraryDirectories) Console - false diff -Nru icu-64.2/source/samples/ugrep/ugrep.vcxproj icu-65.1/source/samples/ugrep/ugrep.vcxproj --- icu-64.2/source/samples/ugrep/ugrep.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/ugrep/ugrep.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -74,7 +74,6 @@ ../../../lib;%(AdditionalLibraryDirectories) .\x86\Release/ugrep.pdb Console - false @@ -109,7 +108,6 @@ ../../../lib64;%(AdditionalLibraryDirectories) .\x64\Release/ugrep.pdb Console - false @@ -143,7 +141,6 @@ true .\x86\Debug/ugrep.pdb Console - false @@ -175,7 +172,6 @@ true .\x64\Debug/ugrep.pdb Console - false diff -Nru icu-64.2/source/samples/uresb/uresb.vcxproj icu-65.1/source/samples/uresb/uresb.vcxproj --- icu-64.2/source/samples/uresb/uresb.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/uresb/uresb.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -78,7 +78,6 @@ ../../../lib/;../../tools/toolutil/;%(AdditionalLibraryDirectories) .\x86\Release/uresb.pdb Console - false @@ -109,7 +108,6 @@ ../../../lib64/;../../tools/toolutil/;%(AdditionalLibraryDirectories) .\x64\Release/uresb.pdb Console - false @@ -140,7 +138,6 @@ true .\x86\Debug/uresb.pdb Console - false @@ -170,7 +167,6 @@ true .\x64\Debug/uresb.pdb Console - false diff -Nru icu-64.2/source/samples/ustring/ustring.vcxproj icu-65.1/source/samples/ustring/ustring.vcxproj --- icu-64.2/source/samples/ustring/ustring.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/samples/ustring/ustring.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -75,7 +75,6 @@ ..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/ustring.pdb Console - false @@ -103,7 +102,6 @@ ..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/ustring.pdb Console - false @@ -130,7 +128,6 @@ true .\x86\Debug/ustring.pdb Console - false @@ -157,7 +154,6 @@ true .\x64\Debug/ustring.pdb Console - false diff -Nru icu-64.2/source/stubdata/stubdata.vcxproj icu-65.1/source/stubdata/stubdata.vcxproj --- icu-64.2/source/stubdata/stubdata.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/stubdata/stubdata.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -35,29 +35,31 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - false - .\x86\Debug\ - .\x86\Debug\ - false - .\x64\Release\ - .\x64\Release\ - false - false - .\x64\Debug\ - .\x64\Debug\ - false + false + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false + + $(OutDir)\icudt.tlb + ..\common;%(AdditionalIncludeDirectories) STUBDATA_BUILD;%(PreprocessorDefinitions) true Level3 Default + $(OutDir)/icudt.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/icudt.pdb STUBDATA_BUILD;%(PreprocessorDefinitions) @@ -66,11 +68,13 @@ echo "File with stubdata build time, used as a dependency to trigger fresh data build, since stubdata dll will overwrite the real one." > "$(ProjectDir)stubdatabuilt.txt" - 0x4ad00000 true true - false true + + ..\..\$(IcuBinOutputDir)\icudt65.dll + .\..\..\$(IcuLibOutputDir)\icudt.pdb + ..\..\$(IcuLibOutputDir)\icudt.lib @@ -85,80 +89,6 @@ MultiThreadedDLL - - - .\x86\Release\icudt.tlb - - - - - .\x86\Release\stubdata.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - - - ..\..\bin\icudt64.dll - true - .\x86\Release\icudt.pdb - - - ..\..\lib\icudt.lib - - - - - .\x86\Debug/icudt.tlb - - - .\x86\Debug/stubdata.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - - - ..\..\bin\icudt64.dll - .\x86\Debug/icudt.pdb - - - ..\..\lib\icudt.lib - - - - - .\x64\Release\icudt.tlb - - - - - .\x64\Release\stubdata.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - - - ..\..\bin64\icudt64.dll - true - .\x64\Release\icudt.pdb - ..\..\lib64\icudt.lib - - - - - .\x64\Debug/icudt.tlb - - - .\x64\Debug/stubdata.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - - - ..\..\bin64\icudt64.dll - .\x64\Debug/icudt.pdb - ..\..\lib64\icudt.lib - - diff -Nru icu-64.2/source/test/cintltst/bocu1tst.c icu-65.1/source/test/cintltst/bocu1tst.c --- icu-64.2/source/test/cintltst/bocu1tst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/bocu1tst.c 2019-10-03 11:16:41.000000000 +0000 @@ -212,14 +212,14 @@ * @param d Divisor. * @param m Output variable for the rest (modulo result). */ -#define NEGDIVMOD(n, d, m) { \ +#define NEGDIVMOD(n, d, m) UPRV_BLOCK_MACRO_BEGIN { \ (m)=(n)%(d); \ (n)/=(d); \ if((m)<0) { \ --(n); \ (m)+=(d); \ } \ -} +} UPRV_BLOCK_MACRO_END /* State for BOCU-1 decoder function. */ struct Bocu1Rx { diff -Nru icu-64.2/source/test/cintltst/callcoll.c icu-65.1/source/test/cintltst/callcoll.c --- icu-64.2/source/test/cintltst/callcoll.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/callcoll.c 2019-10-03 11:16:41.000000000 +0000 @@ -219,7 +219,7 @@ UErrorCode status = U_ZERO_ERROR; - UResourceBundle *loc = ures_open(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "coll", locName, &status);; + UResourceBundle *loc = ures_open(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "coll", locName, &status); if(U_SUCCESS(status)) { status = U_ZERO_ERROR; diff -Nru icu-64.2/source/test/cintltst/capitst.c icu-65.1/source/test/cintltst/capitst.c --- icu-64.2/source/test/cintltst/capitst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/capitst.c 2019-10-03 11:16:41.000000000 +0000 @@ -42,6 +42,7 @@ static char* U_EXPORT2 ucol_sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t len) { + (void)coll; // suppress compiler warnings about unused variable uint32_t position = 0; uint8_t b; @@ -530,8 +531,8 @@ } while (TRUE) { /* testing with en since thai has its own tailoring */ - uint32_t ce = ucol_next(iter1, &status); - uint32_t ce2 = ucol_next(iter2, &status); + int32_t ce = ucol_next(iter1, &status); + int32_t ce2 = ucol_next(iter2, &status); if(U_FAILURE(status)) { log_err("ERROR: CollationElement iterator creation failed.: %s\n", myErrorName(status)); return; @@ -848,7 +849,7 @@ ucol_getSortKey(col, t, -1, k2, l2); if (strcmp((char *)k1,(char *)k2) != 0){ log_err("ucol_openBinary - new collator should equal to old one\n"); - }; + } free(k1); free(k2); } @@ -1544,64 +1545,64 @@ }; struct teststruct tests[] = { - {"\\u010CAKI MIHALJ" } , - {"\\u010CAKI MIHALJ" } , - {"\\u010CAKI PIRO\\u0160KA" }, - {"\\u010CABAI ANDRIJA" } , - {"\\u010CABAI LAJO\\u0160" } , - {"\\u010CABAI MARIJA" } , - {"\\u010CABAI STEVAN" } , - {"\\u010CABAI STEVAN" } , - {"\\u010CABARKAPA BRANKO" } , - {"\\u010CABARKAPA MILENKO" } , - {"\\u010CABARKAPA MIROSLAV" } , - {"\\u010CABARKAPA SIMO" } , - {"\\u010CABARKAPA STANKO" } , - {"\\u010CABARKAPA TAMARA" } , - {"\\u010CABARKAPA TOMA\\u0160" } , - {"\\u010CABDARI\\u0106 NIKOLA" } , - {"\\u010CABDARI\\u0106 ZORICA" } , - {"\\u010CABI NANDOR" } , - {"\\u010CABOVI\\u0106 MILAN" } , - {"\\u010CABRADI AGNEZIJA" } , - {"\\u010CABRADI IVAN" } , - {"\\u010CABRADI JELENA" } , - {"\\u010CABRADI LJUBICA" } , - {"\\u010CABRADI STEVAN" } , - {"\\u010CABRDA MARTIN" } , - {"\\u010CABRILO BOGDAN" } , - {"\\u010CABRILO BRANISLAV" } , - {"\\u010CABRILO LAZAR" } , - {"\\u010CABRILO LJUBICA" } , - {"\\u010CABRILO SPASOJA" } , - {"\\u010CADE\\u0160 ZDENKA" } , - {"\\u010CADESKI BLAGOJE" } , - {"\\u010CADOVSKI VLADIMIR" } , - {"\\u010CAGLJEVI\\u0106 TOMA" } , - {"\\u010CAGOROVI\\u0106 VLADIMIR" } , - {"\\u010CAJA VANKA" } , - {"\\u010CAJI\\u0106 BOGOLJUB" } , - {"\\u010CAJI\\u0106 BORISLAV" } , - {"\\u010CAJI\\u0106 RADOSLAV" } , - {"\\u010CAK\\u0160IRAN MILADIN" } , - {"\\u010CAKAN EUGEN" } , - {"\\u010CAKAN EVGENIJE" } , - {"\\u010CAKAN IVAN" } , - {"\\u010CAKAN JULIJAN" } , - {"\\u010CAKAN MIHAJLO" } , - {"\\u010CAKAN STEVAN" } , - {"\\u010CAKAN VLADIMIR" } , - {"\\u010CAKAN VLADIMIR" } , - {"\\u010CAKAN VLADIMIR" } , - {"\\u010CAKARA ANA" } , - {"\\u010CAKAREVI\\u0106 MOMIR" } , - {"\\u010CAKAREVI\\u0106 NEDELJKO" } , - {"\\u010CAKI \\u0160ANDOR" } , - {"\\u010CAKI AMALIJA" } , - {"\\u010CAKI ANDRA\\u0160" } , - {"\\u010CAKI LADISLAV" } , - {"\\u010CAKI LAJO\\u0160" } , - {"\\u010CAKI LASLO" } , + {"\\u010CAKI MIHALJ", {0}}, + {"\\u010CAKI MIHALJ", {0}}, + {"\\u010CAKI PIRO\\u0160KA", {0}}, + {"\\u010CABAI ANDRIJA", {0}}, + {"\\u010CABAI LAJO\\u0160", {0}}, + {"\\u010CABAI MARIJA", {0}}, + {"\\u010CABAI STEVAN", {0}}, + {"\\u010CABAI STEVAN", {0}}, + {"\\u010CABARKAPA BRANKO", {0}}, + {"\\u010CABARKAPA MILENKO", {0}}, + {"\\u010CABARKAPA MIROSLAV", {0}}, + {"\\u010CABARKAPA SIMO", {0}}, + {"\\u010CABARKAPA STANKO", {0}}, + {"\\u010CABARKAPA TAMARA", {0}}, + {"\\u010CABARKAPA TOMA\\u0160", {0}}, + {"\\u010CABDARI\\u0106 NIKOLA", {0}}, + {"\\u010CABDARI\\u0106 ZORICA", {0}}, + {"\\u010CABI NANDOR", {0}}, + {"\\u010CABOVI\\u0106 MILAN", {0}}, + {"\\u010CABRADI AGNEZIJA", {0}}, + {"\\u010CABRADI IVAN", {0}}, + {"\\u010CABRADI JELENA", {0}}, + {"\\u010CABRADI LJUBICA", {0}}, + {"\\u010CABRADI STEVAN", {0}}, + {"\\u010CABRDA MARTIN", {0}}, + {"\\u010CABRILO BOGDAN", {0}}, + {"\\u010CABRILO BRANISLAV", {0}}, + {"\\u010CABRILO LAZAR", {0}}, + {"\\u010CABRILO LJUBICA", {0}}, + {"\\u010CABRILO SPASOJA", {0}}, + {"\\u010CADE\\u0160 ZDENKA", {0}}, + {"\\u010CADESKI BLAGOJE", {0}}, + {"\\u010CADOVSKI VLADIMIR", {0}}, + {"\\u010CAGLJEVI\\u0106 TOMA", {0}}, + {"\\u010CAGOROVI\\u0106 VLADIMIR", {0}}, + {"\\u010CAJA VANKA", {0}}, + {"\\u010CAJI\\u0106 BOGOLJUB", {0}}, + {"\\u010CAJI\\u0106 BORISLAV", {0}}, + {"\\u010CAJI\\u0106 RADOSLAV", {0}}, + {"\\u010CAK\\u0160IRAN MILADIN", {0}}, + {"\\u010CAKAN EUGEN", {0}}, + {"\\u010CAKAN EVGENIJE", {0}}, + {"\\u010CAKAN IVAN", {0}}, + {"\\u010CAKAN JULIJAN", {0}}, + {"\\u010CAKAN MIHAJLO", {0}}, + {"\\u010CAKAN STEVAN", {0}}, + {"\\u010CAKAN VLADIMIR", {0}}, + {"\\u010CAKAN VLADIMIR", {0}}, + {"\\u010CAKAN VLADIMIR", {0}}, + {"\\u010CAKARA ANA", {0}}, + {"\\u010CAKAREVI\\u0106 MOMIR", {0}}, + {"\\u010CAKAREVI\\u0106 NEDELJKO", {0}}, + {"\\u010CAKI \\u0160ANDOR", {0}}, + {"\\u010CAKI AMALIJA", {0}}, + {"\\u010CAKI ANDRA\\u0160", {0}}, + {"\\u010CAKI LADISLAV", {0}}, + {"\\u010CAKI LAJO\\u0160", {0}}, + {"\\u010CAKI LASLO", {0}}, }; diff -Nru icu-64.2/source/test/cintltst/cbiapts.c icu-65.1/source/test/cintltst/cbiapts.c --- icu-64.2/source/test/cintltst/cbiapts.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cbiapts.c 2019-10-03 11:16:41.000000000 +0000 @@ -35,11 +35,17 @@ #include "cbiapts.h" #include "cmemory.h" -#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ -log_data_err("Failure at file %s, line %d, error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status));}} - -#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ -log_data_err("Test Failure at file %s, line %d (Are you missing data?)\n", __FILE__, __LINE__);}} +#define TEST_ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + log_data_err("Failure at file %s, line %d, error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + log_data_err("Test Failure at file %s, line %d (Are you missing data?)\n", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END #if !UCONFIG_NO_FILE_IO static void TestBreakIteratorSafeClone(void); @@ -99,7 +105,7 @@ UErrorCode status = U_ZERO_ERROR; if (src == NULL) { return NULL; - }; + } cnv = ucnv_open(NULL, &status); if(U_FAILURE(status) || cnv == NULL) { @@ -532,7 +538,7 @@ if (U_FAILURE(status)) { log_data_err("FAIL: ubrk_openRules: ICU Error \"%s\" (Are you missing data?)\n", u_errorName(status)); bi = 0; - }; + } freeToUCharStrings(&strCleanUp); return bi; @@ -566,7 +572,7 @@ ubrk_setText(bi, uData, -1, &status); pos = ubrk_first(bi); - for (i=0; i= sizeof(columns)) + if (k >= (int32_t)sizeof(columns)) c = '+'; else c = columns[k]; @@ -1287,11 +1287,12 @@ } } -#define RETURN_IF_BAD_ERRCODE(x) \ +#define RETURN_IF_BAD_ERRCODE(x) UPRV_BLOCK_MACRO_BEGIN { \ if (U_FAILURE(errorCode)) { \ log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \ return; \ } \ +} UPRV_BLOCK_MACRO_END #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) } @@ -4630,7 +4631,7 @@ k = map[i]; if (k < 0) c = '-'; - else if (k >= sizeof(columns)) + else if (k >= (int32_t)sizeof(columns)) c = '+'; else c = columns[k]; diff -Nru icu-64.2/source/test/cintltst/ccaltst.c icu-65.1/source/test/cintltst/ccaltst.c --- icu-64.2/source/test/cintltst/ccaltst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/ccaltst.c 2019-10-03 11:16:41.000000000 +0000 @@ -40,7 +40,7 @@ void TestGetWindowsTimeZoneID(void); void TestGetTimeZoneIDByWindowsID(void); -void TestJpnCalAddSetNextEra(); +void TestJpnCalAddSetNextEra(void); void addCalTest(TestNode** root); @@ -114,7 +114,8 @@ UChar *result = 0; int32_t resultlength, resultlengthneeded; char tempMsgBuf[1024]; // u_austrcpy() of some formatted dates & times. - UChar zone1[32], zone2[32]; + char tempMsgBuf2[256]; // u_austrcpy() of some formatted dates & times. + UChar zone1[64], zone2[64]; const char *tzver = 0; UChar canonicalID[64]; UBool isSystemID = FALSE; @@ -228,10 +229,10 @@ log_err("FAIL: ucal_getDSTSavings(PST) => %d, expect %d\n", i, 1*60*60*1000); } - /*Test ucal_set/getDefaultTimeZone*/ + /*Test ucal_set/getDefaultTimeZone and ucal_getHostTimeZone */ status = U_ZERO_ERROR; i = ucal_getDefaultTimeZone(zone1, UPRV_LENGTHOF(zone1), &status); - if (U_FAILURE(status)) { + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { log_err("FAIL: ucal_getDefaultTimeZone() => %s\n", u_errorName(status)); } else { @@ -247,6 +248,17 @@ } else { if (u_strcmp(zone2, EUROPE_PARIS) != 0) { log_data_err("FAIL: ucal_getDefaultTimeZone() did not return Europe/Paris (Are you missing data?)\n"); + } else { + // Redetect the host timezone, it should be the same as zone1 even though ICU's default timezone has been changed. + i = ucal_getHostTimeZone(zone2, UPRV_LENGTHOF(zone2), &status); + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { + log_err("FAIL: ucal_getHostTimeZone() => %s\n", u_errorName(status)); + } else { + if (u_strcmp(zone1, zone2) != 0) { + log_err("FAIL: ucal_getHostTimeZone() should give the same host timezone even if the default changed. (Got '%s', Expected '%s').\n", + u_austrcpy(tempMsgBuf, zone2), u_austrcpy(tempMsgBuf2, zone1)); + } + } } } } @@ -346,6 +358,11 @@ datdef=udat_open(UDAT_FULL,UDAT_FULL ,NULL, NULL, 0,NULL,0,&status); if(U_FAILURE(status)){ log_data_err("FAIL: error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status)); + ucal_close(caldef2); + ucal_close(calfr); + ucal_close(calit); + ucal_close(calfrclone); + ucal_close(caldef); return; } log_verbose("PASS: The current date and time fetched is %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datdef, now)) ); @@ -525,6 +542,10 @@ if(U_FAILURE(status)) { log_data_err("error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status)); + ucal_close(caldef); + ucal_close(caldef2); + ucal_close(caldef3); + udat_close(datdef); return; } @@ -935,7 +956,7 @@ u_uastrcpy(tzID, "PST"); /*open the calendar used */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status); if (U_FAILURE(status)) { log_data_err("ucal_open() failed : %s - (Are you missing data?)\n", u_errorName(status)); return; @@ -1123,7 +1144,7 @@ u_uastrcpy(tzID, "PST"); /*open the calendar used */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status); if (U_FAILURE(status)) { log_data_err("ucal_open() for gregorian calendar failed in TestGetLimits: %s - (Are you missing data?)\n", u_errorName(status)); return; @@ -1221,7 +1242,7 @@ char tempMsgBuf[256]; u_strcpy(tzID, fgGMTID); /*open the calendar used */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status)); return; @@ -1238,30 +1259,33 @@ log_verbose("\nTesting the DOW progression\n"); initialDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); - if (U_FAILURE(status)) { log_data_err("ucal_get() failed: %s (Are you missing data?)\n", u_errorName(status) ); return; } - newDOW = initialDOW; - do { - DOW = newDOW; - log_verbose("DOW = %d...\n", DOW); - date1=ucal_getMillis(cal, &status); - if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;} - log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1))); - - ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status); - if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); return; } - - newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); - if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); return; } - expectedDOW = 1 + (DOW + delta - 1) % 7; - date1=ucal_getMillis(cal, &status); - if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;} - if (newDOW != expectedDOW) { - log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW, - u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); - return; + if (U_FAILURE(status)) { + log_data_err("ucal_get() failed: %s (Are you missing data?)\n", u_errorName(status) ); + } else { + newDOW = initialDOW; + do { + DOW = newDOW; + log_verbose("DOW = %d...\n", DOW); + date1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); break;} + log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1))); + + ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status); + if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); break; } + + newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); + if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); break; } + expectedDOW = 1 + (DOW + delta - 1) % 7; + date1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); break;} + if (newDOW != expectedDOW) { + log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW, + u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); + break; + } } + while (newDOW != initialDOW); } - while (newDOW != initialDOW); ucal_close(cal); udat_close(datfor); @@ -1294,16 +1318,16 @@ char tempMsgBuf[256]; u_strcpy(tzID, fgGMTID); - gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);; + gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status)); - return; + goto cleanup; } u_uastrcpy(tzID, "PST"); cal = ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_err("ucal_open failed: %s\n", u_errorName(status)); - return; + goto cleanup; } datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status); @@ -1314,13 +1338,13 @@ ucal_setDateTime(gmtcal, yr, mo - 1, dt, hr, mn, sc, &status); if (U_FAILURE(status)) { log_data_err("ucal_setDateTime failed: %s (Are you missing data?)\n", u_errorName(status)); - return; + goto cleanup; } ucal_set(gmtcal, UCAL_MILLISECOND, 0); date1 = ucal_getMillis(gmtcal, &status); if (U_FAILURE(status)) { log_err("ucal_getMillis failed: %s\n", u_errorName(status)); - return; + goto cleanup; } log_verbose("date = %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); @@ -1328,7 +1352,7 @@ ucal_setMillis(cal, date1, &status); if (U_FAILURE(status)) { log_err("ucal_setMillis() failed: %s\n", u_errorName(status)); - return; + goto cleanup; } offset = ucal_get(cal, UCAL_ZONE_OFFSET, &status); @@ -1336,7 +1360,7 @@ if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); - return; + goto cleanup; } temp=(double)((double)offset / 1000.0 / 60.0 / 60.0); /*printf("offset for %s %f hr\n", austrdup(myDateFormat(datfor, date1)), temp);*/ @@ -1347,7 +1371,7 @@ ucal_get(cal, UCAL_MILLISECOND, &status) - offset; if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); - return; + goto cleanup; } expected = ((hr * 60 + mn) * 60 + sc) * 1000; @@ -1357,6 +1381,8 @@ } else log_verbose("PASS: the offset between local and GMT is correct\n"); + +cleanup: ucal_close(gmtcal); ucal_close(cal); udat_close(datfor); @@ -2379,6 +2405,11 @@ static const UChar sBogus[] = /* Bogus */ {0x42,0x6F,0x67,0x75,0x73,0x00}; +#ifndef U_DEBUG +static const UChar sBogusWithVariantCharacters[] = /* Bogus with Variant characters: Hèℓℓô Wôřℓδ */ + {0x48,0xE8,0x2113,0x2113,0xF4,0x20,0x57,0xF4,0x159,0x2113,0x3B4,0x00}; +#endif + void TestGetWindowsTimeZoneID() { UErrorCode status; UChar winID[64]; @@ -2445,7 +2476,6 @@ log_err("FAIL: TZ ID for Eastern Standard Time - CA\n"); } } - { status = U_ZERO_ERROR; len = ucal_getTimeZoneIDForWindowsID(sBogus, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status); @@ -2455,6 +2485,15 @@ log_err("FAIL: TZ ID for Bogus\n"); } } +#ifndef U_DEBUG + // This test is only for release mode because it will cause an assertion failure in debug builds. + // We don't check the API result for errors as the only purpose of this test is to ensure that + // input variant characters don't cause abort() to be called and/or that ICU doesn't crash. + { + status = U_ZERO_ERROR; + len = ucal_getTimeZoneIDForWindowsID(sBogusWithVariantCharacters, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status); + } +#endif } // The following currently assumes that Reiwa is the last known/valid era. diff -Nru icu-64.2/source/test/cintltst/ccapitst.c icu-65.1/source/test/cintltst/ccapitst.c --- icu-64.2/source/test/cintltst/ccapitst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/ccapitst.c 2019-10-03 11:16:41.000000000 +0000 @@ -35,6 +35,9 @@ #define MAX_FILE_LEN 1024*20 #define UCS_FILE_NAME_SIZE 512 +/* Similar to C++ alignof(type) */ +#define ALIGNOF(type) offsetof (struct { char c; type member; }, member) + /*returns an action other than the one provided*/ #if !UCONFIG_NO_LEGACY_CONVERSION static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA); @@ -1367,6 +1370,11 @@ UConverterCallbackReason reason, UErrorCode * err) { + // suppress compiler warnings about unused variables + (void)codeUnits; + (void)length; + (void)codePoint; + TSCCContext *ctx = (TSCCContext*)context; UConverterFromUCallback junkFrom; @@ -1413,6 +1421,10 @@ UConverterCallbackReason reason, UErrorCode * err) { + // suppress compiler warnings about unused variables + (void)codeUnits; + (void)length; + TSCCContext *ctx = (TSCCContext*)context; UConverterToUCallback junkFrom; @@ -1821,7 +1833,7 @@ /* close the original immediately to make sure that the clone works by itself */ ucnv_close(cnv); - if( actualSizes[idx] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) && + if( actualSizes[idx] <= (bufferSizes[j] - (int32_t)ALIGNOF(UConverter)) && err == U_SAFECLONE_ALLOCATED_WARNING ) { log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[idx]); @@ -2194,10 +2206,10 @@ if(errorCode==U_BUFFER_OVERFLOW_ERROR) { /* continue converting another chunk */ errorCode=U_ZERO_ERROR; - if(targetLength+chunkSize<=sizeof(targetBuffer)) { + if(targetLength+chunkSize<=(int32_t)sizeof(targetBuffer)) { targetLimit=target+chunkSize; } else { - targetLimit=targetBuffer+sizeof(targetBuffer); + targetLimit=targetBuffer+(int32_t)sizeof(targetBuffer); } } else if(U_FAILURE(errorCode)) { /* failure */ @@ -2519,6 +2531,12 @@ char charUTF8[4], int32_t charUTF8Length, char char0[8], int32_t char0Length, char char1[8], int32_t char1Length) { + // suppress compiler warnings about unused variables + (void)char0; + (void)char0Length; + (void)char1; + (void)char1Length; + char utf8[16]; int32_t utf8Length; diff -Nru icu-64.2/source/test/cintltst/cdtdptst.c icu-65.1/source/test/cintltst/cdtdptst.c --- icu-64.2/source/test/cintltst/cdtdptst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cdtdptst.c 2019-10-03 11:16:41.000000000 +0000 @@ -207,6 +207,7 @@ format = udat_open(UDAT_PATTERN, UDAT_PATTERN, NULL, NULL, 0,pattern, u_strlen(pattern), &status); if(U_FAILURE(status)){ log_data_err("FAIL: Error in date format construction with pattern: %s - (Are you missing data?)\n", myErrorName(status)); + free(pattern); return; } date1 = ucal_getNow(); @@ -304,10 +305,12 @@ */ void TestQuotePattern161() { - UDateFormat *format; - UCalendar *cal; + UDateFormat *format = NULL; + UCalendar *cal = NULL; UDate currentTime_1; - UChar *pattern, *tzID, *exp; + UChar *pattern = NULL; + UChar *tzID = NULL; + UChar *exp = NULL; UChar *dateString; UErrorCode status = U_ZERO_ERROR; const char* expStr = "04/13/1999 at 10:42:28 AM "; @@ -323,27 +326,27 @@ format= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); if(U_FAILURE(status)){ log_data_err("error in udat_open: %s - (Are you missing data?)\n", myErrorName(status)); - return; + } else { + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */ + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status)); } + + ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status); + currentTime_1 = ucal_getMillis(cal, &status); + + dateString = myDateFormat(format, currentTime_1); + exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) ); + u_uastrcpy(exp, expStr); + + log_verbose("%s\n", austrdup(dateString) ); + if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0) { + log_err("Error in formatting a pattern with single quotes\n"); + } } - tzID=(UChar*)malloc(sizeof(UChar) * 4); - u_uastrcpy(tzID, "PST"); - /* this is supposed to open default date format, but later on it treats it like it is "en_US" - - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ - /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */ - cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); - if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status)); } - - ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status); - currentTime_1 = ucal_getMillis(cal, &status); - - dateString = myDateFormat(format, currentTime_1); - exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) ); - u_uastrcpy(exp, expStr); - - log_verbose("%s\n", austrdup(dateString) ); - if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0) - log_err("Error in formatting a pattern with single quotes\n"); - udat_close(format); ucal_close(cal); free(exp); diff -Nru icu-64.2/source/test/cintltst/cdtrgtst.c icu-65.1/source/test/cintltst/cdtrgtst.c --- icu-64.2/source/test/cintltst/cdtrgtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cdtrgtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -166,6 +166,7 @@ if(U_FAILURE(status)) { log_data_err("FAIL: error in creating the dateformat using u_openPattern(): %s - (Are you missing data?)\n", myErrorName(status)); + ucal_close(cal); return; } start = 1800; diff -Nru icu-64.2/source/test/cintltst/cintltst.c icu-65.1/source/test/cintltst/cintltst.c --- icu-64.2/source/test/cintltst/cintltst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cintltst.c 2019-10-03 11:16:41.000000000 +0000 @@ -743,4 +743,18 @@ return TRUE; } +U_CFUNC UBool assertPtrEquals(const char* message, const void* expected, const void* actual) { + if (expected != actual) { + log_err("FAIL: %s; got 0x%llx; expected 0x%llx\n", + message, actual, expected); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + log_verbose("Ok: %s; got 0x%llx\n", message, actual); + } +#endif + return TRUE; +} + #endif diff -Nru icu-64.2/source/test/cintltst/cintltst.h icu-65.1/source/test/cintltst/cintltst.h --- icu-64.2/source/test/cintltst/cintltst.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cintltst.h 2019-10-03 11:16:41.000000000 +0000 @@ -147,6 +147,12 @@ */ U_CFUNC UBool assertIntEquals(const char* msg, int64_t expected, int64_t actual); +/** + * Assert that the addresses of the two pointers are the same, returning + * TRUE if they are equal. + */ +U_CFUNC UBool assertPtrEquals(const char* msg, const void* expected, const void* actual); + /* * note - isICUVersionBefore and isICUVersionAtLeast have been removed. * use log_knownIssue() instead. diff -Nru icu-64.2/source/test/cintltst/cintltst.vcxproj icu-65.1/source/test/cintltst/cintltst.vcxproj --- icu-64.2/source/test/cintltst/cintltst.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cintltst.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,124 +33,55 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Debug\ - .\x86\Debug\ - true - .\x86\Release\ - .\x86\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + - - ..\..\..\include;..\..\tools\ctestfw;..\..\common;..\..\i18n;..\..\tools\toolutil;%(AdditionalIncludeDirectories) - U_ATTRIBUTE_DEPRECATED=;%(PreprocessorDefinitions) - false - Level3 - - - - - .\x86\Debug/cintltst.tlb - - - MultiThreadedDebug - .\x86\Debug/cintltst.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true - EditAndContinue - Default - - - .\x86\Debug/cintltst.exe - icuucd.lib;icuind.lib;icutestd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Debug/cintltst.pdb - Console - false - false - - - - - - .\x86\Release/cintltst.tlb + $(OutDir)\cintltst.tlb - MultiThreaded - true - true - .\x86\Release/cintltst.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ + Level3 Default + false + ..\..\..\include;..\..\tools\ctestfw;..\..\common;..\..\i18n;..\..\tools\toolutil;%(AdditionalIncludeDirectories) + U_ATTRIBUTE_DEPRECATED=;%(PreprocessorDefinitions) + $(OutDir)\cintltst.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\cintltst.pdb - .\x86\Release/cintltst.exe - icuuc.lib;icuin.lib;icutest.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Release/cintltst.pdb Console - false - - + $(OutDir)\cintltst.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - .\x64\Debug/cintltst.tlb - + + - MultiThreadedDebug - .\x64\Debug/cintltst.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ true - ProgramDatabase - Default + MultiThreadedDebugDLL - .\x64\Debug/cintltst.exe icuucd.lib;icuind.lib;icutestd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Debug/cintltst.pdb - Console - false - - - .\x64\Release/cintltst.tlb - + + - MultiThreaded - true + MultiThreadedDLL true - .\x64\Release/cintltst.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default - .\x64\Release/cintltst.exe icuuc.lib;icuin.lib;icutest.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Release/cintltst.pdb - Console diff -Nru icu-64.2/source/test/cintltst/citertst.c icu-65.1/source/test/cintltst/citertst.c --- icu-64.2/source/test/cintltst/citertst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/citertst.c 2019-10-03 11:16:41.000000000 +0000 @@ -1076,7 +1076,7 @@ log_verbose("count %d\n", count); for (;;) { - uint32_t ce; + int32_t ce; UChar *e = u_strchr(s, 0x20); if (e == 0) { e = u_strchr(s, 0); @@ -1088,7 +1088,7 @@ return; } while (ce != UCOL_NULLORDER) { - if (ce != (uint32_t)ucol_next(iter, &status) || + if (ce != ucol_next(iter, &status) || U_FAILURE(status)) { log_err("Discontiguos contraction test mismatch\n"); return; diff -Nru icu-64.2/source/test/cintltst/cldrtest.c icu-65.1/source/test/cintltst/cldrtest.c --- icu-64.2/source/test/cintltst/cldrtest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cldrtest.c 2019-10-03 11:16:41.000000000 +0000 @@ -454,6 +454,7 @@ testLCID(UResourceBundle *currentBundle, const char *localeName) { + (void)currentBundle; // suppress compiler warnings about unused variables UErrorCode status = U_ZERO_ERROR; uint32_t expectedLCID; char lcidStringC[64] = {0}; diff -Nru icu-64.2/source/test/cintltst/cloctst.c icu-65.1/source/test/cintltst/cloctst.c --- icu-64.2/source/test/cintltst/cloctst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cloctst.c 2019-10-03 11:16:41.000000000 +0000 @@ -218,6 +218,7 @@ TESTCASE(TestSimpleResourceInfo); TESTCASE(TestDisplayNames); TESTCASE(TestGetAvailableLocales); + TESTCASE(TestGetAvailableLocalesByType); TESTCASE(TestDataDirectory); #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION TESTCASE(TestISOFunctions); @@ -255,8 +256,8 @@ TESTCASE(TestLikelySubtags); TESTCASE(TestToLanguageTag); TESTCASE(TestBug20132); + TESTCASE(TestBug20149); TESTCASE(TestForLanguageTag); - TESTCASE(TestInvalidLanguageTag); TESTCASE(TestLangAndRegionCanonicalize); TESTCASE(TestTrailingNull); TESTCASE(TestUnicodeDefines); @@ -834,6 +835,77 @@ } } +static void TestGetAvailableLocalesByType() { + UErrorCode status = U_ZERO_ERROR; + + UEnumeration* uenum = uloc_openAvailableByType(ULOC_AVAILABLE_DEFAULT, &status); + assertSuccess("Constructing the UEnumeration", &status); + + assertIntEquals("countAvailable() should be same in old and new methods", + uloc_countAvailable(), + uenum_count(uenum, &status)); + + for (int32_t i = 0; i < uloc_countAvailable(); i++) { + const char* old = uloc_getAvailable(i); + int32_t len = 0; + const char* new = uenum_next(uenum, &len, &status); + assertEquals("Old and new strings should equal", old, new); + assertIntEquals("String length should be correct", uprv_strlen(old), len); + } + assertPtrEquals("Should get nullptr on the last string", + NULL, uenum_next(uenum, NULL, &status)); + + uenum_close(uenum); + + uenum = uloc_openAvailableByType(ULOC_AVAILABLE_ONLY_LEGACY_ALIASES, &status); + UBool found_he = FALSE; + UBool found_iw = FALSE; + const char* loc; + while ((loc = uenum_next(uenum, NULL, &status))) { + if (uprv_strcmp("he", loc) == 0) { + found_he = TRUE; + } + if (uprv_strcmp("iw", loc) == 0) { + found_iw = TRUE; + } + } + assertTrue("Should NOT have found he amongst the legacy/alias locales", !found_he); + assertTrue("Should have found iw amongst the legacy/alias locales", found_iw); + uenum_close(uenum); + + uenum = uloc_openAvailableByType(ULOC_AVAILABLE_WITH_LEGACY_ALIASES, &status); + found_he = FALSE; + found_iw = FALSE; + const UChar* uloc; // test the UChar conversion + int32_t count = 0; + while ((uloc = uenum_unext(uenum, NULL, &status))) { + if (u_strcmp(u"iw", uloc) == 0) { + found_iw = TRUE; + } + if (u_strcmp(u"he", uloc) == 0) { + found_he = TRUE; + } + count++; + } + assertTrue("Should have found he amongst all locales", found_he); + assertTrue("Should have found iw amongst all locales", found_iw); + assertIntEquals("Should return as many strings as claimed", + count, uenum_count(uenum, &status)); + + // Reset the enumeration and it should still work + uenum_reset(uenum, &status); + count = 0; + while ((loc = uenum_next(uenum, NULL, &status))) { + count++; + } + assertIntEquals("After reset, should return as many strings as claimed", + count, uenum_count(uenum, &status)); + + uenum_close(uenum); + + assertSuccess("No errors should have occurred", &status); +} + /* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */ static void TestDataDirectory() { @@ -1783,6 +1855,7 @@ status = U_ZERO_ERROR; resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status); + (void)resultLen; U_ASSERT(resultLen < 256); if (U_SUCCESS(status)) { if (testCases[i].expectedLocaleID == 0) { @@ -2003,7 +2076,7 @@ resultLen = uloc_getKeywordValue(kwSetTestCases[i].x, kwSetTestCases[i].k, buffer, 1023, &status); if(U_FAILURE(status)) { log_err("Err on test case %d for getKeywordValue: got error %s\n", i, u_errorName(status)); - } else if (resultLen != uprv_strlen(kwSetTestCases[i].v) || uprv_strcmp(buffer, kwSetTestCases[i].v) != 0) { + } else if (resultLen != (int32_t)uprv_strlen(kwSetTestCases[i].v) || uprv_strcmp(buffer, kwSetTestCases[i].v) != 0) { log_err("FAIL: #%d getKeywordValue: got %s (%d) expected %s (%d)\n", i, buffer, resultLen, kwSetTestCases[i].v, uprv_strlen(kwSetTestCases[i].v)); } @@ -2347,6 +2420,7 @@ displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); if(U_FAILURE(status)){ log_err("uloc_getDisplayKeyword filed for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); + free(displayKeyword); break; } if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){ @@ -2355,6 +2429,7 @@ } else { log_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale); } + free(displayKeyword); break; } }else{ @@ -2430,6 +2505,7 @@ displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); if(U_FAILURE(status)){ log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); + free(displayKeywordValue); break; } if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){ @@ -2438,6 +2514,7 @@ } else { log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); } + free(displayKeywordValue); break; } }else{ @@ -2483,6 +2560,7 @@ displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); if(U_FAILURE(status)){ log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", localeID, keyword, displayLocale, u_errorName(status)); + free(displayKeywordValue); break; } if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){ @@ -2491,6 +2569,7 @@ } else { log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale); } + free(displayKeywordValue); break; } }else{ @@ -3396,7 +3475,7 @@ continue; } - if (length != uprv_strlen(temp2)) { + if (length != (int32_t)uprv_strlen(temp2)) { log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2)); } @@ -6200,35 +6279,6 @@ } } -/* See https://unicode-org.atlassian.net/browse/ICU-20149 . - * Depending on the resolution of that bug, this test may have - * to be revised. - */ -static void TestInvalidLanguageTag(void) { - static const char* invalid_lang_tags[] = { - "zh-u-foo-foo-co-pinyin", /* duplicate attribute in U extension */ - "zh-cmn-hans-u-foo-foo-co-pinyin", /* duplicate attribute in U extension */ -#if 0 - /* - * These do not lead to an error. Instead, parsing stops at the 1st - * invalid subtag. - */ - "de-DE-1901-1901", /* duplicate variant */ - "en-a-bbb-a-ccc", /* duplicate extension */ -#endif - NULL - }; - char locale[256]; - for (const char** tag = invalid_lang_tags; *tag != NULL; tag++) { - UErrorCode status = U_ZERO_ERROR; - uloc_forLanguageTag(*tag, locale, sizeof(locale), NULL, &status); - if (status != U_ILLEGAL_ARGUMENT_ERROR) { - log_err("Error returned by uloc_forLanguageTag for input language tag [%s] : %s - expected error: %s\n", - *tag, u_errorName(status), u_errorName(U_ILLEGAL_ARGUMENT_ERROR)); - } - } -} - static const struct { const char *input; const char *canonical; @@ -6558,3 +6608,18 @@ log_err("FAIL: Expected LCID value of 0 for invalid localeID input."); } } + +// Test case for ICU-20149 +// Handle the duplicate U extension attribute +static void TestBug20149() { + const char *localeID = "zh-u-foo-foo-co-pinyin"; + char locale[256]; + UErrorCode status = U_ZERO_ERROR; + int32_t parsedLen; + locale[0] = '\0'; + uloc_forLanguageTag(localeID, locale, sizeof(locale), &parsedLen, &status); + if (U_FAILURE(status) || + 0 !=strcmp("zh@attribute=foo;collation=pinyin", locale)) { + log_err("ERROR: in uloc_forLanguageTag %s return %s\n", myErrorName(status), locale); + } +} diff -Nru icu-64.2/source/test/cintltst/cloctst.h icu-65.1/source/test/cintltst/cloctst.h --- icu-64.2/source/test/cintltst/cloctst.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cloctst.h 2019-10-03 11:16:41.000000000 +0000 @@ -36,7 +36,8 @@ /** * Test getAvailableLocales **/ - static void TestGetAvailableLocales(void); +static void TestGetAvailableLocales(void); +static void TestGetAvailableLocalesByType(void); /** * Test functions to set and access a custom data directory **/ @@ -124,7 +125,6 @@ * language tag */ static void TestForLanguageTag(void); -static void TestInvalidLanguageTag(void); static void TestToLanguageTag(void); static void TestBug20132(void); static void TestLangAndRegionCanonicalize(void); @@ -133,6 +133,7 @@ static void TestToLegacyKey(void); static void TestToUnicodeLocaleType(void); static void TestToLegacyType(void); +static void TestBug20149(void); /** * locale data diff -Nru icu-64.2/source/test/cintltst/cmsccoll.c icu-65.1/source/test/cintltst/cmsccoll.c --- icu-64.2/source/test/cintltst/cmsccoll.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cmsccoll.c 2019-10-03 11:16:41.000000000 +0000 @@ -588,11 +588,13 @@ coll = ucol_open("", &status); if (U_FAILURE(status)) { log_data_err("Error opening collator -> %s (Are you missing data?)\n", u_errorName(status)); + uset_close(charsToTest); return; } charsToTestSize = uset_size(charsToTest); if (charsToTestSize <= 0) { log_err("Set was zero. Missing data?\n"); + uset_close(charsToTest); return; } t = (tester **)malloc(charsToTestSize * sizeof(tester *)); @@ -1454,14 +1456,14 @@ UCollationElements *iter2 = ucol_openElements(coll, &(testdata[i][j]), 1, &status); - uint32_t ce; + int32_t ce; if (U_FAILURE(status)) { log_err("Collation iterator creation failed\n"); return; } ce = ucol_next(iter2, &status); while (ce != UCOL_NULLORDER) { - if ((uint32_t)ucol_next(iter1, &status) != ce) { + if (ucol_next(iter1, &status) != ce) { log_err("Collation elements in contraction split does not match\n"); return; } diff -Nru icu-64.2/source/test/cintltst/cmsgtst.c icu-65.1/source/test/cintltst/cmsgtst.c --- icu-64.2/source/test/cintltst/cmsgtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cmsgtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -189,6 +189,7 @@ if(U_FAILURE(ec)){ log_data_err("umsg_open() failed for testCasePattens[0]. -> %s (Are you missing data?)\n", u_errorName(ec)); + umsg_close(formatter); return; } for(i = 0;i %s\n", pat[p], u_errorName(status)); + free(upat); + upat = NULL; continue; } lneed= u_strlen(upat) + 1; diff -Nru icu-64.2/source/test/cintltst/cnormtst.c icu-65.1/source/test/cintltst/cnormtst.c --- icu-64.2/source/test/cintltst/cnormtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cnormtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -484,6 +484,7 @@ UNORM_YES) { log_data_err("ERROR in NFD quick check for string at count %d - (Are you missing data?)\n", count); + free(d); free(c); return; } @@ -491,6 +492,7 @@ UNORM_NO) { log_err("ERROR in NFC quick check for string at count %d\n", count); + free(d); free(c); return; } @@ -506,6 +508,7 @@ UNORM_YES) { log_data_err("ERROR in NFKD quick check for string at count %d\n", count); + free(d); free(c); return; } @@ -513,6 +516,7 @@ UNORM_YES) { log_err("ERROR in NFKC quick check for string at count %d\n", count); + free(d); free(c); return; } @@ -661,7 +665,7 @@ for (count = 0; count < 50; count ++) { int size = 0; - UBool testresult = UNORM_YES; + UNormalizationCheckResult testresult = UNORM_YES; UChar data[20]; UChar norm[100]; UChar nfd[100]; @@ -1413,6 +1417,7 @@ log_data_err("%s:%d errorCode=%s\n", __FILE__, __LINE__, u_errorName(errorCode)); break; } + /* length-length == 0 is used to get around a compiler warning. */ U16_GET(nfd, 0, length-length, length, lead); U16_GET(nfd, 0, length-1, length, trail); diff -Nru icu-64.2/source/test/cintltst/cnumtst.c icu-65.1/source/test/cintltst/cnumtst.c --- icu-64.2/source/test/cintltst/cnumtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cnumtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -73,6 +73,7 @@ static void TestParseCases(void); static void TestSetMaxFracAndRoundIncr(void); static void TestIgnorePadding(void); +static void TestSciNotationMaxFracCap(void); #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x) @@ -112,6 +113,7 @@ TESTCASE(TestParseCases); TESTCASE(TestSetMaxFracAndRoundIncr); TESTCASE(TestIgnorePadding); + TESTCASE(TestSciNotationMaxFracCap); } /* test Parse int 64 */ @@ -498,7 +500,7 @@ pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status); if(U_FAILURE(status)) { - log_err("error in unum_openPattern(): %s\n", myErrorName(status) );; + log_err("error in unum_openPattern(): %s\n", myErrorName(status) ); } else log_verbose("Pass: unum_openPattern() works fine\n"); @@ -881,9 +883,9 @@ log_err("File %s, Line %d, (expected, acutal) = (\"%s\", \"%s\")\n", __FILE__, __LINE__, numFormatted, desta); } - if (strlen(numFormatted) != resultSize) { + if ((int32_t)strlen(numFormatted) != resultSize) { log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n", - __FILE__, __LINE__, strlen(numFormatted), resultSize); + __FILE__, __LINE__, (int32_t)strlen(numFormatted), resultSize); } /* Format with a FieldPosition parameter */ @@ -922,9 +924,9 @@ log_verbose("File %s, Line %d, got expected = \"%s\"\n", __FILE__, __LINE__, desta); } - if (strlen(parseExpected) != resultSize) { + if ((int32_t)strlen(parseExpected) != resultSize) { log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n", - __FILE__, __LINE__, strlen(parseExpected), resultSize); + __FILE__, __LINE__, (int32_t)strlen(parseExpected), resultSize); } /* Parse with a parsePos parameter */ @@ -944,9 +946,9 @@ log_verbose("File %s, Line %d, got expected = \"%s\"\n", __FILE__, __LINE__, desta); } - if (strlen(numFormatted) != parsePos) { + if ((int32_t)strlen(numFormatted) != parsePos) { log_err("File %s, Line %d, parsePos (expected, actual) = (\"%d\", \"%d\")\n", - __FILE__, __LINE__, strlen(parseExpected), parsePos); + __FILE__, __LINE__, (int32_t)strlen(parseExpected), parsePos); } unum_close(fmt); @@ -1323,7 +1325,7 @@ pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), "en_US",NULL, &status); if(U_FAILURE(status)) { - log_err_status(status, "error in padding unum_openPattern(%s): %s\n", temp1, myErrorName(status) );; + log_err_status(status, "error in padding unum_openPattern(%s): %s\n", temp1, myErrorName(status) ); } else { log_verbose("Pass: padding unum_openPattern() works fine\n"); @@ -1625,7 +1627,7 @@ /* set the default ruleset to the first one found, and retry */ if (len > 0) { - for (i = 0; i < len && temp[i] != ';'; ++i){}; + for (i = 0; i < len && temp[i] != ';'; ++i){} if (i < len) { buffer[i] = 0; unum_setTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, -1, &status); @@ -1836,6 +1838,7 @@ } len = unum_formatDouble(fmt, 10.123456789, fmtbuf, FORMAT_BUF_CAPACITY, NULL, &status); U_ASSERT(len < FORMAT_BUF_CAPACITY); + (void)len; if (U_FAILURE(status)) { log_err_status(status, "unum_formatDouble 10.123456789 failed with %s\n", u_errorName(status)); } @@ -2564,8 +2567,8 @@ {"zh_CN", "1234.56", "USD", "US$1,234.56", "US$1,234.56", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"}, // {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "CHY1.00", "CHY1.00", "1.00 CHY"}, // wrong ISO code // {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"}, // wrong ISO code - {"zh_CN", "1", "CNY", "\\uFFE51.00", "\\uFFE51.00", "\\uFFE51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"}, - {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "\\uFFE51,234.56", "\\uFFE51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"}, + {"zh_CN", "1", "CNY", "\\u00A51.00", "\\u00A51.00", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"}, + {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "\\u00A51,234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"}, {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0\\u20BD", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E " "\\u0440\\u0443\\u0431\\u043B\\u044F"}, {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0\\u20BD", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E " @@ -3235,6 +3238,7 @@ status = U_ZERO_ERROR; decstr[0] = 0; dclen = unum_parseDecimal(unumDec, itemPtr->text, -1, &parsePos, decstr, 32, &status); + (void)dclen; if (status != itemPtr->decStatus || parsePos != itemPtr->decPos || uprv_strcmp(decstr,itemPtr->decString) != 0) { char btext[32]; u_austrcpy(btext, itemPtr->text); @@ -3366,6 +3370,7 @@ status = U_ZERO_ERROR; ulen = unum_toPattern(unf, FALSE, ubuf, kUBufMax, &status); + (void)ulen; if ( U_FAILURE(status) ) { log_err("test %s: unum_toPattern fails with %s\n", itemPtr->descrip, u_errorName(status)); } else if (u_strcmp(ubuf,itemPtr->expPattern)!=0) { @@ -3433,6 +3438,40 @@ } } unum_close(unum); + } +} + +static void TestSciNotationMaxFracCap(void) { + static const UChar* pat1 = u"#.##E+00;-#.##E+00"; + UErrorCode status = U_ZERO_ERROR; + UNumberFormat* unum = unum_open(UNUM_PATTERN_DECIMAL, pat1, -1, "en_US", NULL, &status); + if ( U_FAILURE(status) ) { + log_data_err("unum_open UNUM_PATTERN_DECIMAL with scientific pattern for \"en_US\" fails with %s\n", u_errorName(status)); + } else { + double value; + UChar ubuf[kUBufMax]; + char bbuf[kBBufMax]; + int32_t ulen; + + unum_setAttribute(unum, UNUM_MIN_FRACTION_DIGITS, 0); + unum_setAttribute(unum, UNUM_MAX_FRACTION_DIGITS, 2147483647); + ulen = unum_toPattern(unum, FALSE, ubuf, kUBufMax, &status); + if ( U_SUCCESS(status) ) { + u_austrncpy(bbuf, ubuf, kUBufMax); + log_info("unum_toPattern (%d): %s\n", ulen, bbuf); + } + + for (value = 10.0; value < 1000000000.0; value *= 10.0) { + status = U_ZERO_ERROR; + ulen = unum_formatDouble(unum, value, ubuf, kUBufMax, NULL, &status); + if ( U_FAILURE(status) ) { + log_err("unum_formatDouble value %.1f status %s\n", value, u_errorName(status)); + } else if (u_strncmp(ubuf,u"1E+0",4) != 0) { + u_austrncpy(bbuf, ubuf, kUBufMax); + log_err("unum_formatDouble value %.1f expected result to begin with 1E+0, got %s\n", value, bbuf); + } + } + unum_close(unum); } } diff -Nru icu-64.2/source/test/cintltst/crelativedateformattest.c icu-65.1/source/test/cintltst/crelativedateformattest.c --- icu-64.2/source/test/cintltst/crelativedateformattest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/crelativedateformattest.c 2019-10-03 11:16:41.000000000 +0000 @@ -171,8 +171,8 @@ "2 minutes ago", "2 minutes ago", /* -2 */ "1 minute ago", "1 minute ago", /* -1 */ "0.7 minutes ago", "0.7 minutes ago", /* -0.7 */ - "0 minutes ago", "0 minutes ago", /* -0 */ - "in 0 minutes", "in 0 minutes", /* 0 */ + "this minute", "0 minutes ago", /* -0 */ + "this minute", "in 0 minutes", /* 0 */ "in 0.7 minutes", "in 0.7 minutes", /* 0.7 */ "in 1 minute", "in 1 minute", /* 1 */ "in 2 minutes", "in 2 minutes", /* 2 */ @@ -186,8 +186,8 @@ {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "2 minutes ago", "2 minutes ago", -2 */ {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "1 minute ago", "1 minute ago", -1 */ {UDAT_REL_NUMERIC_FIELD, 0, 3}, {UDAT_REL_NUMERIC_FIELD, 0, 3}, /* "0.7 minutes ago", "0.7 minutes ago", -0.7 */ - {UDAT_REL_NUMERIC_FIELD, 0, 1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "0 minutes ago", "0 minutes ago", -0 */ - {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 0 minutes", "in 0 minutes", 0 */ + {-1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 0, 1}, /* "this minute", "0 minutes ago", -0 */ + {-1, -1, -1}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "this minute", "in 0 minutes", 0 */ {UDAT_REL_NUMERIC_FIELD, 3, 6}, {UDAT_REL_NUMERIC_FIELD, 3, 6}, /* "in 0.7 minutes", "in 0.7 minutes", 0.7 */ {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 1 minute", "in 1 minute", 1 */ {UDAT_REL_NUMERIC_FIELD, 3, 4}, {UDAT_REL_NUMERIC_FIELD, 3, 4}, /* "in 2 minutes", "in 2 minutes", 2 */ diff -Nru icu-64.2/source/test/cintltst/crestst.c icu-65.1/source/test/cintltst/crestst.c --- icu-64.2/source/test/cintltst/crestst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/crestst.c 2019-10-03 11:16:41.000000000 +0000 @@ -55,9 +55,23 @@ typedef enum E_Where E_Where; /*****************************************************************************/ -#define CONFIRM_EQ(actual,expected) if (u_strcmp(expected,actual)==0){ record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); } - -#define CONFIRM_ErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); } +#define CONFIRM_EQ(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if (u_strcmp(expected,actual)==0) { \ + record_pass(); \ + } else { \ + record_fail(); \ + log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define CONFIRM_ErrorCode(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)==(actual)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); \ + } \ +} UPRV_BLOCK_MACRO_END /* Array of our test objects */ @@ -534,7 +548,7 @@ } ures_close(idna_rules); - errorCode = U_USING_FALLBACK_WARNING;; + errorCode = U_USING_FALLBACK_WARNING; idna_rules=ures_openDirect("testdata", "idna_rules", &errorCode); if(U_FAILURE(errorCode)) { log_data_err("ures_openDirect(\"idna_rules\") failed when U_USING_FALLBACK_WARNING was set prior to call: %s\n", u_errorName(errorCode)); diff -Nru icu-64.2/source/test/cintltst/creststn.c icu-65.1/source/test/cintltst/creststn.c --- icu-64.2/source/test/cintltst/creststn.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/creststn.c 2019-10-03 11:16:41.000000000 +0000 @@ -62,7 +62,7 @@ } /* Assume rand has at least 12 bits of precision */ - for (i=0; i> 4); return l; } @@ -132,10 +132,38 @@ typedef enum E_Where E_Where; /*****************************************************************************/ -#define CONFIRM_EQ(actual,expected) if (u_strcmp(expected,actual)==0){ record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); } -#define CONFIRM_INT_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of %d\n", action, actual, expected); } -#define CONFIRM_INT_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of x >= %d\n", action, actual, expected); } -#define CONFIRM_INT_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of x != %d\n", action, actual, expected); } +#define CONFIRM_EQ(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if (u_strcmp(expected,actual)==0) { \ + record_pass(); \ + } else { \ + record_fail(); \ + log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_INT_EQ(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)==(actual)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + log_err("%s returned %d instead of %d\n", action, actual, expected); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_INT_GE(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((actual)>=(expected)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + log_err("%s returned %d instead of x >= %d\n", action, actual, expected); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_INT_NE(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)!=(actual)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + log_err("%s returned %d instead of x != %d\n", action, actual, expected); \ + } \ +} UPRV_BLOCK_MACRO_END /*#define CONFIRM_ErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); } */ static void CONFIRM_ErrorCode(UErrorCode actual,UErrorCode expected) @@ -2137,7 +2165,7 @@ UResourceBundle* tResB; UResourceBundle* zoneResource; const UChar* version = NULL; - static const UChar versionStr[] = { 0x0032, 0x002E, 0x0031, 0x002E, 0x0034, 0x0037, 0x002E, 0x0038, 0x0032, 0x0000}; // 2.1.47.82 in nn_NO + static const UChar versionStr[] = u"36"; // 36 in nn_NO if(err != U_ZERO_ERROR){ log_data_err("Expected U_ZERO_ERROR when trying to test no_NO_NY aliased to nn_NO for Version err=%s\n",u_errorName(err)); @@ -2946,7 +2974,7 @@ } /* verify NUL-termination */ - if((p8 != buffer8 || length8 < sizeof(buffer8)) && s8[length8] != 0) { + if((p8 != buffer8 || length8 < (int32_t)sizeof(buffer8)) && s8[length8] != 0) { log_err("ures_getUTF8String(%p, %ld, '%s') did not NUL-terminate\n", resB, (long)idx, key); } diff -Nru icu-64.2/source/test/cintltst/cstrcase.c icu-65.1/source/test/cintltst/cstrcase.c --- icu-64.2/source/test/cintltst/cstrcase.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cstrcase.c 2019-10-03 11:16:41.000000000 +0000 @@ -442,7 +442,7 @@ /* test simple case folding */ p=simple; - for(i=0; i?_"; +static const UChar *asciiInvChars = + u"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + u"abcdefghijklmnopqrstuvwxyz" + u"0123456789 \"%&'()*+,-./:;<=>?_"; + +static void +TestLocaleAtSign() { + static const char *invLocale = "de-Latn_DE@PHONEBOOK"; + for (int32_t i = 0;; ++i) { + char ic = invLocale[i]; + if (ic == 0) { break; } + UBool expected = i == 10; + UBool actual = uprv_isAtSign(ic); + if (actual != expected) { + log_err("uprv_isAtSign('%c')=%d is wrong\n", ic, (int)actual); + } + } +} + +// The at sign is not an invariant character. +static void +TestNoInvariantAtSign() { + for (int32_t i = 0;; ++i) { + char ic = nativeInvChars[i]; + UBool actual = uprv_isAtSign(ic); + if (actual) { + log_err("uprv_isAtSign(invariant '%c')=TRUE is wrong\n", ic); + } + if (ic == 0) { break; } + } +} + +static void +TestInvCharToAscii() { + for (int32_t i = 0;; ++i) { + char ic = nativeInvChars[i]; + uint8_t ac = asciiInvChars[i]; + uint8_t actual = uprv_invCharToAscii(ic); + if (actual != ac) { + log_err("uprv_invCharToAscii('%c') did not convert to ASCII 0x%02x\n", ic, (int)ac); + } + if (ic == 0) { break; } + } +} diff -Nru icu-64.2/source/test/cintltst/cucdtst.c icu-65.1/source/test/cintltst/cucdtst.c --- icu-64.2/source/test/cintltst/cucdtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/cucdtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -963,6 +963,7 @@ char *fields[][2], int32_t fieldCount, UErrorCode *pErrorCode) { + (void)fieldCount; // suppress compiler warnings about unused variable char buffer[100]; const char *d; char *end; @@ -1022,7 +1023,7 @@ /* get BiDi category, field 4 */ *fields[4][1]=0; i=MakeDir(fields[4][0]); - if(i!=u_charDirection(c) || i!=u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)) { + if(i!=(int32_t)u_charDirection(c) || i!=u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)) { log_err("error: u_charDirection(U+%04lx)==%u instead of %u (%s)\n", c, u_charDirection(c), MakeDir(fields[4][0]), fields[4][0]); } @@ -1217,6 +1218,8 @@ static UBool U_CALLCONV enumDefaultsRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) { + (void)context; // suppress compiler warnings about unused variable + /* default Bidi classes for unassigned code points, from the DerivedBidiClass.txt header */ static const int32_t defaultBidi[][2]={ /* { limit, class } */ { 0x0590, U_LEFT_TO_RIGHT }, @@ -1292,7 +1295,7 @@ } if( u_charDirection(c)!=shouldBeDir || - u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)!=shouldBeDir + (UCharDirection)u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)!=shouldBeDir ) { log_err("error: u_charDirection(unassigned/PUA U+%04lx)=%s should be %s\n", c, dirStrings[u_charDirection(c)], dirStrings[shouldBeDir]); @@ -1651,28 +1654,28 @@ uint32_t code; const char *name, *oldName, *extName, *alias; } names[]={ - {0x0061, "LATIN SMALL LETTER A", "", "LATIN SMALL LETTER A"}, + {0x0061, "LATIN SMALL LETTER A", "", "LATIN SMALL LETTER A", NULL}, {0x01a2, "LATIN CAPITAL LETTER OI", "", "LATIN CAPITAL LETTER OI", "LATIN CAPITAL LETTER GHA"}, {0x0284, "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK", "", - "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK" }, + "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK", NULL}, {0x0fd0, "TIBETAN MARK BSKA- SHOG GI MGO RGYAN", "", "TIBETAN MARK BSKA- SHOG GI MGO RGYAN", "TIBETAN MARK BKA- SHOG GI MGO RGYAN"}, - {0x3401, "CJK UNIFIED IDEOGRAPH-3401", "", "CJK UNIFIED IDEOGRAPH-3401" }, - {0x7fed, "CJK UNIFIED IDEOGRAPH-7FED", "", "CJK UNIFIED IDEOGRAPH-7FED" }, - {0xac00, "HANGUL SYLLABLE GA", "", "HANGUL SYLLABLE GA" }, - {0xd7a3, "HANGUL SYLLABLE HIH", "", "HANGUL SYLLABLE HIH" }, - {0xd800, "", "", "" }, - {0xdc00, "", "", "" }, - {0xff08, "FULLWIDTH LEFT PARENTHESIS", "", "FULLWIDTH LEFT PARENTHESIS" }, - {0xffe5, "FULLWIDTH YEN SIGN", "", "FULLWIDTH YEN SIGN" }, - {0xffff, "", "", "" }, + {0x3401, "CJK UNIFIED IDEOGRAPH-3401", "", "CJK UNIFIED IDEOGRAPH-3401", NULL}, + {0x7fed, "CJK UNIFIED IDEOGRAPH-7FED", "", "CJK UNIFIED IDEOGRAPH-7FED", NULL}, + {0xac00, "HANGUL SYLLABLE GA", "", "HANGUL SYLLABLE GA", NULL}, + {0xd7a3, "HANGUL SYLLABLE HIH", "", "HANGUL SYLLABLE HIH", NULL}, + {0xd800, "", "", "", NULL}, + {0xdc00, "", "", "", NULL}, + {0xff08, "FULLWIDTH LEFT PARENTHESIS", "", "FULLWIDTH LEFT PARENTHESIS", NULL}, + {0xffe5, "FULLWIDTH YEN SIGN", "", "FULLWIDTH YEN SIGN", NULL}, + {0xffff, "", "", "", NULL}, {0x1d0c5, "BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS", "", "BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS", "BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA VASIS"}, - {0x23456, "CJK UNIFIED IDEOGRAPH-23456", "", "CJK UNIFIED IDEOGRAPH-23456" } + {0x23456, "CJK UNIFIED IDEOGRAPH-23456", "", "CJK UNIFIED IDEOGRAPH-23456", NULL} }; static UBool @@ -1908,7 +1911,8 @@ uset_add, uset_addRange, uset_addString, - NULL /* don't need remove() */ + NULL, /* don't need remove() */ + NULL /* don't need removeRange() */ }; sa.set=set; uprv_getCharNameCharacters(&sa); @@ -3418,6 +3422,8 @@ caseFoldingLineFn(void *context, char *fields[][2], int32_t fieldCount, UErrorCode *pErrorCode) { + (void)fieldCount; // suppress compiler warnings about unused variable + CaseFoldingData *pData=(CaseFoldingData *)context; char *end; UChar full[32]; @@ -3525,7 +3531,7 @@ static void TestCaseFolding() { - CaseFoldingData data={ NULL }; + CaseFoldingData data={ NULL, 0, 0, {0}, 0, 0 }; char *fields[3][2]; UErrorCode errorCode; diff -Nru icu-64.2/source/test/cintltst/currtest.c icu-65.1/source/test/cintltst/currtest.c --- icu-64.2/source/test/cintltst/currtest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/currtest.c 2019-10-03 11:16:41.000000000 +0000 @@ -122,7 +122,7 @@ originalCount = uenum_count(en, &status); for (count=0;;count++) { const char *str = uenum_next(en, &len, &status); - if (str == NULL || len != expectedLen || strlen(str) != expectedLen) { + if (str == NULL || len != expectedLen || (int32_t)strlen(str) != expectedLen) { break; } } diff -Nru icu-64.2/source/test/cintltst/custrtrn.c icu-65.1/source/test/cintltst/custrtrn.c --- icu-64.2/source/test/cintltst/custrtrn.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/custrtrn.c 2019-10-03 11:16:41.000000000 +0000 @@ -748,7 +748,7 @@ withTrail16, u_strlen(withTrail16), 0xfffd, &numSubstitutions, &err); - if(U_FAILURE(err) || u8DestLen!=uprv_strlen((const char *)withTrail8SubFFFD) || + if(U_FAILURE(err) || u8DestLen!=(int32_t)uprv_strlen((const char *)withTrail8SubFFFD) || 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen+1) || numSubstitutions!=1) { log_err("error: u_strToUTF8WithSub(length) failed\n"); @@ -763,7 +763,7 @@ withTrail16, -1, 0x1a, &numSubstitutions, &err); - if(U_FAILURE(err) || u8DestLen!=uprv_strlen((const char *)withTrail8Sub1A) || + if(U_FAILURE(err) || u8DestLen!=(int32_t)uprv_strlen((const char *)withTrail8Sub1A) || 0!=uprv_memcmp((const char *)withTrail8Sub1A, out8, u8DestLen+1) || numSubstitutions!=1) { log_err("error: u_strToUTF8WithSub(NUL termination) failed\n"); @@ -778,7 +778,7 @@ withTrail16, -1, 0xfffd, &numSubstitutions, &err); - if(err!=U_BUFFER_OVERFLOW_ERROR || u8DestLen!=uprv_strlen((const char *)withTrail8SubFFFD) || + if(err!=U_BUFFER_OVERFLOW_ERROR || u8DestLen!=(int32_t)uprv_strlen((const char *)withTrail8SubFFFD) || numSubstitutions!=1) { log_err("error: u_strToUTF8WithSub(preflight/NUL termination) failed\n"); } diff -Nru icu-64.2/source/test/cintltst/hpmufn.c icu-65.1/source/test/cintltst/hpmufn.c --- icu-64.2/source/test/cintltst/hpmufn.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/hpmufn.c 2019-10-03 11:16:41.000000000 +0000 @@ -42,17 +42,20 @@ static int32_t gMutexFailures = 0; -#define TEST_STATUS(status, expected) \ -if (status != expected) { \ -log_err_status(status, "FAIL at %s:%d. Actual status = \"%s\"; Expected status = \"%s\"\n", \ - __FILE__, __LINE__, u_errorName(status), u_errorName(expected)); gMutexFailures++; } +#define TEST_STATUS(status, expected) UPRV_BLOCK_MACRO_BEGIN { \ + if (status != expected) { \ + log_err_status(status, "FAIL at %s:%d. Actual status = \"%s\"; Expected status = \"%s\"\n", \ + __FILE__, __LINE__, u_errorName(status), u_errorName(expected)); gMutexFailures++; \ + } \ +} UPRV_BLOCK_MACRO_END -#define TEST_ASSERT(expr) \ -if (!(expr)) { \ - log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \ - gMutexFailures++; \ -} +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(expr)) { \ + log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \ + gMutexFailures++; \ + } \ +} UPRV_BLOCK_MACRO_END /* These tests do cleanup and reinitialize ICU in the course of their operation. @@ -83,6 +86,7 @@ const void *gContext; static void * U_CALLCONV myMemAlloc(const void *context, size_t size) { + (void)context; // suppress compiler warnings about unused variable char *retPtr = (char *)malloc(size+sizeof(ctest_AlignedMemory)); if (retPtr != NULL) { retPtr += sizeof(ctest_AlignedMemory); @@ -92,6 +96,7 @@ } static void U_CALLCONV myMemFree(const void *context, void *mem) { + (void)context; // suppress compiler warnings about unused variable char *freePtr = (char *)mem; if (freePtr != NULL) { freePtr -= sizeof(ctest_AlignedMemory); @@ -102,6 +107,7 @@ static void * U_CALLCONV myMemRealloc(const void *context, void *mem, size_t size) { + (void)context; // suppress compiler warnings about unused variable char *p = (char *)mem; char *retPtr; diff -Nru icu-64.2/source/test/cintltst/nccbtst.c icu-65.1/source/test/cintltst/nccbtst.c --- icu-64.2/source/test/cintltst/nccbtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/nccbtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -914,7 +914,7 @@ if(!testConvertToUnicode(sampleText1, UPRV_LENGTHOF(sampleText1), expected1, UPRV_LENGTHOF(expected1),"utf8", UCNV_TO_U_CALLBACK_SKIP, offsets1, NULL, 0 )) - log_err("utf8->u with skip did not match.\n");; + log_err("utf8->u with skip did not match.\n"); } log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_SKIP \n"); @@ -1330,7 +1330,7 @@ if(!testConvertToUnicode(sampleText1, UPRV_LENGTHOF(sampleText1), expected1, UPRV_LENGTHOF(expected1),"utf8", UCNV_TO_U_CALLBACK_STOP, offsets1, NULL, 0 )) - log_err("utf8->u with stop did not match.\n");; + log_err("utf8->u with stop did not match.\n"); } log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_STOP \n"); { @@ -1341,7 +1341,7 @@ if(!testConvertToUnicode(sampleText1, UPRV_LENGTHOF(sampleText1), expected1, UPRV_LENGTHOF(expected1),"SCSU", UCNV_TO_U_CALLBACK_STOP, offsets1, NULL, 0 )) - log_err("scsu->u with stop did not match.\n");; + log_err("scsu->u with stop did not match.\n"); } } @@ -1620,7 +1620,7 @@ if(!testConvertToUnicode(sampleText1, UPRV_LENGTHOF(sampleText1), expected1, UPRV_LENGTHOF(expected1),"utf8", UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0 )) - log_err("utf8->u with substitute did not match.\n");; + log_err("utf8->u with substitute did not match.\n"); } log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_SUBSTITUTE \n"); { @@ -1631,7 +1631,7 @@ if(!testConvertToUnicode(sampleText1, UPRV_LENGTHOF(sampleText1), expected1, UPRV_LENGTHOF(expected1),"SCSU", UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0 )) - log_err("scsu->u with stop did not match.\n");; + log_err("scsu->u with stop did not match.\n"); } #if !UCONFIG_NO_LEGACY_CONVERSION diff -Nru icu-64.2/source/test/cintltst/ncnvtst.c icu-65.1/source/test/cintltst/ncnvtst.c --- icu-64.2/source/test/cintltst/ncnvtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/ncnvtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -699,7 +699,7 @@ offset16 = 0; offset8 = 0; while(currCh <= UNICODE_LIMIT - && offset16 < (MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN) + && offset16 < ((int32_t)(MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN)) && offset8 < (MAX_LENGTH - MAX_UTF8_LEN)) { if (currCh == SURROGATE_HIGH_START) { @@ -770,8 +770,8 @@ offset16 = 0; offset32 = 0; while(currCh <= UNICODE_LIMIT - && offset16 < (MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN) - && offset32 < (MAX_LENGTH/sizeof(UChar32) - MAX_UTF32_LEN)) + && offset16 < ((int32_t)(MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN)) + && offset32 < ((int32_t)(MAX_LENGTH/sizeof(UChar32) - MAX_UTF32_LEN))) { if (currCh == SURROGATE_HIGH_START) { currCh = SURROGATE_LOW_END + 1; /* Skip surrogate range */ @@ -968,7 +968,7 @@ if(!testConvertToU(sampleText1, sizeof(sampleText1), expected1, UPRV_LENGTHOF(expected1),"utf8", UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1,FALSE)) - log_err("utf8->u with substitute did not match.\n");; + log_err("utf8->u with substitute did not match.\n"); } #if !UCONFIG_NO_LEGACY_CONVERSION diff -Nru icu-64.2/source/test/cintltst/nucnvtst.c icu-65.1/source/test/cintltst/nucnvtst.c --- icu-64.2/source/test/cintltst/nucnvtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/nucnvtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -3095,17 +3095,18 @@ UChar *uTarget; char *cTarget; const char *cTargetLimit; - char *cBuf; - UChar *uBuf,*test; + char *cBuf = NULL; + UChar *uBuf = NULL; + UChar *test; int32_t uBufSize = 120; UErrorCode errorCode=U_ZERO_ERROR; - UConverter *cnv; + UConverter *cnv = NULL; int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); int32_t* myOff= offsets; cnv=ucnv_open("HZ", &errorCode); if(U_FAILURE(errorCode)) { log_data_err("Unable to open HZ converter: %s\n", u_errorName(errorCode)); - return; + goto cleanup; } uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); @@ -3119,7 +3120,7 @@ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); if(U_FAILURE(errorCode)){ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); - return; + goto cleanup; } cSource = cBuf; cSourceLimit =cTarget; @@ -3128,7 +3129,7 @@ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); if(U_FAILURE(errorCode)){ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); - return; + goto cleanup; } uSource = (const UChar*)in; while(uSource UCNV_IRREGULAR) { return; } diff -Nru icu-64.2/source/test/cintltst/putiltst.c icu-65.1/source/test/cintltst/putiltst.c --- icu-64.2/source/test/cintltst/putiltst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/putiltst.c 2019-10-03 11:16:41.000000000 +0000 @@ -36,7 +36,7 @@ int32_t m=-1; int32_t x4=x>>4; int32_t m1=m>>1; - UBool signedRightShiftIsArithmetic= x4==0xffff5fff && m1==-1; + UBool signedRightShiftIsArithmetic= (x4==(int32_t)0xffff5fff && m1==-1); if(signedRightShiftIsArithmetic==U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC) { log_info("signed right shift is Arithmetic Shift Right: %d\n", signedRightShiftIsArithmetic); diff -Nru icu-64.2/source/test/cintltst/reapits.c icu-65.1/source/test/cintltst/reapits.c --- icu-64.2/source/test/cintltst/reapits.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/reapits.c 2019-10-03 11:16:41.000000000 +0000 @@ -33,11 +33,17 @@ #include "cintltst.h" #include "cmemory.h" -#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ -log_data_err("Failure at file %s:%d - error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status));}} - -#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ -log_err("Test Failure at file %s:%d - ASSERT(%s) failed.\n", __FILE__, __LINE__, #expr);}} +#define TEST_ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + log_data_err("Failure at file %s:%d - error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + log_err("Test Failure at file %s:%d - ASSERT(%s) failed.\n", __FILE__, __LINE__, #expr); \ + } \ +} UPRV_BLOCK_MACRO_END /* * TEST_SETUP and TEST_TEARDOWN @@ -50,7 +56,7 @@ * Put arbitrary test code between SETUP and TEARDOWN. * 're" is the compiled, ready-to-go regular expression. */ -#define TEST_SETUP(pattern, testString, flags) { \ +#define TEST_SETUP(pattern, testString, flags) UPRV_BLOCK_MACRO_BEGIN { \ UChar *srcString = NULL; \ status = U_ZERO_ERROR; \ re = uregex_openC(pattern, flags, NULL, &status); \ @@ -60,14 +66,15 @@ u_uastrncpy(srcString, testString, testStringLen + 1); \ uregex_setText(re, srcString, -1, &status); \ TEST_ASSERT_SUCCESS(status); \ - if (U_SUCCESS(status)) { - + if (U_SUCCESS(status)) { \ + UPRV_BLOCK_MACRO_BEGIN {} UPRV_BLOCK_MACRO_END + #define TEST_TEARDOWN \ } \ TEST_ASSERT_SUCCESS(status); \ uregex_close(re); \ free(srcString); \ - } +} UPRV_BLOCK_MACRO_END /** @@ -691,7 +698,7 @@ /* SetRegion(), getRegion() do something */ - TEST_SETUP(".*", "0123456789ABCDEF", 0) + TEST_SETUP(".*", "0123456789ABCDEF", 0); UChar resultString[40]; TEST_ASSERT(uregex_regionStart(re, &status) == 0); TEST_ASSERT(uregex_regionEnd(re, &status) == 16); @@ -699,7 +706,7 @@ TEST_ASSERT(uregex_regionStart(re, &status) == 3); TEST_ASSERT(uregex_regionEnd(re, &status) == 6); TEST_ASSERT(uregex_findNext(re, &status)); - TEST_ASSERT(uregex_group(re, 0, resultString, UPRV_LENGTHOF(resultString), &status) == 3) + TEST_ASSERT(uregex_group(re, 0, resultString, UPRV_LENGTHOF(resultString), &status) == 3); TEST_ASSERT_STRING("345", resultString, TRUE); TEST_TEARDOWN; @@ -1322,7 +1329,7 @@ * to be invoked. The nested '+' operators give exponential time * behavior with increasing string length. */ - TEST_SETUP("((.)+\\2)+x", "aaaaaaaaaaaaaaaaaaab", 0) + TEST_SETUP("((.)+\\2)+x", "aaaaaaaaaaaaaaaaaaab", 0); callBackContext cbInfo = {4, 0, 0}; const void *pContext = &cbInfo; URegexMatchCallback *returnedFn = &TestCallbackFn; @@ -2253,10 +2260,16 @@ } static UBool U_CALLCONV FindCallback(const void* context , int64_t matchIndex) { + // suppress compiler warnings about unused variables + (void)context; + (void)matchIndex; return FALSE; } static UBool U_CALLCONV MatchCallback(const void *context, int32_t steps) { + // suppress compiler warnings about unused variables + (void)context; + (void)steps; return FALSE; } diff -Nru icu-64.2/source/test/cintltst/sorttest.c icu-65.1/source/test/cintltst/sorttest.c --- icu-64.2/source/test/cintltst/sorttest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/sorttest.c 2019-10-03 11:16:41.000000000 +0000 @@ -109,6 +109,7 @@ static void printLines(const Line *lines) { + (void)lines; // suppress compiler warnings about unused variable #if 0 int32_t i, j; for(i=0; i 0); TEST_ASSERT(gTraceExitCount > 0); diff -Nru icu-64.2/source/test/cintltst/trie2test.c icu-65.1/source/test/cintltst/trie2test.c --- icu-64.2/source/test/cintltst/trie2test.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/trie2test.c 2019-10-03 11:16:41.000000000 +0000 @@ -75,6 +75,7 @@ /* utrie2_enum() callback, modifies a value */ static uint32_t U_CALLCONV testEnumValue(const void *context, uint32_t value) { + (void)context; // suppress compiler warnings about unused variable return value^0x5555; } @@ -98,6 +99,7 @@ testTrieEnum(const char *testName, const UTrie2 *trie, const CheckRange checkRanges[], int32_t countCheckRanges) { + (void)testName; // suppress compiler warnings about unused variable /* skip over special values */ while(countCheckRanges>0 && checkRanges[0].limit<=0) { ++checkRanges; @@ -430,7 +432,7 @@ values[countValues++]=value; } /* write an illegal byte sequence */ - if(i8text, 1, length, f)) { + if (length != (int32_t)fread(tt->text, 1, length, f)) { log_err("error reading %ld bytes from test text file\n", (long)length); length = 0; uprv_free(tt->text); @@ -386,7 +386,7 @@ return; } if (!text_open(&text)) { - releaseAvailableNames();; + releaseAvailableNames(); } excluded_sets[0] = uset_openEmpty(); diff -Nru icu-64.2/source/test/cintltst/ucptrietest.c icu-65.1/source/test/cintltst/ucptrietest.c --- icu-64.2/source/test/cintltst/ucptrietest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/ucptrietest.c 2019-10-03 11:16:41.000000000 +0000 @@ -67,6 +67,7 @@ /* ucptrie_enum() callback, modifies a value */ static uint32_t U_CALLCONV testFilter(const void *context, uint32_t value) { + (void)context; // suppress compiler warnings about unused variable return value ^ 0x5555; } @@ -568,7 +569,7 @@ values[countValues++]=value; } /* write an illegal byte sequence */ - if(i8size>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && @@ -590,6 +591,7 @@ isAcceptable2(void *context, const char *type, const char *name, const UDataInfo *pInfo){ + (void)context; // suppress compiler warnings about unused variable UVersionInfo unicodeVersion; u_getUnicodeVersion(unicodeVersion); @@ -618,6 +620,7 @@ isAcceptable3(void *context, const char *type, const char *name, const UDataInfo *pInfo){ + (void)context; // suppress compiler warnings about unused variable if( pInfo->size>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && @@ -1233,7 +1236,8 @@ {0x31, 0x31, 0x31, 0x31}, /* dataFormat="1111" */ {0, 0, 0, 0}, /* formatVersion */ - {0, 0, 0, 0}} /* dataVersion */ + {0, 0, 0, 0}}, /* dataVersion */ + 0 }; #endif @@ -1395,6 +1399,7 @@ static void U_CALLCONV printError(void *context, const char *fmt, va_list args) { + (void)context; // suppress compiler warnings about unused variable vlog_info("[swap] ", fmt, args); log_err("\n"); /* Register error */ } diff -Nru icu-64.2/source/test/cintltst/uenumtst.c icu-65.1/source/test/cintltst/uenumtst.c --- icu-64.2/source/test/cintltst/uenumtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/uenumtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -59,11 +59,13 @@ static int32_t U_CALLCONV chArrayCount(UEnumeration *en, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable return cont->maxIndex; } static const UChar* U_CALLCONV chArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable if(cont->currIndex >= cont->maxIndex) { return NULL; } @@ -81,6 +83,7 @@ static const char* U_CALLCONV chArrayNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable if(cont->currIndex >= cont->maxIndex) { return NULL; } @@ -93,6 +96,7 @@ static void U_CALLCONV chArrayReset(UEnumeration *en, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable cont->currIndex = 0; } @@ -160,11 +164,13 @@ static int32_t U_CALLCONV uchArrayCount(UEnumeration *en, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable return ucont->maxIndex; } static const UChar* U_CALLCONV uchArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable if(ucont->currIndex >= ucont->maxIndex) { return NULL; } @@ -177,6 +183,7 @@ static void U_CALLCONV uchArrayReset(UEnumeration *en, UErrorCode *status) { + (void)status; // suppress compiler warnings about unused variable ucont->currIndex = 0; } @@ -343,7 +350,7 @@ log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__, line, i, c); } - if(len!=strlen(compareToChar[i])) { + if(len!=(int32_t)strlen(compareToChar[i])) { log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len); } else { log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__, line, i, len); @@ -380,7 +387,7 @@ log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, compareToChar[i]); } - if(len!=strlen(compareToChar[i])) { + if(len!=(int32_t)strlen(compareToChar[i])) { log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len); } else { log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len); diff -Nru icu-64.2/source/test/cintltst/uformattedvaluetst.c icu-65.1/source/test/cintltst/uformattedvaluetst.c --- icu-64.2/source/test/cintltst/uformattedvaluetst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/uformattedvaluetst.c 2019-10-03 11:16:41.000000000 +0000 @@ -213,6 +213,7 @@ UFieldCategory expectedCategory, const UFieldPosition* expectedFieldPositions, int32_t expectedFieldPositionsLength) { + (void)expectedFieldPositionsLength; // suppress compiler warnings about unused variable UErrorCode ec = U_ZERO_ERROR; checkFormattedValueString(message, fv, expectedString, &ec); if (U_FAILURE(ec)) { return; } @@ -244,6 +245,7 @@ const UChar* expectedString, const UFieldPositionWithCategory* expectedFieldPositions, int32_t length) { + (void)length; // suppress compiler warnings about unused variable UErrorCode ec = U_ZERO_ERROR; checkFormattedValueString(message, fv, expectedString, &ec); if (U_FAILURE(ec)) { return; } diff -Nru icu-64.2/source/test/cintltst/unumberformattertst.c icu-65.1/source/test/cintltst/unumberformattertst.c --- icu-64.2/source/test/cintltst/unumberformattertst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/unumberformattertst.c 2019-10-03 11:16:41.000000000 +0000 @@ -96,7 +96,7 @@ if (assertSuccessCheck("unumf_formatInt() failed", &ec, TRUE)) { // field position test: - UFieldPosition ufpos = {UNUM_DECIMAL_SEPARATOR_FIELD}; + UFieldPosition ufpos = {UNUM_DECIMAL_SEPARATOR_FIELD, 0, 0}; unumf_resultNextFieldPosition(uresult, &ufpos, &ec); assertIntEquals("Field position should be correct", 14, ufpos.beginIndex); assertIntEquals("Field position should be correct", 15, ufpos.endIndex); @@ -118,7 +118,7 @@ {UNUM_MEASURE_UNIT_FIELD, 18, 19} }; UFieldPosition actual; - for (int32_t i = 0; i < sizeof(expectedFields) / sizeof(*expectedFields); i++) { + for (int32_t i = 0; i < (int32_t)(sizeof(expectedFields) / sizeof(*expectedFields)); i++) { // Iterate using the UFieldPosition to hold state... UFieldPosition expected = expectedFields[i]; actual.field = ufieldpositer_next(ufpositer, &actual.beginIndex, &actual.endIndex); diff -Nru icu-64.2/source/test/cintltst/usrchtst.c icu-65.1/source/test/cintltst/usrchtst.c --- icu-64.2/source/test/cintltst/usrchtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/usrchtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -362,7 +362,7 @@ matchlength = search.size[count]; usearch_next(strsrch, &status); if (matchindex != usearch_getMatchedStart(strsrch) || - matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + matchlength != usearch_getMatchedLength(strsrch)) { char *str = toCharString(usearch_getText(strsrch, &textlength)); log_err("Text: %s\n", str); str = toCharString(usearch_getPattern(strsrch, &textlength)); @@ -375,7 +375,7 @@ count ++; if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != - (int32_t) matchlength || U_FAILURE(status) || + matchlength || U_FAILURE(status) || memcmp(matchtext, usearch_getText(strsrch, &textlength) + matchindex, matchlength * sizeof(UChar)) != 0) { @@ -404,7 +404,7 @@ matchlength = search.size[count]; usearch_previous(strsrch, &status); if (matchindex != usearch_getMatchedStart(strsrch) || - matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + matchlength != usearch_getMatchedLength(strsrch)) { char *str = toCharString(usearch_getText(strsrch, &textlength)); log_err("Text: %s\n", str); str = toCharString(usearch_getPattern(strsrch, &textlength)); @@ -416,7 +416,7 @@ } if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != - (int32_t) matchlength || U_FAILURE(status) || + matchlength || U_FAILURE(status) || memcmp(matchtext, usearch_getText(strsrch, &textlength) + matchindex, matchlength * sizeof(UChar)) != 0) { @@ -1255,10 +1255,10 @@ ucol_setStrength(usearch_getCollator(strsrch), search.strength); usearch_reset(strsrch); while (U_SUCCESS(status) && matchindex >= 0) { - uint32_t matchlength = search.size[count]; + int32_t matchlength = search.size[count]; usearch_next(strsrch, &status); if (matchindex != usearch_getMatchedStart(strsrch) || - matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + matchlength != usearch_getMatchedLength(strsrch)) { char *str = toCharString(usearch_getText(strsrch, &textlength)); log_err("Text: %s\n", str); @@ -1272,7 +1272,7 @@ usearch_setOffset(strsrch, matchindex + matchlength, &status); usearch_previous(strsrch, &status); if (matchindex != usearch_getMatchedStart(strsrch) || - matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + matchlength != usearch_getMatchedLength(strsrch)) { char *str = toCharString(usearch_getText(strsrch, &textlength)); log_err("Text: %s\n", str); @@ -1459,23 +1459,23 @@ } status = U_ZERO_ERROR; if (usearch_getMatchedText(strsrch, NULL, 0, &status) != - (int32_t)matchlength || U_SUCCESS(status)){ + matchlength || U_SUCCESS(status)){ log_err("Error pre-flighting match length\n"); } status = U_ZERO_ERROR; if (usearch_getMatchedText(strsrch, matchtext, 0, &status) != - (int32_t)matchlength || U_SUCCESS(status)){ + matchlength || U_SUCCESS(status)){ log_err("Error getting match text with buffer size 0\n"); } status = U_ZERO_ERROR; if (usearch_getMatchedText(strsrch, matchtext, matchlength, &status) - != (int32_t)matchlength || matchtext[matchlength - 1] == 0 || + != matchlength || matchtext[matchlength - 1] == 0 || U_FAILURE(status)){ log_err("Error getting match text with exact size\n"); } status = U_ZERO_ERROR; if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != - (int32_t) matchlength || U_FAILURE(status) || + matchlength || U_FAILURE(status) || memcmp(matchtext, usearch_getText(strsrch, &textlength) + matchindex, matchlength * sizeof(UChar)) != 0 || @@ -2313,10 +2313,10 @@ usearch_setText(strsrch, text, -1, &status); usearch_setPattern(strsrch, pattern, -1, &status); while (U_SUCCESS(status) && matchindex >= 0) { - uint32_t matchlength = search.size[count]; + int32_t matchlength = search.size[count]; usearch_next(strsrch, &status); if (matchindex != usearch_getMatchedStart(strsrch) || - matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + matchlength != usearch_getMatchedLength(strsrch)) { char *str = toCharString(usearch_getText(strsrch, &textlength)); log_err("Text: %s\n", str); @@ -2506,9 +2506,11 @@ } } -#define TEST_ASSERT(x) \ - {if (U_FAILURE(x)) {log_err_status(x, "%s:%d: FAIL: test assertion failure \n", __FILE__, __LINE__);\ - }} +#define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(x)) { \ + log_err_status(x, "%s:%d: FAIL: test assertion failure \n", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END static void TestSearchForNull(void) { UCollator *coll; @@ -2892,6 +2894,43 @@ return; } +static void TestUInt16Overflow(void) { + const int32_t uint16_overflow = UINT16_MAX + 1; + UChar* pattern = (UChar*)uprv_malloc(uint16_overflow * sizeof(UChar)); + if (pattern == NULL) + { + log_err("Err: uprv_malloc returned NULL\n"); + return; + } + u_memset(pattern, 'A', uint16_overflow); + UChar text[] = { 'B' }; + + UErrorCode errorCode = U_ZERO_ERROR; + UStringSearch* usearch = usearch_open(pattern, uint16_overflow, text, 1, "en-US", NULL, &errorCode); + + if (U_SUCCESS(errorCode)) + { + int32_t match = usearch_first(usearch, &errorCode); + + if (U_SUCCESS(errorCode)) + { + if (match != USEARCH_DONE) + { + log_err("Err: match was not expected, got %d\n", match); + } + } + else + { + log_err("usearch_first error %s\n", u_errorName(errorCode)); + } + usearch_close(usearch); + } + else + { + log_err("usearch_open error %s\n", u_errorName(errorCode)); + } + uprv_free(pattern); +} static void TestPCEBuffer_100df(void) { UChar search[] = @@ -3068,6 +3107,7 @@ addTest(root, &TestPCEBuffer_2surr, "tscoll/usrchtst/TestPCEBuffer/2_dfff"); addTest(root, &TestMatchFollowedByIgnorables, "tscoll/usrchtst/TestMatchFollowedByIgnorables"); addTest(root, &TestIndicPrefixMatch, "tscoll/usrchtst/TestIndicPrefixMatch"); + addTest(root, &TestUInt16Overflow, "tscoll/usrchtst/TestUInt16Overflow"); } #endif /* #if !UCONFIG_NO_COLLATION */ diff -Nru icu-64.2/source/test/cintltst/utexttst.c icu-65.1/source/test/cintltst/utexttst.c --- icu-64.2/source/test/cintltst/utexttst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/utexttst.c 2019-10-03 11:16:41.000000000 +0000 @@ -34,17 +34,21 @@ } -#define TEST_ASSERT(x) \ - {if ((x)==FALSE) {log_err("Test failure in file %s at line %d\n", __FILE__, __LINE__);\ - gFailed = TRUE;\ - }} +#define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \ + if ((x)==FALSE) { \ + log_err("Test failure in file %s at line %d\n", __FILE__, __LINE__); \ + gFailed = TRUE; \ + } \ +} UPRV_BLOCK_MACRO_END -#define TEST_SUCCESS(status) \ - {if (U_FAILURE(status)) {log_err("Test failure in file %s at line %d. Error = \"%s\"\n", \ - __FILE__, __LINE__, u_errorName(status)); \ - gFailed = TRUE;\ - }} +#define TEST_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + log_err("Test failure in file %s at line %d. Error = \"%s\"\n", \ + __FILE__, __LINE__, u_errorName(status)); \ + gFailed = TRUE; \ + } \ +} UPRV_BLOCK_MACRO_END diff -Nru icu-64.2/source/test/cintltst/utf8tst.c icu-65.1/source/test/cintltst/utf8tst.c --- icu-64.2/source/test/cintltst/utf8tst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/utf8tst.c 2019-10-03 11:16:41.000000000 +0000 @@ -35,7 +35,7 @@ * the macros below do not attempt to assemble such pairs. */ -#define L8_NEXT(s, i, length, c) { \ +#define L8_NEXT(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[(i)++]; \ if((c)>=0x80) { \ if(U8_IS_LEAD(c)) { \ @@ -44,9 +44,9 @@ (c)=U_SENTINEL; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END -#define L8_PREV(s, start, i, c) { \ +#define L8_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if((c)>=0x80) { \ if((c)<=0xbf) { \ @@ -55,7 +55,7 @@ (c)=U_SENTINEL; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /* -------------------------------------------------------------------------- */ @@ -884,13 +884,13 @@ } #if !U_HIDE_OBSOLETE_UTF_OLD_H setOffset=offset; - UTF8_SET_CHAR_LIMIT_SAFE(input,0, setOffset, sizeof(input)); + UTF8_SET_CHAR_LIMIT_SAFE(input,0, setOffset, (int32_t)sizeof(input)); if(setOffset != limit_safe[i]){ log_err("ERROR: UTF8_SET_CHAR_LIMIT_SAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_safe[i], setOffset); } #endif setOffset=offset; - U8_SET_CP_LIMIT(input,0, setOffset, sizeof(input)); + U8_SET_CP_LIMIT(input,0, setOffset, (int32_t)sizeof(input)); if(setOffset != limit_safe[i]){ log_err("ERROR: U8_SET_CP_LIMIT failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_safe[i], setOffset); } diff -Nru icu-64.2/source/test/cintltst/utmstest.c icu-65.1/source/test/cintltst/utmstest.c --- icu-64.2/source/test/cintltst/utmstest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/cintltst/utmstest.c 2019-10-03 11:16:41.000000000 +0000 @@ -52,7 +52,7 @@ } /* Assume rand has at least 12 bits of precision */ - for (i = 0; i < sizeof(ran); i += 1) { + for (i = 0; i < (int32_t)sizeof(ran); i += 1) { ((char*)&ran)[i] = (char)((rand() & 0x0FF0) >> 4); } diff -Nru icu-64.2/source/test/depstest/dependencies.txt icu-65.1/source/test/depstest/dependencies.txt --- icu-64.2/source/test/depstest/dependencies.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/depstest/dependencies.txt 2019-10-03 11:16:41.000000000 +0000 @@ -20,7 +20,7 @@ c_strings c_string_formatting int_functions floating_point trigonometry stdlib_qsort - pthread system_locale + system_locale stdio_input stdio_output file_io readlink_function dir_io mmap_functions dlfcn # C++ cplusplus iostream @@ -82,10 +82,6 @@ group: stdlib_qsort qsort -group: pthread - pthread_mutex_init pthread_mutex_destroy pthread_mutex_lock pthread_mutex_unlock - pthread_cond_wait pthread_cond_broadcast pthread_cond_signal - group: system_locale getenv nl_langinfo setlocale newlocale freelocale @@ -94,7 +90,7 @@ group: stdio_input fopen fclose fgets fread fseek ftell rewind feof fileno # Additional symbols in an optimized build. - __fgets_chk __fread_chk + __fgets_chk __fread_chk fread_unlocked group: stdio_output fflush fwrite @@ -188,7 +184,7 @@ uinit utypes errorcode icuplug platform - localebuilder + localebuilder localematcher group: pluralmap # TODO: Move to i18n library, ticket #11926. @@ -635,7 +631,7 @@ # We can probably only disentangle basic locale ID handling from resource bundle code # by hardcoding all of the locale ID data. locid.o locmap.o wintz.o - # Do we need class LocaleBased? http://bugs.icu-project.org/trac/ticket/8608 + # Do we need class LocaleBased? https://unicode-org.atlassian.net/browse/ICU-8608 locbased.o loclikely.o deps @@ -643,18 +639,45 @@ sort stringenumeration uhash uvector uscript_props propname bytesinkutil + errorcode group: localebuilder localebuilder.o deps resourcebundle +group: localematcher + localematcher.o + deps + localebuilder localeprioritylist loclikelysubtags locdistance lsr + +group: localeprioritylist + localeprioritylist.o + deps + resourcebundle + +group: locdistance + locdistance.o + deps + loclikelysubtags + +group: loclikelysubtags + loclikelysubtags.o + deps + lsr resourcebundle + +group: lsr + lsr.o + deps + platform + group: udata - udata.o ucmndata.o udatamem.o + udata.o ucmndata.o udatamem.o restrace.o umapfile.o deps uhash platform stubdata file_io mmap_functions + icu_utility group: unifiedcache unifiedcache.o @@ -831,7 +854,7 @@ # The "platform" group has no ICU dependencies. PIC system_misc system_debug malloc_functions ubsan c_strings c_string_formatting - floating_point pthread system_locale + floating_point system_locale stdio_input readlink_function dir_io dlfcn # Move related code into icuplug.c? cplusplus @@ -853,7 +876,7 @@ group: region region.o uregion.o deps - formatting # Temporary, TODO: Ticket #9982 class Region should use low-level ASCII-integer functions, and probably be moved to the common library. + icu_utility resourcebundle uvector uclean_i18n @@ -925,14 +948,17 @@ resourcebundle simpleformatter format uclean_i18n formatted_value_iterimpl group: double_conversion - double-conversion.o double-conversion-bignum.o double-conversion-bignum-dtoa.o - double-conversion-cached-powers.o double-conversion-diy-fp.o - double-conversion-fast-dtoa.o double-conversion-strtod.o + double-conversion-bignum.o double-conversion-double-to-string.o + double-conversion-bignum-dtoa.o double-conversion-cached-powers.o + double-conversion-string-to-double.o double-conversion-fast-dtoa.o + double-conversion-strtod.o deps platform group: number_representation - number_decimalquantity.o number_stringbuilder.o numparse_stringsegment.o number_utils.o + number_decimalquantity.o string_segment.o number_utils.o + # TODO(ICU-20429) Move formatted_string_builder to its own unit. + formatted_string_builder.o deps decnumber double_conversion # for trimming whitespace around fields @@ -1020,6 +1046,7 @@ trigonometry # for astro.o sharedbreakiterator # for reldatefmt.o uclean_i18n + region group: sharedbreakiterator sharedbreakiterator.o diff -Nru icu-64.2/source/test/depstest/depstest.py icu-65.1/source/test/depstest/depstest.py --- icu-64.2/source/test/depstest/depstest.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/depstest/depstest.py 2019-10-03 11:16:41.000000000 +0000 @@ -105,10 +105,13 @@ # in a limited (not transitive) context. List of (file_name, symbol) # TODO: Move this data to dependencies.txt? allowed_errors = ( - ("common/umutex.o", "operator new(unsigned long)"), - ("common/umutex.o", "std::__throw_bad_alloc()"), ("common/umutex.o", "std::__throw_system_error(int)"), ("common/umutex.o", "std::uncaught_exception()"), + ("common/umutex.o", "std::__once_callable"), + ("common/umutex.o", "std::__once_call"), + ("common/umutex.o", "__once_proxy"), + ("common/umutex.o", "__tls_get_addr"), + ("common/unifiedcache.o", "std::__throw_system_error(int)"), ) def _Resolve(name, parents): diff -Nru icu-64.2/source/test/fuzzer/break_iterator_fuzzer.cc icu-65.1/source/test/fuzzer/break_iterator_fuzzer.cc --- icu-64.2/source/test/fuzzer/break_iterator_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/break_iterator_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include -#include -#include -#include -#include -#include "fuzzer_utils.h" -#include "unicode/brkiter.h" -#include "unicode/utext.h" - -IcuEnvironment* env = new IcuEnvironment(); - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - UErrorCode status = U_ZERO_ERROR; - uint8_t rnd8 = 0; - uint16_t rnd16 = 0; - - if (size < 3) { - return 0; - } - // Extract one and two bytes from fuzzer data for random selection purpose. - rnd8 = *data; - data++; - rnd16 = *(reinterpret_cast(data)); - data = data + 2; - size = size - 3; - - size_t unistr_size = size/2; - std::unique_ptr fuzzbuff(new char16_t[unistr_size]); - std::memcpy(fuzzbuff.get(), data, unistr_size * 2); - - UText* fuzzstr = utext_openUChars(nullptr, fuzzbuff.get(), unistr_size, &status); - - const icu::Locale& locale = GetRandomLocale(rnd16); - - std::unique_ptr bi; - - switch (rnd8 % 5) { - case 0: - bi.reset(icu::BreakIterator::createWordInstance(locale, status)); - break; - case 1: - bi.reset(icu::BreakIterator::createLineInstance(locale, status)); - break; - case 2: - bi.reset(icu::BreakIterator::createCharacterInstance(locale, status)); - break; - case 3: - bi.reset(icu::BreakIterator::createSentenceInstance(locale, status)); - break; - case 4: - bi.reset(icu::BreakIterator::createTitleInstance(locale, status)); - break; - } - - bi->setText(fuzzstr, status); - - if (U_FAILURE(status)) { - utext_close(fuzzstr); - return 0; - } - - for (int32_t p = bi->first(); p != icu::BreakIterator::DONE; p = bi->next()) {} - - utext_close(fuzzstr); - return 0; -} - diff -Nru icu-64.2/source/test/fuzzer/break_iterator_fuzzer.cpp icu-65.1/source/test/fuzzer/break_iterator_fuzzer.cpp --- icu-64.2/source/test/fuzzer/break_iterator_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/break_iterator_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,71 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include +#include +#include +#include +#include +#include +#include "fuzzer_utils.h" +#include "unicode/brkiter.h" +#include "unicode/utext.h" + +IcuEnvironment* env = new IcuEnvironment(); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UErrorCode status = U_ZERO_ERROR; + uint8_t rnd8 = 0; + uint16_t rnd16 = 0; + + if (size < 3) { + return 0; + } + // Extract one and two bytes from fuzzer data for random selection purpose. + rnd8 = *data; + data++; + rnd16 = *(reinterpret_cast(data)); + data = data + 2; + size = size - 3; + + size_t unistr_size = size/2; + std::unique_ptr fuzzbuff(new char16_t[unistr_size]); + std::memcpy(fuzzbuff.get(), data, unistr_size * 2); + + UText* fuzzstr = utext_openUChars(nullptr, fuzzbuff.get(), unistr_size, &status); + + const icu::Locale& locale = GetRandomLocale(rnd16); + + std::unique_ptr bi; + + switch (rnd8 % 5) { + case 0: + bi.reset(icu::BreakIterator::createWordInstance(locale, status)); + break; + case 1: + bi.reset(icu::BreakIterator::createLineInstance(locale, status)); + break; + case 2: + bi.reset(icu::BreakIterator::createCharacterInstance(locale, status)); + break; + case 3: + bi.reset(icu::BreakIterator::createSentenceInstance(locale, status)); + break; + case 4: + bi.reset(icu::BreakIterator::createTitleInstance(locale, status)); + break; + } + + bi->setText(fuzzstr, status); + + if (U_FAILURE(status)) { + utext_close(fuzzstr); + return 0; + } + + for (int32_t p = bi->first(); p != icu::BreakIterator::DONE; p = bi->next()) {} + + utext_close(fuzzstr); + return 0; +} + diff -Nru icu-64.2/source/test/fuzzer/collator_compare_fuzzer.cpp icu-65.1/source/test/fuzzer/collator_compare_fuzzer.cpp --- icu-64.2/source/test/fuzzer/collator_compare_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/collator_compare_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,35 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "fuzzer_utils.h" +#include "unicode/coll.h" +#include "unicode/localpointer.h" +#include "unicode/locid.h" + +IcuEnvironment* env = new IcuEnvironment(); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UErrorCode status = U_ZERO_ERROR; + + if (size < 2) + return 0; + + std::unique_ptr compbuff1(new char16_t[size/4]); + std::memcpy(compbuff1.get(), data, (size/4)*2); + data = data + size/2; + std::unique_ptr compbuff2(new char16_t[size/4]); + std::memcpy(compbuff2.get(), data, (size/4)*2); + + icu::LocalPointer fuzzCollator( + icu::Collator::createInstance(icu::Locale::getUS(), status), status); + if (U_FAILURE(status)) + return 0; + fuzzCollator->setStrength(icu::Collator::TERTIARY); + + fuzzCollator->compare(compbuff1.get(), size/4, + compbuff2.get(), size/4); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/collator_rulebased_fuzzer.cpp icu-65.1/source/test/fuzzer/collator_rulebased_fuzzer.cpp --- icu-64.2/source/test/fuzzer/collator_rulebased_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/collator_rulebased_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,26 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "fuzzer_utils.h" +#include "unicode/coll.h" +#include "unicode/localpointer.h" +#include "unicode/locid.h" +#include "unicode/tblcoll.h" + +IcuEnvironment* env = new IcuEnvironment(); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UErrorCode status = U_ZERO_ERROR; + + size_t unistr_size = size/2; + std::unique_ptr fuzzbuff(new char16_t[unistr_size]); + std::memcpy(fuzzbuff.get(), data, unistr_size * 2); + icu::UnicodeString fuzzstr(false, fuzzbuff.get(), unistr_size); + + icu::LocalPointer col1( + new icu::RuleBasedCollator(fuzzstr, status)); + + return 0; +} Binary files /tmp/tmp1eTomn/Up6jWaEcgn/icu-64.2/source/test/fuzzer/collator_rulebased_fuzzer_seed_corpus.txt and /tmp/tmp1eTomn/1QfOdCdfdZ/icu-65.1/source/test/fuzzer/collator_rulebased_fuzzer_seed_corpus.txt differ diff -Nru icu-64.2/source/test/fuzzer/converter_fuzzer.cc icu-65.1/source/test/fuzzer/converter_fuzzer.cc --- icu-64.2/source/test/fuzzer/converter_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/converter_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include -#include - -#include -#include -#include -#include - -#include "fuzzer_utils.h" -#include "unicode/unistr.h" -#include "unicode/ucnv.h" - -IcuEnvironment* env = new IcuEnvironment(); - -template -using deleted_unique_ptr = std::unique_ptr>; - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - UErrorCode status = U_ZERO_ERROR; - uint16_t rnd = 0; - - if (size < 2) { - return 0; - } - - rnd = *(reinterpret_cast(data)); - data = data + 2; - size = size - 2; - - size_t unistr_size = size/2; - std::unique_ptr fuzzbuff(new char16_t[unistr_size]); - std::memcpy(fuzzbuff.get(), data, unistr_size * 2); - - icu::UnicodeString fuzzstr(false, fuzzbuff.get(), unistr_size); - - const char* converter_name = - ucnv_getAvailableName(rnd % ucnv_countAvailable()); - deleted_unique_ptr converter(ucnv_open(converter_name, &status), - &ucnv_close); - if (U_FAILURE(status)) { - return 0; - } - - static const size_t dest_buffer_size = 1024 * 1204; - static const std::unique_ptr dest_buffer(new char[dest_buffer_size]); - - fuzzstr.extract(dest_buffer.get(), dest_buffer_size, converter.get(), status); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/converter_fuzzer.cpp icu-65.1/source/test/fuzzer/converter_fuzzer.cpp --- icu-64.2/source/test/fuzzer/converter_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/converter_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,55 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "fuzzer_utils.h" +#include "unicode/unistr.h" +#include "unicode/ucnv.h" + +IcuEnvironment* env = new IcuEnvironment(); + +template +using deleted_unique_ptr = std::unique_ptr>; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UErrorCode status = U_ZERO_ERROR; + uint16_t rnd = 0; + + if (size < 2) { + return 0; + } + + rnd = *(reinterpret_cast(data)); + data = data + 2; + size = size - 2; + + size_t unistr_size = size/2; + std::unique_ptr fuzzbuff(new char16_t[unistr_size]); + std::memcpy(fuzzbuff.get(), data, unistr_size * 2); + + icu::UnicodeString fuzzstr(false, fuzzbuff.get(), unistr_size); + + const char* converter_name = + ucnv_getAvailableName(rnd % ucnv_countAvailable()); + deleted_unique_ptr converter(ucnv_open(converter_name, &status), + &ucnv_close); + if (U_FAILURE(status)) { + return 0; + } + + static const size_t dest_buffer_size = 1024 * 1204; + static const std::unique_ptr dest_buffer(new char[dest_buffer_size]); + + fuzzstr.extract(dest_buffer.get(), dest_buffer_size, converter.get(), status); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/fuzzer_driver.cpp icu-65.1/source/test/fuzzer/fuzzer_driver.cpp --- icu-64.2/source/test/fuzzer/fuzzer_driver.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/fuzzer_driver.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,20 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include +#include + +#include "cmemory.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +int main(int argc, char* argv[]) +{ + (void) argc; + (void) argv; + const char *fuzzer_data = "abc123"; + + LLVMFuzzerTestOneInput((const uint8_t *) fuzzer_data, strlen(fuzzer_data)); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/locale_fuzzer.cc icu-65.1/source/test/fuzzer/locale_fuzzer.cc --- icu-64.2/source/test/fuzzer/locale_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/locale_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -// Fuzzer for ICU Locales. - -#include -#include -#include -#include -#include -#include - -#include "unicode/locid.h" - -namespace { - -void ConsumeNBytes(const uint8_t** data, size_t* size, size_t N) { - *data += N; - *size -= N; -} - -uint8_t ConsumeUint8(const uint8_t** data, size_t* size) { - uint8_t tmp = 0; - if (*size >= 1) { - tmp = (*data)[0]; - ConsumeNBytes(data, size, 1); - } - return tmp; -} - -std::string ConsumeSubstring(const uint8_t** data, size_t* size) { - const size_t request_size = ConsumeUint8(data, size); - const char* substring_start = reinterpret_cast(*data); - const size_t substring_size = std::min(*size, request_size); - ConsumeNBytes(data, size, substring_size); - return std::string(substring_start, substring_size); -} - -} // namespace - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - const std::string language = ConsumeSubstring(&data, &size); - const std::string country = ConsumeSubstring(&data, &size); - const std::string variant = ConsumeSubstring(&data, &size); - const std::string kv_pairs = ConsumeSubstring(&data, &size); - icu::Locale locale(language.c_str(), country.c_str(), variant.c_str(), - kv_pairs.c_str()); - return EXIT_SUCCESS; -} diff -Nru icu-64.2/source/test/fuzzer/locale_fuzzer.cpp icu-65.1/source/test/fuzzer/locale_fuzzer.cpp --- icu-64.2/source/test/fuzzer/locale_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/locale_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,49 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// Fuzzer for ICU Locales. + +#include +#include +#include +#include +#include +#include + +#include "unicode/locid.h" + +namespace { + +void ConsumeNBytes(const uint8_t** data, size_t* size, size_t N) { + *data += N; + *size -= N; +} + +uint8_t ConsumeUint8(const uint8_t** data, size_t* size) { + uint8_t tmp = 0; + if (*size >= 1) { + tmp = (*data)[0]; + ConsumeNBytes(data, size, 1); + } + return tmp; +} + +std::string ConsumeSubstring(const uint8_t** data, size_t* size) { + const size_t request_size = ConsumeUint8(data, size); + const char* substring_start = reinterpret_cast(*data); + const size_t substring_size = std::min(*size, request_size); + ConsumeNBytes(data, size, substring_size); + return std::string(substring_start, substring_size); +} + +} // namespace + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + const std::string language = ConsumeSubstring(&data, &size); + const std::string country = ConsumeSubstring(&data, &size); + const std::string variant = ConsumeSubstring(&data, &size); + const std::string kv_pairs = ConsumeSubstring(&data, &size); + icu::Locale locale(language.c_str(), country.c_str(), variant.c_str(), + kv_pairs.c_str()); + return EXIT_SUCCESS; +} diff -Nru icu-64.2/source/test/fuzzer/locale_util.cc icu-65.1/source/test/fuzzer/locale_util.cc --- icu-64.2/source/test/fuzzer/locale_util.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/locale_util.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -// Helper method for ICU locale fuzzer. - -#include "locale_util.h" - -#include - -std::string MakeZeroTerminatedInput(const uint8_t *data, int32_t size) { - return size == 0 ? "" : std::string(reinterpret_cast(data), size); -} diff -Nru icu-64.2/source/test/fuzzer/locale_util.cpp icu-65.1/source/test/fuzzer/locale_util.cpp --- icu-64.2/source/test/fuzzer/locale_util.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/locale_util.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,12 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// Helper method for ICU locale fuzzer. + +#include "locale_util.h" + +#include + +std::string MakeZeroTerminatedInput(const uint8_t *data, int32_t size) { + return size == 0 ? "" : std::string(reinterpret_cast(data), size); +} diff -Nru icu-64.2/source/test/fuzzer/Makefile.in icu-65.1/source/test/fuzzer/Makefile.in --- icu-64.2/source/test/fuzzer/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,99 @@ +# © 2019 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +#****************************************************************************** +## Makefile.in for ICU - test/fuzzer + +## Source directory information +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +top_builddir = ../.. + +## All the flags and other definitions are included here. +include $(top_builddir)/icudefs.mk + +## Build directory information +subdir = test/fuzzer + +## Extra files to remove for 'make clean' +CLEANFILES = *~ $(DEPS) $(TESTXML) + +## Target information +TARGET = all_fuzzers + +BUILDDIR := $(CURR_SRCCODE_FULL_DIR)/../../ +# Simplify the path for Unix +BUILDDIR := $(BUILDDIR:test/fuzzer/../../=) +# Simplify the path for Windows +BUILDDIR := $(BUILDDIR:test\\fuzzer/../../=) +# Simplify the path for Windows 98 +BUILDDIR := $(BUILDDIR:TEST\\FUZZER/../../=) + +CPPFLAGS += -I$(srcdir) -I$(top_srcdir)/common -I$(top_srcdir)/i18n -I$(top_srcdir)/tools/ctestfw -I$(top_srcdir)/io +DEFS += -D'U_TOPSRCDIR="$(top_srcdir)/"' -D'U_TOPBUILDDIR="$(BUILDDIR)"' +LIBS = $(LIBCTESTFW) $(LIBICUTOOLUTIL) $(LIBICUIO) $(LIBICUI18N) $(LIBICUUC) $(DEFAULT_LIBS) $(LIB_M) + +FUZZER_TARGETS = break_iterator_fuzzer collator_compare_fuzzer collator_rulebased_fuzzer converter_fuzzer locale_fuzzer number_format_fuzzer ucasemap_fuzzer uloc_canonicalize_fuzzer uloc_for_language_tag_fuzzer uloc_get_name_fuzzer uloc_is_right_to_left_fuzzer uloc_open_keywords_fuzzer unicode_string_codepage_create_fuzzer uregex_open_fuzzer + +OBJECTS = $(FUZZER_TARGETS:%=%.o) +OBJECTS += fuzzer_driver.o locale_util.o + +DEPS = $(OBJECTS:.o=.d) + +-include Makefile.local + +## List of phony targets +.PHONY : all all-local install install-local clean clean-local \ +distclean distclean-local dist dist-local check check-local xcheck \ +check-exhaustive check-exhaustive-local all_fuzzers + +## Clear suffix list +.SUFFIXES : + +## List of standard targets +all: all-local +install: install-local +clean: clean-local +distclean : distclean-local +dist: dist-local +check: all check-local +xcheck: all xcheck-local + +all-local: $(TARGET) + +install-local: + +dist-local: + +clean-local: + test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES) + $(RMV) $(OBJECTS) $(TARGET) $(FUZZER_TARGETS) + +distclean-local: clean-local + $(RMV) Makefile + +check-local: all-local + $(foreach trgt,$(FUZZER_TARGETS), echo $(trgt); $(INVOKE) ./$(trgt) \ + $(TEST_OUTPUT_OPTS) || exit \ + $(IOTEST_OPTS);) + +xcheck-local: check-local + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +all_fuzzers: $(FUZZER_TARGETS) + +%_fuzzer: %_fuzzer.o fuzzer_driver.o locale_util.o + $(LINK.cc) $(OUTOPT)$@ $^ $(LIBS) + +ifeq (,$(MAKECMDGOALS)) +-include $(DEPS) +else +ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),) +ifneq ($(patsubst %install,,$(MAKECMDGOALS)),) +-include $(DEPS) +endif +endif +endif diff -Nru icu-64.2/source/test/fuzzer/number_format_fuzzer.cc icu-65.1/source/test/fuzzer/number_format_fuzzer.cc --- icu-64.2/source/test/fuzzer/number_format_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/number_format_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -// Fuzzer for NumberFormat::parse. - -#include -#include -#include -#include "fuzzer_utils.h" -#include "unicode/numfmt.h" - -IcuEnvironment* env = new IcuEnvironment(); - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - UErrorCode status = U_ZERO_ERROR; - uint16_t rnd = 0; - - if (size < 2) { - return 0; - } - - rnd = *(reinterpret_cast(data)); - data = data + 2; - size = size - 2; - - size_t unistr_size = size/2; - std::unique_ptr fuzzbuff(new char16_t[unistr_size]); - std::memcpy(fuzzbuff.get(), data, unistr_size * 2); - - const icu::Locale& locale = GetRandomLocale(rnd); - - std::unique_ptr fmt( - icu::NumberFormat::createInstance(locale, status)); - if (U_FAILURE(status)) { - return 0; - } - - icu::UnicodeString fuzzstr(false, fuzzbuff.get(), unistr_size); - icu::Formattable result; - fmt->parse(fuzzstr, result, status); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/number_format_fuzzer.cpp icu-65.1/source/test/fuzzer/number_format_fuzzer.cpp --- icu-64.2/source/test/fuzzer/number_format_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/number_format_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,45 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// Fuzzer for NumberFormat::parse. + +#include +#include +#include +#include +#include +#include "fuzzer_utils.h" +#include "unicode/numfmt.h" + +IcuEnvironment* env = new IcuEnvironment(); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UErrorCode status = U_ZERO_ERROR; + uint16_t rnd = 0; + + if (size < 2) { + return 0; + } + + rnd = *(reinterpret_cast(data)); + data = data + 2; + size = size - 2; + + size_t unistr_size = size/2; + std::unique_ptr fuzzbuff(new char16_t[unistr_size]); + std::memcpy(fuzzbuff.get(), data, unistr_size * 2); + + const icu::Locale& locale = GetRandomLocale(rnd); + + std::unique_ptr fmt( + icu::NumberFormat::createInstance(locale, status)); + if (U_FAILURE(status)) { + return 0; + } + + icu::UnicodeString fuzzstr(false, fuzzbuff.get(), unistr_size); + icu::Formattable result; + fmt->parse(fuzzstr, result, status); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/ucasemap_fuzzer.cc icu-65.1/source/test/fuzzer/ucasemap_fuzzer.cc --- icu-64.2/source/test/fuzzer/ucasemap_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/ucasemap_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -// Fuzzer for ucasemap. - -#include -#include -#include -#include "fuzzer_utils.h" -#include "unicode/ucasemap.h" - -IcuEnvironment* env = new IcuEnvironment(); - -template -using deleted_unique_ptr = std::unique_ptr>; - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - UErrorCode status = U_ZERO_ERROR; - uint8_t rnd8 = 0; - uint16_t rnd16 = 0; - uint32_t rnd32 = 0; - - if (size < 7) { - return 0; - } - // Extract one, two, and four bytes from fuzzer data for random selection - // purposes. - rnd8 = *data; - data++; - rnd16 = *(reinterpret_cast(data)); - data = data + 2; - rnd32 = *(reinterpret_cast(data)); - data = data + 4; - size = size - 7; - - std::unique_ptr fuzzbuff(new char[size]); - std::memcpy(fuzzbuff.get(), data, size); - - const icu::Locale& locale = GetRandomLocale(rnd16); - uint32_t open_flags = rnd32; - - deleted_unique_ptr csm( - ucasemap_open(locale.getName(), open_flags, &status), - [](UCaseMap* map) { ucasemap_close(map); }); - - if (U_FAILURE(status)) { - return 0; - } - - int32_t dst_size = size * 2; - std::unique_ptr dst(new char[dst_size]); - auto src = reinterpret_cast(fuzzbuff.get()); - - switch (rnd8 % 4) { - case 0: ucasemap_utf8ToLower(csm.get(), dst.get(), dst_size, src, size, - &status); - break; - case 1: ucasemap_utf8ToUpper(csm.get(), dst.get(), dst_size, src, size, - &status); - break; - case 2: ucasemap_utf8ToTitle(csm.get(), dst.get(), dst_size, src, size, - &status); - break; - case 3: ucasemap_utf8FoldCase(csm.get(), dst.get(), dst_size, src, size, - &status); - break; - } - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/ucasemap_fuzzer.cpp icu-65.1/source/test/fuzzer/ucasemap_fuzzer.cpp --- icu-64.2/source/test/fuzzer/ucasemap_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/ucasemap_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,72 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// Fuzzer for ucasemap. + +#include +#include +#include +#include +#include +#include "fuzzer_utils.h" +#include "unicode/ucasemap.h" + +IcuEnvironment* env = new IcuEnvironment(); + +template +using deleted_unique_ptr = std::unique_ptr>; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UErrorCode status = U_ZERO_ERROR; + uint8_t rnd8 = 0; + uint16_t rnd16 = 0; + uint32_t rnd32 = 0; + + if (size < 7) { + return 0; + } + // Extract one, two, and four bytes from fuzzer data for random selection + // purposes. + rnd8 = *data; + data++; + rnd16 = *(reinterpret_cast(data)); + data = data + 2; + rnd32 = *(reinterpret_cast(data)); + data = data + 4; + size = size - 7; + + std::unique_ptr fuzzbuff(new char[size]); + std::memcpy(fuzzbuff.get(), data, size); + + const icu::Locale& locale = GetRandomLocale(rnd16); + uint32_t open_flags = rnd32; + + deleted_unique_ptr csm( + ucasemap_open(locale.getName(), open_flags, &status), + [](UCaseMap* map) { ucasemap_close(map); }); + + if (U_FAILURE(status)) { + return 0; + } + + int32_t dst_size = size * 2; + std::unique_ptr dst(new char[dst_size]); + auto src = reinterpret_cast(fuzzbuff.get()); + + switch (rnd8 % 4) { + case 0: ucasemap_utf8ToLower(csm.get(), dst.get(), dst_size, src, size, + &status); + break; + case 1: ucasemap_utf8ToUpper(csm.get(), dst.get(), dst_size, src, size, + &status); + break; + case 2: ucasemap_utf8ToTitle(csm.get(), dst.get(), dst_size, src, size, + &status); + break; + case 3: ucasemap_utf8FoldCase(csm.get(), dst.get(), dst_size, src, size, + &status); + break; + } + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/uloc_canonicalize_fuzzer.cc icu-65.1/source/test/fuzzer/uloc_canonicalize_fuzzer.cc --- icu-64.2/source/test/fuzzer/uloc_canonicalize_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_canonicalize_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include - -#include "locale_util.h" -#include "unicode/uloc.h" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - // Canonicalized locale name. - char name[ULOC_FULLNAME_CAPACITY]; - int32_t name_capacity = ULOC_FULLNAME_CAPACITY; - - const std::string input = MakeZeroTerminatedInput(data, size); - - UErrorCode status = U_ZERO_ERROR; - uloc_canonicalize(input.c_str(), name, name_capacity, &status); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/uloc_canonicalize_fuzzer.cpp icu-65.1/source/test/fuzzer/uloc_canonicalize_fuzzer.cpp --- icu-64.2/source/test/fuzzer/uloc_canonicalize_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_canonicalize_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,20 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "locale_util.h" +#include "unicode/uloc.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // Canonicalized locale name. + char name[ULOC_FULLNAME_CAPACITY]; + int32_t name_capacity = ULOC_FULLNAME_CAPACITY; + + const std::string input = MakeZeroTerminatedInput(data, size); + + UErrorCode status = U_ZERO_ERROR; + uloc_canonicalize(input.c_str(), name, name_capacity, &status); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/uloc_for_language_tag_fuzzer.cc icu-65.1/source/test/fuzzer/uloc_for_language_tag_fuzzer.cc --- icu-64.2/source/test/fuzzer/uloc_for_language_tag_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_for_language_tag_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include - -#include "locale_util.h" -#include "unicode/uloc.h" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - // Full locale id. - char locale_id[ULOC_FULLNAME_CAPACITY]; - int32_t locale_id_capacity = ULOC_FULLNAME_CAPACITY; - - const std::string input = MakeZeroTerminatedInput(data, size); - - UErrorCode status = U_ZERO_ERROR; - uloc_forLanguageTag(input.c_str(), locale_id, locale_id_capacity, nullptr, - &status); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/uloc_for_language_tag_fuzzer.cpp icu-65.1/source/test/fuzzer/uloc_for_language_tag_fuzzer.cpp --- icu-64.2/source/test/fuzzer/uloc_for_language_tag_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_for_language_tag_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,21 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "locale_util.h" +#include "unicode/uloc.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // Full locale id. + char locale_id[ULOC_FULLNAME_CAPACITY]; + int32_t locale_id_capacity = ULOC_FULLNAME_CAPACITY; + + const std::string input = MakeZeroTerminatedInput(data, size); + + UErrorCode status = U_ZERO_ERROR; + uloc_forLanguageTag(input.c_str(), locale_id, locale_id_capacity, nullptr, + &status); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/uloc_get_name_fuzzer.cc icu-65.1/source/test/fuzzer/uloc_get_name_fuzzer.cc --- icu-64.2/source/test/fuzzer/uloc_get_name_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_get_name_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include - -#include "locale_util.h" -#include "unicode/uloc.h" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - // Full locale name. - char name[ULOC_FULLNAME_CAPACITY]; - int32_t name_capacity = ULOC_FULLNAME_CAPACITY; - - const std::string input = MakeZeroTerminatedInput(data, size); - - UErrorCode status = U_ZERO_ERROR; - uloc_getName(input.c_str(), name, name_capacity, &status); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/uloc_get_name_fuzzer.cpp icu-65.1/source/test/fuzzer/uloc_get_name_fuzzer.cpp --- icu-64.2/source/test/fuzzer/uloc_get_name_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_get_name_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,20 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "locale_util.h" +#include "unicode/uloc.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // Full locale name. + char name[ULOC_FULLNAME_CAPACITY]; + int32_t name_capacity = ULOC_FULLNAME_CAPACITY; + + const std::string input = MakeZeroTerminatedInput(data, size); + + UErrorCode status = U_ZERO_ERROR; + uloc_getName(input.c_str(), name, name_capacity, &status); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cc icu-65.1/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cc --- icu-64.2/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include - -#include "locale_util.h" -#include "unicode/uloc.h" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - const std::string input = MakeZeroTerminatedInput(data, size); - - uloc_isRightToLeft(input.c_str()); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cpp icu-65.1/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cpp --- icu-64.2/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_is_right_to_left_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,15 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "locale_util.h" +#include "unicode/uloc.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + const std::string input = MakeZeroTerminatedInput(data, size); + + uloc_isRightToLeft(input.c_str()); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/uloc_open_keywords_fuzzer.cc icu-65.1/source/test/fuzzer/uloc_open_keywords_fuzzer.cc --- icu-64.2/source/test/fuzzer/uloc_open_keywords_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_open_keywords_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include - -#include "locale_util.h" -#include "unicode/uenum.h" -#include "unicode/uloc.h" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - const std::string input = MakeZeroTerminatedInput(data, size); - - UErrorCode status = U_ZERO_ERROR; - UEnumeration* enumeration = uloc_openKeywords(input.c_str(), &status); - - // Have to clean up. Call works even for nullptr enumeration. - uenum_close(enumeration); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/uloc_open_keywords_fuzzer.cpp icu-65.1/source/test/fuzzer/uloc_open_keywords_fuzzer.cpp --- icu-64.2/source/test/fuzzer/uloc_open_keywords_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uloc_open_keywords_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,20 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include + +#include "locale_util.h" +#include "unicode/uenum.h" +#include "unicode/uloc.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + const std::string input = MakeZeroTerminatedInput(data, size); + + UErrorCode status = U_ZERO_ERROR; + UEnumeration* enumeration = uloc_openKeywords(input.c_str(), &status); + + // Have to clean up. Call works even for nullptr enumeration. + uenum_close(enumeration); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cc icu-65.1/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cc --- icu-64.2/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include -#include - -#include -#include -#include - -#include "fuzzer_utils.h" -#include "unicode/unistr.h" - -// Taken from third_party/icu/source/data/mappings/convrtrs.txt file. -static const std::array kConverters = { - { - "UTF-8", - "utf-16be", - "utf-16le", - "UTF-32", - "UTF-32BE", - "UTF-32LE", - "ibm866-html", - "iso-8859-2-html", - "iso-8859-3-html", - "iso-8859-4-html", - "iso-8859-5-html", - "iso-8859-6-html", - "iso-8859-7-html", - "iso-8859-8-html", - "ISO-8859-8-I", - "iso-8859-10-html", - "iso-8859-13-html", - "iso-8859-14-html", - "iso-8859-15-html", - "iso-8859-16-html", - "koi8-r-html", - "koi8-u-html", - "macintosh-html", - "windows-874-html", - "windows-1250-html", - "windows-1251-html", - "windows-1252-html", - "windows-1253-html", - "windows-1254-html", - "windows-1255-html", - "windows-1256-html", - "windows-1257-html", - "windows-1258-html", - "x-mac-cyrillic-html", - "windows-936-2000", - "gb18030", - "big5-html", - "euc-jp-html", - "ISO_2022,locale=ja,version=0", - "shift_jis-html", - "euc-kr-html", - "ISO-2022-KR", - "ISO-2022-CN", - "ISO-2022-CN-EXT", - "HZ-GB-2312" - } -}; - -IcuEnvironment* env = new IcuEnvironment(); - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size < 1) { - return 0; - } - - // First byte is used for random converter selection. - uint8_t rnd = *data; - data++; - size--; - - std::unique_ptr fuzzbuff(new char[size]); - std::memcpy(fuzzbuff.get(), data, size); - - icu::UnicodeString str(fuzzbuff.get(), size, - kConverters[rnd % kConverters.size()]); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cpp icu-65.1/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cpp --- icu-64.2/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/unicode_string_codepage_create_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,85 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include +#include + +#include +#include +#include +#include + +#include "fuzzer_utils.h" +#include "unicode/unistr.h" + +// Taken from third_party/icu/source/data/mappings/convrtrs.txt file. +static const std::array kConverters = { + { + "UTF-8", + "utf-16be", + "utf-16le", + "UTF-32", + "UTF-32BE", + "UTF-32LE", + "ibm866-html", + "iso-8859-2-html", + "iso-8859-3-html", + "iso-8859-4-html", + "iso-8859-5-html", + "iso-8859-6-html", + "iso-8859-7-html", + "iso-8859-8-html", + "ISO-8859-8-I", + "iso-8859-10-html", + "iso-8859-13-html", + "iso-8859-14-html", + "iso-8859-15-html", + "iso-8859-16-html", + "koi8-r-html", + "koi8-u-html", + "macintosh-html", + "windows-874-html", + "windows-1250-html", + "windows-1251-html", + "windows-1252-html", + "windows-1253-html", + "windows-1254-html", + "windows-1255-html", + "windows-1256-html", + "windows-1257-html", + "windows-1258-html", + "x-mac-cyrillic-html", + "windows-936-2000", + "gb18030", + "big5-html", + "euc-jp-html", + "ISO_2022,locale=ja,version=0", + "shift_jis-html", + "euc-kr-html", + "ISO-2022-KR", + "ISO-2022-CN", + "ISO-2022-CN-EXT", + "HZ-GB-2312" + } +}; + +IcuEnvironment* env = new IcuEnvironment(); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 1) { + return 0; + } + + // First byte is used for random converter selection. + uint8_t rnd = *data; + data++; + size--; + + std::unique_ptr fuzzbuff(new char[size]); + std::memcpy(fuzzbuff.get(), data, size); + + icu::UnicodeString str(fuzzbuff.get(), size, + kConverters[rnd % kConverters.size()]); + + return 0; +} diff -Nru icu-64.2/source/test/fuzzer/uregex_open_fuzzer.cc icu-65.1/source/test/fuzzer/uregex_open_fuzzer.cc --- icu-64.2/source/test/fuzzer/uregex_open_fuzzer.cc 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uregex_open_fuzzer.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -// © 2019 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include -#include - -#include "fuzzer_utils.h" -#include "unicode/regex.h" - -IcuEnvironment* env = new IcuEnvironment(); - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - UParseError pe = { 0 }; - UErrorCode status = U_ZERO_ERROR; - URegularExpression* re = uregex_open(reinterpret_cast(data), - static_cast(size) / sizeof(UChar), - 0, &pe, &status); - if (re) - uregex_close(re); - - return 0; -} diff -Nru icu-64.2/source/test/fuzzer/uregex_open_fuzzer.cpp icu-65.1/source/test/fuzzer/uregex_open_fuzzer.cpp --- icu-64.2/source/test/fuzzer/uregex_open_fuzzer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/fuzzer/uregex_open_fuzzer.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,26 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include +#include +#include + + +#include "fuzzer_utils.h" +#include "unicode/regex.h" + +IcuEnvironment* env = new IcuEnvironment(); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + UParseError pe = { 0 }; + UErrorCode status = U_ZERO_ERROR; + + URegularExpression* re = uregex_open(reinterpret_cast(data), + static_cast(size) / sizeof(UChar), + 0, &pe, &status); + + if (re) + uregex_close(re); + + return 0; +} diff -Nru icu-64.2/source/test/hdrtst/cxxfiles.txt icu-65.1/source/test/hdrtst/cxxfiles.txt --- icu-64.2/source/test/hdrtst/cxxfiles.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/hdrtst/cxxfiles.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -# Copyright (C) 2016 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html -# Copyright (c) 2001-2016 International Business Machines -# Corporation and others. All Rights Reserved. -# Begin temporary addition. -# These are very bad "C" APIs that do not work with a C compiler and -# violate many ICU coding guidelines. These were added with ticket #5996. -# Temporarily marked as C++ for the hdrtst to pass. -# These are gone in ICU 50.1, remove -#vzone.h -#zrule.h -#ztrans.h -# End temporary addition. -# common & i18n -alphaindex.h -appendable.h -bidi.h -basictz.h -bmsearch.h -brkiter.h -bytestream.h -bytestrie.h -bytestriebuilder.h -calendar.h -caniter.h -casemap.h -char16ptr.h -chariter.h -choicfmt.h -coleitr.h -coll.h -colldata.h -compactdecimalformat.h -convert.h -cpdtrans.h -curramt.h -currunit.h -currpinf.h -datefmt.h -dbbi.h -dcfmtsym.h -decimfmt.h -dtintrv.h -dtitvinf.h -dtitvfmt.h -dtfmtsym.h -dtptngen.h -dtrule.h -edits.h -enumset.h -errorcode.h -fieldpos.h -filteredbrk.h -fmtable.h -format.h -formattedvalue.h -fpositer.h -gender.h -gregocal.h -idna.h -listformatter.h -localebuilder.h -locdspnm.h -locid.h -measfmt.h -measunit.h -measure.h -messagepattern.h -msgfmt.h -normalizer2.h -normlzr.h -nounit.h -numberformatter.h -numberrangeformatter.h -numfmt.h -numsys.h -parsepos.h -plurfmt.h -plurrule.h -rbbi.h -rbnf.h -rbtz.h -regex.h -region.h -reldatefmt.h -rep.h -resbund.h -schriter.h -scientificformathelper.h -scientificnumberformatter.h -search.h -selfmt.h -simpleformatter.h -simpletz.h -smpdtfmt.h -sortkey.h -std_string.h -strenum.h -stringtriebuilder.h -stringpiece.h -stsearch.h -symtable.h -tblcoll.h -timezone.h -tmunit.h -tmutamt.h -tmutfmt.h -translit.h -tzfmt.h -tznames.h -tzrule.h -tztrans.h -ucharstrie.h -ucharstriebuilder.h -uchriter.h -unifilt.h -unifunct.h -unimatch.h -unirepl.h -uniset.h -unistr.h -uobject.h -usetiter.h -vtzone.h -# io library -ustream.h -# layout & layoutex -LayoutEngine.h -LEFontInstance.h -LEGlyphFilter.h -LEGlyphStorage.h -LELanguages.h -LEScripts.h -LESwaps.h -# LETypes.h -- C header -# loengine.h -- C header -ParagraphLayout.h -RunArrays.h diff -Nru icu-64.2/source/test/hdrtst/Makefile.in icu-65.1/source/test/hdrtst/Makefile.in --- icu-64.2/source/test/hdrtst/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/hdrtst/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -17,9 +17,8 @@ ## ## .. etc. Anything other than zero is an error. (except for the deprecation tests, where '1' is the correct value) ## -## -## If a header fails the C compile because it's a C++ header, add it to the -## file named 'cxxfiles.txt' in this directory. +## If a header fails the C compile test it is likely because the header is a +## C++ header and isn't properly guarded by the U_SHOW_CPLUSPLUS_API macro. ## ## If a header fails because it is deprecated, add it to the 'dfiles.txt' ## @@ -33,135 +32,84 @@ subdir = test/hdrtst include $(shell icu-config --incfile) -DIRS=$(prefix)/include/unicode -LDIRS=$(prefix)/include/layout -ECHO_T=@ECHO_T@ -ECHO_C=@ECHO_C@ -ECHO_N=@ECHO_N@ all: @echo Please read this Makefile for more information. @echo run \'$(MAKE) check\' to run the test "(use -k if you don't want to stop on errs)" -E_NUM=8 -E_D="[1/$(E_NUM)] Deprecated: " -E_C="[2/$(E_NUM)] C : " -E_CXX="[3/$(E_NUM)] C++: " -E_CXX_L="[4/$(E_NUM)] C++ layout: " -E_DRF="[5/$(E_NUM)] Hide Draft: " -E_DEP="[6/$(E_NUM)] Hide Deprecated: " -E_INT="[7/$(E_NUM)] Hide Internal: " -E_OBS="[8/$(E_NUM)] Hide Obsolete: " - -check: dtest ctest cpptest doclean drafttest deprtest internaltest obsoletetest -ifeq ($(MAKECMDGOALS),check) - $(MAKE) clean -else - @echo "(not cleaning automatically)" -endif - -# break dependency -doclean: - make clean - -cpptest: - @FAIL=0;for file in `ls $(prefix)/include/unicode/*.h | fgrep -v -f $(srcdir)/pfiles.txt`; do \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#include "'unicode/$$incfile'.h"' > ht_$$incfile.cpp ; \ - echo 'void junk(){}' >> ht_$$incfile.cpp ; \ - $(COMPILE.cc) -c $(cppflags) ht_$$incfile.cpp || FAIL=1 ; \ - done ;\ - exit $$FAIL - -# layout is removed +check: dtest ctest cpptest drafttest deprtest internaltest obsoletetest -dtest: - @FAIL=0;NONE="(No deprecated headers)";for stub in `cat $(srcdir)/dfiles.txt | grep -v '^#'` ; do \ - file=unicode/$$stub ; \ - NONE="" ; \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#include "'unicode/$$incfile'.h"' > ht_$$incfile.cpp ; \ - echo 'void junk(){}' >> ht_$$incfile.cpp ; \ - echo > ht_dep.junk ; \ - $(COMPILE.cc) -c $(cppflags) ht_$$incfile.cpp 2>&1 | sed -e 's/^.*#error[^"]*"//' | fgrep -v ht_ | tee ht_dep.junk | fgrep -v "$$incfile.h header is obsolete" ; \ - RES=$$? ; \ - echo $$RES ; \ - fgrep -q "$$incfile.h header is obsolete" ht_dep.junk || echo "** FAIL Header unicode/$$incfile.h is not obsoleted properly" ; \ - fgrep -q "$$incfile.h header is obsolete" ht_dep.junk || FAIL=1 ; \ - rm -f unicode/$$stub ; \ +headertest: + @FAIL=0;stub=ht_stub_$(NAME.headers).$(SUFFIX.headers); for file in "$(prefix)/include/unicode"/*.h ; do \ + incfile=`basename $$file` ; \ + echo "$(NAME.headers) unicode/$$incfile" ; \ + echo "#include " > $$stub ; \ + echo 'void junk(){}' >> $$stub ; \ + $(COMPILE.headers) $(cppflags) $(FLAGS.headers) $$stub || FAIL=1 ; \ + rm -f $$stub; \ done ; \ - echo "$@: $$NONE - exit status $$FAIL" ; \ exit $$FAIL -# < ht_dep.junk && ; \ - - ctest: - @echo Building test harness for header files in ../../common and ../../i18n - @FAIL=0;for file in `ls $(prefix)/include/unicode/*.h | fgrep -v -f $(srcdir)/cxxfiles.txt | tee cfiles.txt`; do \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#include "'unicode/$$incfile'.h"' > ht_$$incfile.c ; \ - echo 'void junk(void);' >> ht_$$incfile.c ; \ - echo 'void junk(){}' >> ht_$$incfile.c ; \ - $(COMPILE.c) -c $(cppflags) ht_$$incfile.c || FAIL=1 ; \ - done ;\ - exit $$FAIL + $(MAKE) headertest \ + NAME.headers=$@ \ + COMPILE.headers="$(COMPILE.c)" \ + SUFFIX.headers=c \ + FLAGS.headers= + +cpptest: + $(MAKE) headertest \ + NAME.headers=$@ \ + COMPILE.headers="$(COMPILE.cc)" \ + SUFFIX.headers=cpp \ + FLAGS.headers= drafttest: - @FAIL=0;for file in `ls $(prefix)/include/unicode/*.h | fgrep -v -f $(srcdir)/pfiles.txt`; do \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#define U_HIDE_DRAFT_API' > hd_$$incfile.cpp ; \ - echo '#include "'unicode/$$incfile'.h"' >> hd_$$incfile.cpp ; \ - echo 'void junk(void);' >> hd_$$incfile.cpp ; \ - echo 'void junk(){}' >> hd_$$incfile.cpp ; \ - $(COMPILE.cc) -c $(cppflags) hd_$$incfile.cpp ||FAIL=1 ; \ - done ;\ - exit $$FAIL + $(MAKE) headertest \ + NAME.headers=$@ \ + COMPILE.headers="$(COMPILE.cc)" \ + SUFFIX.headers=cpp \ + FLAGS.headers="-DU_HIDE_DRAFT_API" deprtest: - @FAIL=0; for file in `ls $(prefix)/include/unicode/*.h | fgrep -v -f $(srcdir)/pfiles.txt`; do \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#define U_HIDE_DEPRECATED_API' > hdp_$$incfile.cpp ; \ - echo '#include "'unicode/$$incfile'.h"' >> hdp_$$incfile.cpp ; \ - echo 'void junk(void);' >> hdp_$$incfile.cpp ; \ - echo 'void junk(){}' >> hdp_$$incfile.cpp ; \ - $(COMPILE.cc) -c $(cppflags) hdp_$$incfile.cpp || FAIL=1; \ - done ; \ - exit $$FAIL + $(MAKE) headertest \ + NAME.headers=$@ \ + COMPILE.headers="$(COMPILE.cc)" \ + SUFFIX.headers=cpp \ + FLAGS.headers="-DU_HIDE_DEPRECATED_API" internaltest: - @FAIL=0;\ - for file in `ls $(prefix)/include/unicode/*.h | fgrep -v -f $(srcdir)/pfiles.txt`; do \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#define U_HIDE_INTERNAL_API' > hin_$$incfile.cpp ; \ - echo '#include "'unicode/$$incfile'.h"' >> hin_$$incfile.cpp ; \ - echo 'void junk(void);' >> hin_$$incfile.cpp ; \ - echo 'void junk(){}' >> hin_$$incfile.cpp ; \ - $(COMPILE.cc) -c $(cppflags) hin_$$incfile.cpp || FAIL=1 ; \ - done ; \ - exit $$FAIL + $(MAKE) headertest \ + NAME.headers=$@ \ + COMPILE.headers="$(COMPILE.cc)" \ + SUFFIX.headers=cpp \ + FLAGS.headers="-DU_HIDE_INTERNAL_API" obsoletetest: - @FAIL=0;for file in `ls $(prefix)/include/unicode/*.h | fgrep -v -f $(srcdir)/pfiles.txt`; do \ - incfile=`basename $$file .h` ; \ - echo "$@ unicode/$$incfile.h" ; \ - echo '#define U_HIDE_OBSOLETE_API' > hob_$$incfile.cpp ; \ - echo '#include "'unicode/$$incfile'.h"' >> hob_$$incfile.cpp ; \ - echo 'void junk(void);' >> hob_$$incfile.cpp ; \ - echo 'void junk(){}' >> hob_$$incfile.cpp ; \ - $(COMPILE.cc) -c $(cppflags) hob_$$incfile.cpp || FAIL=1 ; \ + $(MAKE) headertest \ + NAME.headers=$@ \ + COMPILE.headers="$(COMPILE.cc)" \ + SUFFIX.headers=cpp \ + FLAGS.headers="-DU_HIDE_OBSOLETE_API" + +dtest: + @FAIL=0;NONE="(No deprecated headers)";stub=ht_stub_dtest.cpp;for incfile in `cat $(srcdir)/dfiles.txt | grep -v '^#' | sort` ; do \ + NONE= ; \ + echo "$@ unicode/$$incfile" ; \ + echo "#include " > $$stub ; \ + echo 'void junk(){}' >> $$stub ; \ + $(COMPILE.cc) $(cppflags) $$stub 2>&1 | tee $$stub.out || FAIL=1 ; \ + if ! cat $$stub.out | sed -e 's/^.*#error[^"]*"//' | grep -v ht_ | grep -v "$$incfile header is obsolete"; then \ + echo "** FAIL Header unicode/$$incfile is not obsoleted properly" ; \ + FAIL=1 ; \ + fi ; \ + rm -f $$stub*; \ done ; \ + echo "$@: $$NONE - exit status $$FAIL" ; \ exit $$FAIL clean: - -@echo cleaning.. - -@rm -f *.h *.c *.cpp *.o *.junk cfiles.txt + -@rm -f ht_* distclean: clean -@rm -f Makefile @@ -170,5 +118,4 @@ cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status -.PHONY: doclean check all cpptest dtest ctest clean distclean - +.PHONY: doclean check all headertest cpptest dtest ctest clean distclean diff -Nru icu-64.2/source/test/hdrtst/pfiles.txt icu-65.1/source/test/hdrtst/pfiles.txt --- icu-64.2/source/test/hdrtst/pfiles.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/hdrtst/pfiles.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -# Copyright (C) 2016 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html -# Copyright (c) 2001-2016 International Business Machines -# Corporation and others. All Rights Reserved. -# ICU 49 and later: no more platform-specific headers diff -Nru icu-64.2/source/test/hdrtst/testtagsguards.sh icu-65.1/source/test/hdrtst/testtagsguards.sh --- icu-64.2/source/test/hdrtst/testtagsguards.sh 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/hdrtst/testtagsguards.sh 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,94 @@ +# Copyright © 2019 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +# Run this script from $ICU_ROOT/icu4c. +# ~/icu/mine/src/icu4c$ source/test/hdrtest/testtagsguards.sh + +# set -x # echo on + +DEF=-DU_NO_DEFAULT_INCLUDE_UTF_HEADERS=1 +INCL="-Isource/common -Isource/i18n -Isource/io" +TMPDIR=`mktemp -d` +DIFF="diff -u --minimal" + +echo "*** testtagsguards.sh TMPDIR=$TMPDIR" + +for file in source/common/unicode/*.h source/i18n/unicode/*.h source/io/unicode/*.h ; do + base=`basename $file` + echo $file + echo '#include "unicode/'$base'"' > $TMPDIR/ht-$base.cpp + # Preprocess only. + clang++ $INCL -C -E $DEF -o $TMPDIR/ht-$base-normal.i $TMPDIR/ht-$base.cpp + + # When hiding @draft, none should be in the output. + TAG=draft + GUARD=DRAFT + echo " @$TAG" + clang++ $INCL -C -E -DU_HIDE_${GUARD}_API=1 -DU_FORCE_HIDE_${GUARD}_API=1 $DEF -o $TMPDIR/ht-$base-$TAG.i $TMPDIR/ht-$base.cpp + if grep "@$TAG" -C 5 $TMPDIR/ht-$base-$TAG.i; then + echo "*** error: @$TAG not hidden in $TMPDIR/ht-$base-$TAG.i" + exit 1 + fi + # Only @draft should be hidden. + # Except: Ok to hide nested @internal/@system/@obsolete. + $DIFF $TMPDIR/ht-$base-normal.i $TMPDIR/ht-$base-$TAG.i > $TMPDIR/ht-$base-normal-$TAG.txt + if egrep '^-.*@(stable|deprecated)' -C 5 $TMPDIR/ht-$base-normal-$TAG.txt; then + echo "*** error: Non-@$TAG hidden in $TMPDIR/ht-$base-$TAG.i see $TMPDIR/ht-$base-normal-$TAG.txt" + cat $TMPDIR/ht-$base-normal-$TAG.txt + exit 1 + fi + + # @deprecated + TAG=deprecated + GUARD=DEPRECATED + echo " @$TAG" + clang++ $INCL -C -E -DU_HIDE_${GUARD}_API=1 -DU_FORCE_HIDE_${GUARD}_API=1 $DEF -o $TMPDIR/ht-$base-$TAG.i $TMPDIR/ht-$base.cpp + if grep "@$TAG" -C 5 $TMPDIR/ht-$base-$TAG.i; then + echo "*** error: @$TAG not hidden in $TMPDIR/ht-$base-$TAG.i" + exit 1 + fi + # In the egrep: All tags except $TAG and @internal & similar. + $DIFF $TMPDIR/ht-$base-normal.i $TMPDIR/ht-$base-$TAG.i > $TMPDIR/ht-$base-normal-$TAG.txt + if egrep '^-.*@(stable|draft)' -C 5 $TMPDIR/ht-$base-normal-$TAG.txt; then + echo "*** error: Non-@$TAG hidden in $TMPDIR/ht-$base-$TAG.i see $TMPDIR/ht-$base-normal-$TAG.txt" + cat $TMPDIR/ht-$base-normal-$TAG.txt + exit 1 + fi + + # TODO: @internal + # Hiding some @internal definitions, in particular in platform.h and similar, + # tends to break even preprocessing of other headers. + + # @system + TAG=system + GUARD=SYSTEM + echo " @$TAG" + clang++ $INCL -C -E -DU_HIDE_${GUARD}_API=1 -DU_FORCE_HIDE_${GUARD}_API=1 $DEF -o $TMPDIR/ht-$base-$TAG.i $TMPDIR/ht-$base.cpp + if grep "@$TAG" -C 5 $TMPDIR/ht-$base-$TAG.i; then + echo "*** error: @$TAG not hidden in $TMPDIR/ht-$base-$TAG.i" + exit 1 + fi + # @system is orthogonal to @stable / @deprecated etc., + # so we don't check that none of those are hidden. + + # @obsolete + TAG=obsolete + GUARD=OBSOLETE + echo " @$TAG" + clang++ $INCL -C -E -DU_HIDE_${GUARD}_API=1 -DU_FORCE_HIDE_${GUARD}_API=1 $DEF -o $TMPDIR/ht-$base-$TAG.i $TMPDIR/ht-$base.cpp + if grep "@$TAG" -C 5 $TMPDIR/ht-$base-$TAG.i; then + echo "*** error: @$TAG not hidden in $TMPDIR/ht-$base-$TAG.i" + exit 1 + fi + # In the egrep: All tags except $TAG and @internal & similar. + $DIFF $TMPDIR/ht-$base-normal.i $TMPDIR/ht-$base-$TAG.i > $TMPDIR/ht-$base-normal-$TAG.txt + if egrep '^-.*@(stable|draft|deprecated)' -C 5 $TMPDIR/ht-$base-normal-$TAG.txt; then + echo "*** error: Non-@$TAG hidden in $TMPDIR/ht-$base-$TAG.i see $TMPDIR/ht-$base-normal-$TAG.txt" + cat $TMPDIR/ht-$base-normal-$TAG.txt + exit 1 + fi +done + +echo "pass" +rm -rf $TMPDIR + diff -Nru icu-64.2/source/test/intltest/alphaindextst.cpp icu-65.1/source/test/intltest/alphaindextst.cpp --- icu-64.2/source/test/intltest/alphaindextst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/alphaindextst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -71,10 +71,19 @@ TESTCASE_AUTO_END; } -#define TEST_CHECK_STATUS {if (U_FAILURE(status)) {dataerrln("%s:%d: Test failure. status=%s", \ - __FILE__, __LINE__, u_errorName(status)); return;}} - -#define TEST_ASSERT(expr) {if ((expr)==FALSE) {errln("%s:%d: Test failure \n", __FILE__, __LINE__);};} +#define TEST_CHECK_STATUS UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + dataerrln("%s:%d: Test failure. status=%s", \ + __FILE__, __LINE__, u_errorName(status)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("%s:%d: Test failure \n", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END // // APITest. Invoke every function at least once, and check that it does something. @@ -87,34 +96,35 @@ UErrorCode status = U_ZERO_ERROR; int32_t lc = 0; int32_t i = 0; - AlphabeticIndex *index = new AlphabeticIndex(Locale::getEnglish(), status); + LocalPointer index(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; lc = index->getBucketCount(status); TEST_CHECK_STATUS; TEST_ASSERT(28 == lc); // 26 letters plus two under/overflow labels. //printf("getBucketCount() == %d\n", lc); - delete index; + index.adoptInstead(nullptr); // Constructor from a Collator // status = U_ZERO_ERROR; - RuleBasedCollator *coll = dynamic_cast( - Collator::createInstance(Locale::getGerman(), status)); + LocalPointer coll(dynamic_cast( + Collator::createInstance(Locale::getGerman(), status)), status); TEST_CHECK_STATUS; - TEST_ASSERT(coll != NULL); - index = new AlphabeticIndex(coll, status); + TEST_ASSERT(coll.isValid()); + RuleBasedCollator *originalColl = coll.getAlias(); + index.adoptInstead(new AlphabeticIndex(coll.orphan(), status)); TEST_CHECK_STATUS; - TEST_ASSERT(coll == &index->getCollator()); + TEST_ASSERT(originalColl == &index->getCollator()); assertEquals("only the underflow label in an index built from a collator", 1, index->getBucketCount(status)); TEST_CHECK_STATUS; - delete index; + index.adoptInstead(nullptr); // addLabels() status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getEnglish(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; UnicodeSet additions; additions.add((UChar32)0x410).add((UChar32)0x415); // A couple of Cyrillic letters @@ -125,32 +135,31 @@ assertEquals("underflow, A-Z, inflow, 2 Cyrillic, overflow", 31, index->getBucketCount(status)); // std::cout << lc << std::endl; - delete index; + index.adoptInstead(nullptr); // addLabels(Locale) status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getEnglish(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; AlphabeticIndex &aip = index->addLabels(Locale::getJapanese(), status); - TEST_ASSERT(&aip == index); + TEST_ASSERT(&aip == index.getAlias()); TEST_CHECK_STATUS; lc = index->getBucketCount(status); TEST_CHECK_STATUS; TEST_ASSERT(35 < lc); // Japanese should add a bunch. Don't rely on the exact value. - delete index; + index.adoptInstead(nullptr); // GetCollator(), Get under/in/over flow labels status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getGerman(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getGerman(), status)); TEST_CHECK_STATUS; - Collator *germanCol = Collator::createInstance(Locale::getGerman(), status); + LocalPointer germanCol(Collator::createInstance(Locale::getGerman(), status)); TEST_CHECK_STATUS; const RuleBasedCollator &indexCol = index->getCollator(); TEST_ASSERT(*germanCol == indexCol); - delete germanCol; UnicodeString ELLIPSIS; ELLIPSIS.append((UChar32)0x2026); UnicodeString s = index->getUnderflowLabel(); @@ -171,7 +180,7 @@ - delete index; + index.adoptInstead(nullptr); @@ -185,7 +194,7 @@ // addRecord(), verify that it comes back out. // status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getEnglish(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; index->addRecord(UnicodeString("Adam"), this, status); UBool b; @@ -208,12 +217,12 @@ const void *itemContext = index->getRecordData(); TEST_ASSERT(itemContext == this); - delete index; + index.adoptInstead(nullptr); // clearRecords, addRecord(), Iteration status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getEnglish(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; while (index->nextBucket(status)) { TEST_CHECK_STATUS; @@ -256,12 +265,12 @@ } } TEST_CHECK_STATUS; - delete index; + index.adoptInstead(nullptr); // getBucketLabel(), getBucketType() status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getEnglish(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; index->setUnderflowLabel(adam, status).setOverflowLabel(charlie, status); TEST_CHECK_STATUS; @@ -285,12 +294,12 @@ } } TEST_ASSERT(i==28); - delete index; + index.adoptInstead(nullptr); // getBucketIndex() status = U_ZERO_ERROR; - index = new AlphabeticIndex(Locale::getEnglish(), status); + index.adoptInstead(new AlphabeticIndex(Locale::getEnglish(), status)); TEST_CHECK_STATUS; int32_t n = index->getBucketIndex(adam, status); TEST_CHECK_STATUS; @@ -310,8 +319,8 @@ } TEST_ASSERT(i == 28); - delete index; - index = new AlphabeticIndex(Locale::createFromName("ru"), status); + index.adoptInstead(nullptr); + index.adoptInstead(new AlphabeticIndex(Locale::createFromName("ru"), status)); TEST_CHECK_STATUS; assertEquals("Russian index.getBucketCount()", 32, index->getBucketCount(status)); // Latin-script names should go into the underflow label (0) @@ -333,8 +342,6 @@ n = index->getBucketIndex(zed, status); assertEquals("Russian index.getBucketIndex(zed)", expectedLatinIndex, n); - delete index; - } @@ -497,7 +504,7 @@ /* Greek*/ {"el", "\\u0391:\\u0392:\\u0393:\\u0394:\\u0395:\\u0396:\\u0397:\\u0398:\\u0399:\\u039A:\\u039B:\\u039C:\\u039D:\\u039E:\\u039F:\\u03A0:\\u03A1:\\u03A3:\\u03A4:\\u03A5:\\u03A6:\\u03A7:\\u03A8:\\u03A9"}, /* English*/ {"en", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"}, /* Spanish*/ {"es", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\\u00D1:O:P:Q:R:S:T:U:V:W:X:Y:Z"}, - /* Estonian*/ {"et", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:\\u0160:Z:\\u017D:T:U:V:\\u00D5:\\u00C4:\\u00D6:\\u00DC:X:Y"}, + /* Estonian*/ {"et", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:\\u0160:Z:\\u017D:T:U:V:W:\\u00D5:\\u00C4:\\u00D6:\\u00DC:X:Y"}, /* Basque*/ {"eu", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"}, /* Finnish*/ {"fi", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\\u00C5:\\u00C4:\\u00D6"}, /* Filipino*/ {"fil", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\\u00D1:Ng:O:P:Q:R:S:T:U:V:W:X:Y:Z"}, diff -Nru icu-64.2/source/test/intltest/apicoll.cpp icu-65.1/source/test/intltest/apicoll.cpp --- icu-64.2/source/test/intltest/apicoll.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/apicoll.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -2000,7 +2000,7 @@ class TestCollator : public Collator { public: - virtual Collator* clone(void) const; + virtual TestCollator* clone() const; using Collator::compare; @@ -2048,9 +2048,9 @@ virtual UBool operator==(const Collator& other) const; // Collator::operator!= calls !Collator::operator== which works for all subclasses. virtual void setLocales(const Locale& requestedLocale, const Locale& validLocale, const Locale& actualLocale); - TestCollator() : Collator() {}; + TestCollator() : Collator() {} TestCollator(UCollationStrength collationStrength, - UNormalizationMode decompositionMode) : Collator(collationStrength, decompositionMode) {}; + UNormalizationMode decompositionMode) : Collator(collationStrength, decompositionMode) {} }; inline UBool TestCollator::operator==(const Collator& other) const { @@ -2065,7 +2065,7 @@ // (compare this vs. o's subclass fields) } -Collator* TestCollator::clone() const +TestCollator* TestCollator::clone() const { return new TestCollator(); } @@ -2345,7 +2345,7 @@ dump("c1", c1, status); logln("\ninit c2"); - RuleBasedCollator* c2 = (RuleBasedCollator*)c1->clone(); + RuleBasedCollator* c2 = c1->clone(); val = c2->getAttribute(UCOL_CASE_FIRST, status); if(val == UCOL_LOWER_FIRST){ c2->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status); diff -Nru icu-64.2/source/test/intltest/astrotst.cpp icu-65.1/source/test/intltest/astrotst.cpp --- icu-64.2/source/test/intltest/astrotst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/astrotst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -44,7 +44,12 @@ #undef CASE -#define ASSERT_OK(x) if(U_FAILURE(x)) { dataerrln("%s:%d: %s\n", __FILE__, __LINE__, u_errorName(x)); return; } +#define ASSERT_OK(x) UPRV_BLOCK_MACRO_BEGIN { \ + if(U_FAILURE(x)) { \ + dataerrln("%s:%d: %s\n", __FILE__, __LINE__, u_errorName(x)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END void AstroTest::initAstro(UErrorCode &status) { @@ -256,7 +261,7 @@ logln("Sunrise/Sunset times for Toronto, Canada"); // long = 79 25", lat = 43 40" - CalendarAstronomer *astro3 = new CalendarAstronomer(-(79+25/60), 43+40/60); + CalendarAstronomer astro3(-(79+25/60), 43+40/60); // As of ICU4J 2.8 the ICU4J time zones implement pass-through // to the underlying JDK. Because of variation in the @@ -266,46 +271,47 @@ // [aliu 10/15/03] // TimeZone tz = TimeZone.getTimeZone("America/Montreal"); - TimeZone *tz = new SimpleTimeZone(-18000000 + 3600000, "Montreal(FIXED)"); + SimpleTimeZone tz(-18000000 + 3600000, "Montreal(FIXED)"); - GregorianCalendar *cal = new GregorianCalendar(tz->clone(), Locale::getUS(), status); - GregorianCalendar *cal2 = new GregorianCalendar(tz->clone(), Locale::getUS(), status); - cal->clear(); - cal->set(UCAL_YEAR, 2001); - cal->set(UCAL_MONTH, UCAL_APRIL); - cal->set(UCAL_DAY_OF_MONTH, 1); - cal->set(UCAL_HOUR_OF_DAY, 12); // must be near local noon for getSunRiseSet to work - - DateFormat *df_t = DateFormat::createTimeInstance(DateFormat::MEDIUM,Locale::getUS()); - DateFormat *df_d = DateFormat::createDateInstance(DateFormat::MEDIUM,Locale::getUS()); - DateFormat *df_dt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::MEDIUM, Locale::getUS()); - if(!df_t || !df_d || !df_dt) { - dataerrln("couldn't create dateformats."); - return; - } - df_t->adoptTimeZone(tz->clone()); - df_d->adoptTimeZone(tz->clone()); - df_dt->adoptTimeZone(tz->clone()); + GregorianCalendar cal(tz.clone(), Locale::getUS(), status); + GregorianCalendar cal2(tz.clone(), Locale::getUS(), status); + cal.clear(); + cal.set(UCAL_YEAR, 2001); + cal.set(UCAL_MONTH, UCAL_APRIL); + cal.set(UCAL_DAY_OF_MONTH, 1); + cal.set(UCAL_HOUR_OF_DAY, 12); // must be near local noon for getSunRiseSet to work + + LocalPointer df_t(DateFormat::createTimeInstance(DateFormat::MEDIUM,Locale::getUS())); + LocalPointer df_d(DateFormat::createDateInstance(DateFormat::MEDIUM,Locale::getUS())); + LocalPointer df_dt(DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::MEDIUM, Locale::getUS())); + if(!df_t.isValid() || !df_d.isValid() || !df_dt.isValid()) { + dataerrln("couldn't create dateformats."); + closeAstro(status); + return; + } + df_t->adoptTimeZone(tz.clone()); + df_d->adoptTimeZone(tz.clone()); + df_dt->adoptTimeZone(tz.clone()); for (int32_t i=0; i < 30; i++) { logln("setDate\n"); - astro3->setDate(cal->getTime(status)); + astro3.setDate(cal.getTime(status)); logln("getRiseSet(TRUE)\n"); - UDate sunrise = astro3->getSunRiseSet(TRUE); + UDate sunrise = astro3.getSunRiseSet(TRUE); logln("getRiseSet(FALSE)\n"); - UDate sunset = astro3->getSunRiseSet(FALSE); + UDate sunset = astro3.getSunRiseSet(FALSE); logln("end of getRiseSet\n"); - cal2->setTime(cal->getTime(status), status); - cal2->set(UCAL_SECOND, 0); - cal2->set(UCAL_MILLISECOND, 0); - - cal2->set(UCAL_HOUR_OF_DAY, USNO[4*i+0]); - cal2->set(UCAL_MINUTE, USNO[4*i+1]); - UDate exprise = cal2->getTime(status); - cal2->set(UCAL_HOUR_OF_DAY, USNO[4*i+2]); - cal2->set(UCAL_MINUTE, USNO[4*i+3]); - UDate expset = cal2->getTime(status); + cal2.setTime(cal.getTime(status), status); + cal2.set(UCAL_SECOND, 0); + cal2.set(UCAL_MILLISECOND, 0); + + cal2.set(UCAL_HOUR_OF_DAY, USNO[4*i+0]); + cal2.set(UCAL_MINUTE, USNO[4*i+1]); + UDate exprise = cal2.getTime(status); + cal2.set(UCAL_HOUR_OF_DAY, USNO[4*i+2]); + cal2.set(UCAL_MINUTE, USNO[4*i+3]); + UDate expset = cal2.getTime(status); // Compute delta of what we got to the USNO data, in seconds int32_t deltarise = (int32_t)uprv_fabs((sunrise - exprise) / 1000); int32_t deltaset = (int32_t)uprv_fabs((sunset - expset) / 1000); @@ -318,34 +324,34 @@ UnicodeString s1, s2, s3, s4, s5; if (deltarise > MAX_DEV || deltaset > MAX_DEV) { if (deltarise > MAX_DEV) { - errln("FAIL: (rise) " + df_d->format(cal->getTime(status),s1) + + errln("FAIL: (rise) " + df_d->format(cal.getTime(status),s1) + ", Sunrise: " + df_dt->format(sunrise, s2) + " (USNO " + df_t->format(exprise,s3) + " d=" + deltarise + "s)"); } else { - logln(df_d->format(cal->getTime(status),s1) + + logln(df_d->format(cal.getTime(status),s1) + ", Sunrise: " + df_dt->format(sunrise,s2) + " (USNO " + df_t->format(exprise,s3) + ")"); } s1.remove(); s2.remove(); s3.remove(); s4.remove(); s5.remove(); if (deltaset > MAX_DEV) { - errln("FAIL: (set) " + df_d->format(cal->getTime(status),s1) + + errln("FAIL: (set) " + df_d->format(cal.getTime(status),s1) + ", Sunset: " + df_dt->format(sunset,s2) + " (USNO " + df_t->format(expset,s3) + " d=" + deltaset + "s)"); } else { - logln(df_d->format(cal->getTime(status),s1) + + logln(df_d->format(cal.getTime(status),s1) + ", Sunset: " + df_dt->format(sunset,s2) + " (USNO " + df_t->format(expset,s3) + ")"); } } else { - logln(df_d->format(cal->getTime(status),s1) + + logln(df_d->format(cal.getTime(status),s1) + ", Sunrise: " + df_dt->format(sunrise,s2) + " (USNO " + df_t->format(exprise,s3) + ")" + ", Sunset: " + df_dt->format(sunset,s4) + " (USNO " + df_t->format(expset,s5) + ")"); } - cal->add(UCAL_DATE, 1, status); + cal.add(UCAL_DATE, 1, status); } // CalendarAstronomer a = new CalendarAstronomer(-(71+5/60), 42+37/60); @@ -358,13 +364,6 @@ // cal.set(cal.DATE, 27); // a.setDate(cal.getTime()); // long r = a.getSunRiseSet2(true); - delete astro3; - delete tz; - delete cal; - delete cal2; - delete df_t; - delete df_d; - delete df_dt; closeAstro(status); ASSERT_OK(status); } @@ -380,38 +379,43 @@ } // Check that our JD computation is the same as the book's (p. 88) - GregorianCalendar *cal3 = new GregorianCalendar(TimeZone::getGMT()->clone(), Locale::getUS(), status); - DateFormat *d3 = DateFormat::createDateTimeInstance(DateFormat::MEDIUM,DateFormat::MEDIUM,Locale::getUS()); + GregorianCalendar cal3(TimeZone::getGMT()->clone(), Locale::getUS(), status); + LocalPointer d3(DateFormat::createDateTimeInstance(DateFormat::MEDIUM,DateFormat::MEDIUM,Locale::getUS())); + if (d3.isNull()) { + dataerrln("Got error: %s", u_errorName(status)); + closeAstro(status); + return; + } d3->setTimeZone(*TimeZone::getGMT()); - cal3->clear(); - cal3->set(UCAL_YEAR, 1980); - cal3->set(UCAL_MONTH, UCAL_JULY); - cal3->set(UCAL_DATE, 2); - logln("cal3[a]=%.1lf, d=%d\n", cal3->getTime(status), cal3->get(UCAL_JULIAN_DAY,status)); + cal3.clear(); + cal3.set(UCAL_YEAR, 1980); + cal3.set(UCAL_MONTH, UCAL_JULY); + cal3.set(UCAL_DATE, 2); + logln("cal3[a]=%.1lf, d=%d\n", cal3.getTime(status), cal3.get(UCAL_JULIAN_DAY,status)); { UnicodeString s; - logln(UnicodeString("cal3[a] = ") + d3->format(cal3->getTime(status),s)); + logln(UnicodeString("cal3[a] = ") + d3->format(cal3.getTime(status),s)); } - cal3->clear(); - cal3->set(UCAL_YEAR, 1980); - cal3->set(UCAL_MONTH, UCAL_JULY); - cal3->set(UCAL_DATE, 27); - logln("cal3=%.1lf, d=%d\n", cal3->getTime(status), cal3->get(UCAL_JULIAN_DAY,status)); + cal3.clear(); + cal3.set(UCAL_YEAR, 1980); + cal3.set(UCAL_MONTH, UCAL_JULY); + cal3.set(UCAL_DATE, 27); + logln("cal3=%.1lf, d=%d\n", cal3.getTime(status), cal3.get(UCAL_JULIAN_DAY,status)); ASSERT_OK(status); { UnicodeString s; - logln(UnicodeString("cal3 = ") + d3->format(cal3->getTime(status),s)); + logln(UnicodeString("cal3 = ") + d3->format(cal3.getTime(status),s)); } - astro->setTime(cal3->getTime(status)); + astro->setTime(cal3.getTime(status)); double jd = astro->getJulianDay() - 2447891.5; double exp = -3444.; if (jd == exp) { UnicodeString s; - logln(d3->format(cal3->getTime(status),s) + " => " + jd); + logln(d3->format(cal3.getTime(status),s) + " => " + jd); } else { UnicodeString s; - errln("FAIL: " + d3->format(cal3->getTime(status), s) + " => " + jd + + errln("FAIL: " + d3->format(cal3.getTime(status), s) + " => " + jd + ", expected " + exp); } @@ -423,8 +427,6 @@ // astro.setDate(cal3.getTime()); // astro.foo(); - delete cal3; - delete d3; ASSERT_OK(status); closeAstro(status); ASSERT_OK(status); diff -Nru icu-64.2/source/test/intltest/bytestrietest.cpp icu-65.1/source/test/intltest/bytestrietest.cpp --- icu-64.2/source/test/intltest/bytestrietest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/bytestrietest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -64,6 +64,7 @@ void checkFirst(BytesTrie &trie, const StringAndValue data[], int32_t dataLength); void checkNext(BytesTrie &trie, const StringAndValue data[], int32_t dataLength); void checkNextWithState(BytesTrie &trie, const StringAndValue data[], int32_t dataLength); + void checkNextWithState64(BytesTrie &trie, const StringAndValue data[], int32_t dataLength); void checkNextString(BytesTrie &trie, const StringAndValue data[], int32_t dataLength); void checkIterator(const BytesTrie &trie, const StringAndValue data[], int32_t dataLength); void checkIterator(BytesTrie::Iterator &iter, const StringAndValue data[], int32_t dataLength); @@ -613,6 +614,7 @@ checkFirst(*trie, data, dataLength); checkNext(*trie, data, dataLength); checkNextWithState(*trie, data, dataLength); + checkNextWithState64(*trie, data, dataLength); checkNextString(*trie, data, dataLength); checkIterator(*trie, data, dataLength); } @@ -817,6 +819,61 @@ data[i].s); } else if(trie.getValue()!=data[i].value) { errln("trie value for %s is %ld=0x%lx instead of expected %ld=0x%lx", + data[i].s, + (long)trie.getValue(), (long)trie.getValue(), + (long)data[i].value, (long)data[i].value); + } + trie.reset(); + } +} + +void BytesTrieTest::checkNextWithState64(BytesTrie &trie, + const StringAndValue data[], int32_t dataLength) { + assertTrue("trie(initial state).getState64()!=0", trie.getState64() != 0); + for(int32_t i=0; i(strlen(expectedString)); + int32_t partialLength = stringLength / 3; + for(int32_t j=0; jclone() ; + GregorianCalendar *cal2 = cal1->clone() ; printdate(cal1, "cal1: ") ; printdate(cal2, "cal2 - cloned(): ") ; @@ -1455,31 +1456,26 @@ void CalendarRegressionTest::test4125881() { UErrorCode status = U_ZERO_ERROR; - GregorianCalendar *cal = (GregorianCalendar*) Calendar::createInstance(status); + LocalPointer cal((GregorianCalendar*) Calendar::createInstance(status), status); if(U_FAILURE(status)) { - dataerrln("Error creating calendar %s", u_errorName(status)); - delete cal; - return; + dataerrln("Error creating calendar %s", u_errorName(status)); + return; } - DateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"),status); + SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"),status); if(U_FAILURE(status)) { - dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status)); - delete cal; - return; + dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status)); + return; } cal->clear(); for (int32_t y=-20; y<=10; ++y) { cal->set(UCAL_ERA, y < 1 ? GregorianCalendar::BC : GregorianCalendar::AD); cal->set(UCAL_YEAR, y < 1 ? 1 - y : y); UnicodeString temp; - logln(UnicodeString("") + y + UnicodeString(" = ") + fmt->format(cal->getTime(status), temp) + " " + + logln(UnicodeString("") + y + UnicodeString(" = ") + fmt.format(cal->getTime(status), temp) + " " + cal->isLeapYear(y)); if (cal->isLeapYear(y) != ((y+40)%4 == 0)) errln("Leap years broken"); } - - delete cal; - delete fmt; } /** @@ -1489,17 +1485,15 @@ */ void CalendarRegressionTest::test4125892() { UErrorCode status = U_ZERO_ERROR; - GregorianCalendar *cal = (GregorianCalendar*) Calendar::createInstance(status); + LocalPointer cal((GregorianCalendar*) Calendar::createInstance(status), status); if(U_FAILURE(status)) { - dataerrln("Error creating calendar %s", u_errorName(status)); - delete cal; - return; + dataerrln("Error creating calendar %s", u_errorName(status)); + return; } - DateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"),status); + SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"),status); if(U_FAILURE(status)) { - dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status)); - delete cal; - return; + dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status)); + return; } cal->clear(); cal->set(UCAL_ERA, GregorianCalendar::BC); @@ -1513,8 +1507,6 @@ !cal->isLeapYear(-80)) // -80 == 81 BC errln("Calendar not proleptic"); - delete cal; - delete fmt; } /** @@ -1530,7 +1522,7 @@ delete cal; return; } - GregorianCalendar *cal2 = (GregorianCalendar*)cal->clone(); + GregorianCalendar *cal2 = cal->clone(); UDate cut = cal->getGregorianChange(); UDate cut2 = cut + 100*24*60*60*1000.0; // 100 days later if (*cal != *cal2) { @@ -1545,6 +1537,41 @@ delete cal2; } +const UDate MILLIS_IN_DAY = 86400000.0; +/** + * ICU-13745 + * GregorianCalendar::setGregorianChange() overflow + */ +void CalendarRegressionTest::Test13745() +{ + UErrorCode status = U_ZERO_ERROR; + GregorianCalendar *cal = new GregorianCalendar(status); + if(U_FAILURE(status)) { + dataerrln("Error creating calendar %s", u_errorName(status)); + delete cal; + return; + } + + // this line would overflow before fix 13745 + cal->setGregorianChange(((double)INT32_MAX+1.0) * MILLIS_IN_DAY, status); + if(U_FAILURE(status)) { + errln("%s:%d Failure setting INT32_MAX+1 change on calendar: %s\n", __FILE__, __LINE__, u_errorName(status)); + return; + } + assertEquals("getGregorianChange()", (double)INT32_MAX * MILLIS_IN_DAY, cal->getGregorianChange()); + + // test underflow + cal->setGregorianChange(((double)INT32_MIN-1.0) * MILLIS_IN_DAY, status); + if(U_FAILURE(status)) { + errln("%s:%d Failure setting INT32_MAX-1 change on calendar: %s\n", __FILE__, __LINE__, u_errorName(status)); + return; + } + assertEquals("getGregorianChange()", (double)INT32_MIN * MILLIS_IN_DAY, cal->getGregorianChange()); + + delete cal; +} + + /** * @bug 4142933 * Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar::roll() @@ -1913,22 +1940,21 @@ { UErrorCode status = U_ZERO_ERROR; UCalendarDateFields field = UCAL_YEAR; - DateFormat *format = new SimpleDateFormat(UnicodeString("EEE MMM dd HH:mm:ss zzz yyyy G"), - Locale::getUS(), status); + LocalPointer format (new SimpleDateFormat(UnicodeString("EEE MMM dd HH:mm:ss zzz yyyy G"), + Locale::getUS(), status)); if(U_FAILURE(status)) { dataerrln("Couldn't create SimpleDateFormat - %s", u_errorName(status)); return; } - GregorianCalendar *calendars [] = { - new GregorianCalendar(100, UCAL_NOVEMBER, 1, status), - new GregorianCalendar(-99 /*100BC*/, UCAL_JANUARY, 1, status), - new GregorianCalendar(1996, UCAL_FEBRUARY, 29, status), + GregorianCalendar calendars [] = { + {100, UCAL_NOVEMBER, 1, status}, + {-99 /*100BC*/, UCAL_JANUARY, 1, status}, + {1996, UCAL_FEBRUARY, 29, status} }; if(U_FAILURE(status)) { errln("Couldn't create GregorianCalendars"); return; - // could leak } UnicodeString id [] = { "Hybrid", "Gregorian", "Julian" }; @@ -1937,7 +1963,7 @@ logln("--- " + id[k] + " ---"); for (int32_t j=0; j < 3; ++j) { - GregorianCalendar *calendar = calendars[j]; + GregorianCalendar *calendar = &calendars[j]; if (k == 1) { calendar->setGregorianChange(EARLIEST_SUPPORTED_MILLIS, status); } @@ -1947,7 +1973,7 @@ if(U_FAILURE(status)) errln("setGregorianChange() failed"); - format->adoptCalendar((Calendar*)calendar->clone()); + format->adoptCalendar(calendar->clone()); UDate dateBefore = calendar->getTime(status); if(U_FAILURE(status)) @@ -1988,11 +2014,6 @@ } } } - - delete format; - delete calendars[0]; - delete calendars[1]; - delete calendars[2]; } /** @@ -2283,15 +2304,18 @@ 1999, UCAL_JUNE, 4, 1964, UCAL_SEPTEMBER, 7, }; int32_t DATA_length = UPRV_LENGTHOF(DATA); - Calendar* pcal = Calendar::createInstance(Locale::getUS(), ec); + LocalPointer pcal(Calendar::createInstance(Locale::getUS(), ec)); if(U_FAILURE(ec)) { - dataerrln("Error creating calendar %s", u_errorName(ec)); - delete pcal; - return; + dataerrln("Error creating calendar %s", u_errorName(ec)); + return; } Calendar& cal = *pcal; int32_t i; SimpleDateFormat fmt(UnicodeString("MMM dd yyyy",""), ec); + if (U_FAILURE(ec)) { + dataerrln("Error creating calendar %s", u_errorName(ec)); + return; + } fmt.setCalendar(cal); UnicodeString s, t, u; if (U_SUCCESS(ec)) { @@ -2323,7 +2347,7 @@ break; { - Calendar *cal2 = cal.clone(); + LocalPointer cal2(cal.clone()); UErrorCode ec2 = U_ZERO_ERROR; cal2->setTime(date1, ec2); @@ -2338,7 +2362,6 @@ (dy2 != dy)){ errln("fieldDifference(UCAL_...) and fieldDifference(Calendar::...) give different results!\n"); } - delete cal2; } @@ -2374,7 +2397,6 @@ } else { dataerrln("Error creating SimpleDateFormat - %s", u_errorName(ec)); } - delete pcal; } void CalendarRegressionTest::TestT5555() diff -Nru icu-64.2/source/test/intltest/calregts.h icu-65.1/source/test/intltest/calregts.h --- icu-64.2/source/test/intltest/calregts.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/calregts.h 2019-10-03 11:16:41.000000000 +0000 @@ -82,6 +82,8 @@ void TestIslamicCalOverflow(void); void TestWeekOfYear13548(void); + void Test13745(void); + void printdate(GregorianCalendar *cal, const char *string); void dowTest(UBool lenient) ; diff -Nru icu-64.2/source/test/intltest/caltest.cpp icu-65.1/source/test/intltest/caltest.cpp --- icu-64.2/source/test/intltest/caltest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/caltest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -25,23 +25,33 @@ #define mkcstr(U) u_austrcpy(calloc(8, u_strlen(U) + 1), U) -#define TEST_CHECK_STATUS { \ +#define TEST_CHECK_STATUS UPRV_BLOCK_MACRO_BEGIN { \ if (U_FAILURE(status)) { \ if (status == U_MISSING_RESOURCE_ERROR) { \ dataerrln("%s:%d: Test failure. status=%s", __FILE__, __LINE__, u_errorName(status)); \ } else { \ errln("%s:%d: Test failure. status=%s", __FILE__, __LINE__, u_errorName(status)); \ - } return;}} + } \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END -#define TEST_CHECK_STATUS_LOCALE(testlocale) { \ +#define TEST_CHECK_STATUS_LOCALE(testlocale) UPRV_BLOCK_MACRO_BEGIN { \ if (U_FAILURE(status)) { \ if (status == U_MISSING_RESOURCE_ERROR) { \ dataerrln("%s:%d: Test failure, locale %s. status=%s", __FILE__, __LINE__, testlocale, u_errorName(status)); \ } else { \ errln("%s:%d: Test failure, locale %s. status=%s", __FILE__, __LINE__, testlocale, u_errorName(status)); \ - } return;}} + } \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END -#define TEST_ASSERT(expr) {if ((expr)==FALSE) {errln("%s:%d: Test failure \n", __FILE__, __LINE__);};} +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("%s:%d: Test failure \n", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END // ***************************************************************************** // class CalendarTest @@ -740,7 +750,7 @@ UErrorCode status = U_ZERO_ERROR; Calendar *c = Calendar::createInstance(status); if (failure(status, "Calendar::createInstance", TRUE)) return; - Calendar *d = (Calendar*) c->clone(); + Calendar *d = c->clone(); c->set(UCAL_MILLISECOND, 123); d->set(UCAL_MILLISECOND, 456); if (c->get(UCAL_MILLISECOND, status) != 123 || @@ -1110,7 +1120,11 @@ status = U_ZERO_ERROR; for (i = 0; i < limit; i++) { temp->add(e, 1, status); - if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; } + if (U_FAILURE(status)) { + limit = i; + status = U_ZERO_ERROR; + break; // Suppress compile warning. Shouldn't be necessary, but it is. + } } for (i = 0; i < limit; i++) { temp->add(e, -1, status); @@ -1718,7 +1732,7 @@ CalendarTest::marchByDelta(Calendar* cal, int32_t delta) { UErrorCode status = U_ZERO_ERROR; - Calendar *cur = (Calendar*) cal->clone(); + Calendar *cur = cal->clone(); int32_t initialDOW = cur->get(UCAL_DAY_OF_WEEK, status); if (U_FAILURE(status)) { errln("Calendar::get failed"); return; } int32_t DOW, newDOW = initialDOW; @@ -1743,11 +1757,12 @@ delete cur; } -#define CHECK(status, msg) \ +#define CHECK(status, msg) UPRV_BLOCK_MACRO_BEGIN { \ if (U_FAILURE(status)) { \ errcheckln(status, msg); \ return; \ - } + } \ +} UPRV_BLOCK_MACRO_END void CalendarTest::TestWOY(void) { /* @@ -2169,7 +2184,7 @@ if(gLocaleCount < 0) { int32_t i; for(i=0;testLocaleID(i) != NULL;i++) { - ; + // do nothing } gLocaleCount = i; } diff -Nru icu-64.2/source/test/intltest/citrtest.cpp icu-65.1/source/test/intltest/citrtest.cpp --- icu-64.2/source/test/intltest/citrtest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/citrtest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -36,7 +36,7 @@ } - virtual ~SCharacterIterator(){}; + virtual ~SCharacterIterator(){} void setText(const UnicodeString& newText){ @@ -57,7 +57,7 @@ return TRUE; } - virtual CharacterIterator* clone(void) const { + virtual SCharacterIterator* clone(void) const { return NULL; } virtual int32_t hashCode(void) const{ @@ -65,19 +65,19 @@ } virtual UChar nextPostInc(void){ return text.charAt(pos++);} virtual UChar32 next32PostInc(void){return text.char32At(pos++);} - virtual UBool hasNext() { return TRUE;}; - virtual UChar first(){return DONE;}; - virtual UChar32 first32(){return DONE;}; - virtual UChar last(){return DONE;}; - virtual UChar32 last32(){return DONE;}; - virtual UChar setIndex(int32_t /*pos*/){return DONE;}; - virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;}; - virtual UChar current() const{return DONE;}; - virtual UChar32 current32() const{return DONE;}; - virtual UChar next(){return DONE;}; - virtual UChar32 next32(){return DONE;}; - virtual UChar previous(){return DONE;}; - virtual UChar32 previous32(){return DONE;}; + virtual UBool hasNext() { return TRUE;} + virtual UChar first(){return DONE;} + virtual UChar32 first32(){return DONE;} + virtual UChar last(){return DONE;} + virtual UChar32 last32(){return DONE;} + virtual UChar setIndex(int32_t /*pos*/){return DONE;} + virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;} + virtual UChar current() const{return DONE;} + virtual UChar32 current32() const{return DONE;} + virtual UChar next(){return DONE;} + virtual UChar32 next32(){return DONE;} + virtual UChar previous(){return DONE;} + virtual UChar32 previous32(){return DONE;} virtual int32_t move(int32_t delta,CharacterIterator::EOrigin origin){ switch(origin) { case kStart: @@ -100,7 +100,7 @@ } return pos; - }; + } virtual int32_t move32(int32_t delta, CharacterIterator::EOrigin origin){ switch(origin) { case kStart: @@ -127,8 +127,8 @@ } return pos; - }; - virtual UBool hasPrevious() {return TRUE;}; + } + virtual UBool hasPrevious() {return TRUE;} SCharacterIterator& operator=(const SCharacterIterator& that){ text = that.text; @@ -198,7 +198,7 @@ UnicodeString testText2("Don't bother using this string."); UnicodeString result1, result2, result3; - CharacterIterator* test1 = new StringCharacterIterator(testText); + StringCharacterIterator* test1 = new StringCharacterIterator(testText); CharacterIterator* test1b= new StringCharacterIterator(testText, -1); CharacterIterator* test1c= new StringCharacterIterator(testText, 100); CharacterIterator* test1d= new StringCharacterIterator(testText, -2, 100, 5); @@ -257,7 +257,7 @@ StringCharacterIterator* testChar1=new StringCharacterIterator(testText); StringCharacterIterator* testChar2=new StringCharacterIterator(testText2); - StringCharacterIterator* testChar3=(StringCharacterIterator*)test1->clone(); + StringCharacterIterator* testChar3=test1->clone(); testChar1->getText(result1); testChar2->getText(result2); @@ -292,7 +292,7 @@ UCharCharacterIterator* test2 = new UCharCharacterIterator(testText, u_strlen(testText), 5); UCharCharacterIterator* test3 = new UCharCharacterIterator(testText, u_strlen(testText), 2, 20, 5); UCharCharacterIterator* test4 = new UCharCharacterIterator(testText2, u_strlen(testText2)); - UCharCharacterIterator* test5 = (UCharCharacterIterator*)test1->clone(); + UCharCharacterIterator* test5 = test1->clone(); UCharCharacterIterator* test6 = new UCharCharacterIterator(*test1); // j785: length=-1 will use u_strlen() diff -Nru icu-64.2/source/test/intltest/compactdecimalformattest.cpp icu-65.1/source/test/intltest/compactdecimalformattest.cpp --- icu-64.2/source/test/intltest/compactdecimalformattest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/compactdecimalformattest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -168,21 +168,21 @@ {-5300.0, "\\u061C-\\u0665\\u066B\\u0663 \\u0623\\u0644\\u0641"}}; static ExpectedResult kChineseCurrencyTestData[] = { - {1.0, "\\uFFE51"}, - {12.0, "\\uFFE512"}, - {123.0, "\\uFFE5120"}, - {1234.0, "\\uFFE51200"}, - {12345.0, "\\uFFE51.2\\u4E07"}, - {123456.0, "\\uFFE512\\u4E07"}, - {1234567.0, "\\uFFE5120\\u4E07"}, - {12345678.0, "\\uFFE51200\\u4E07"}, - {123456789.0, "\\uFFE51.2\\u4EBF"}, - {1234567890.0, "\\uFFE512\\u4EBF"}, - {12345678901.0, "\\uFFE5120\\u4EBF"}, - {123456789012.0, "\\uFFE51200\\u4EBF"}, - {1234567890123.0, "\\uFFE51.2\\u5146"}, - {12345678901234.0, "\\uFFE512\\u5146"}, - {123456789012345.0, "\\uFFE5120\\u5146"}, + {1.0, "\\u00A51"}, + {12.0, "\\u00A512"}, + {123.0, "\\u00A5120"}, + {1234.0, "\\u00A51200"}, + {12345.0, "\\u00A51.2\\u4E07"}, + {123456.0, "\\u00A512\\u4E07"}, + {1234567.0, "\\u00A5120\\u4E07"}, + {12345678.0, "\\u00A51200\\u4E07"}, + {123456789.0, "\\u00A51.2\\u4EBF"}, + {1234567890.0, "\\u00A512\\u4EBF"}, + {12345678901.0, "\\u00A5120\\u4EBF"}, + {123456789012.0, "\\u00A51200\\u4EBF"}, + {1234567890123.0, "\\u00A51.2\\u4E07\\u4EBF"}, + {12345678901234.0, "\\u00A512\\u4E07\\u4EBF"}, + {123456789012345.0, "\\u00A5120\\u4E07\\u4EBF"}, }; static ExpectedResult kGermanCurrencyTestData[] = { {1.0, u8"1\\u00A0\\u20AC"}, diff -Nru icu-64.2/source/test/intltest/convtest.cpp icu-65.1/source/test/intltest/convtest.cpp --- icu-64.2/source/test/intltest/convtest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/convtest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -651,26 +651,26 @@ const char *pattern_ignorable = "[:Default_Ignorable_Code_Point:]"; const char *pattern_not_ignorable = "[:^Default_Ignorable_Code_Point:]"; - UnicodeSet *set_ignorable = new UnicodeSet(pattern_ignorable, status); + LocalPointer set_ignorable(new UnicodeSet(pattern_ignorable, status)); if (U_FAILURE(status)) { dataerrln("Unable to create Unicodeset: %s - %s\n", pattern_ignorable, u_errorName(status)); return; } - UnicodeSet *set_not_ignorable = new UnicodeSet(pattern_not_ignorable, status); + LocalPointer set_not_ignorable(new UnicodeSet(pattern_not_ignorable, status)); if (U_FAILURE(status)) { dataerrln("Unable to create Unicodeset: %s - %s\n", pattern_not_ignorable, u_errorName(status)); return; } - UConverter *cnv = cnv_open(cnv_name, status); + LocalUConverterPointer cnv(cnv_open(cnv_name, status)); if (U_FAILURE(status)) { dataerrln("Unable to open converter: %s - %s\n", cnv_name, u_errorName(status)); return; } // set callback for the converter - ucnv_setFromUCallBack(cnv, UCNV_FROM_U_CALLBACK_SUBSTITUTE, NULL, NULL, NULL, &status); + ucnv_setFromUCallBack(cnv.getAlias(), UCNV_FROM_U_CALLBACK_SUBSTITUTE, NULL, NULL, NULL, &status); UChar32 input[1]; char output[10]; @@ -684,7 +684,7 @@ input[0] = set_ignorable->charAt(i); - outputLength = ucnv_fromUChars(cnv, output, 10, UnicodeString::fromUTF32(input, 1).getTerminatedBuffer(), -1, &status); + outputLength = ucnv_fromUChars(cnv.getAlias(), output, 10, UnicodeString::fromUTF32(input, 1).getTerminatedBuffer(), -1, &status); if (U_FAILURE(status) || outputLength != 0) { errln("Ignorable code point: U+%04X not skipped as expected - %s", input[0], u_errorName(status)); } @@ -702,15 +702,11 @@ continue; } - outputLength = ucnv_fromUChars(cnv, output, 10, UnicodeString::fromUTF32(input, 1).getTerminatedBuffer(), -1, &status); + outputLength = ucnv_fromUChars(cnv.getAlias(), output, 10, UnicodeString::fromUTF32(input, 1).getTerminatedBuffer(), -1, &status); if (U_FAILURE(status) || outputLength <= 0) { errln("Non-ignorable code point: U+%04X skipped unexpectedly - %s", input[0], u_errorName(status)); } } - - ucnv_close(cnv); - delete set_not_ignorable; - delete set_ignorable; } void diff -Nru icu-64.2/source/test/intltest/cpdtrtst.cpp icu-65.1/source/test/intltest/cpdtrtst.cpp --- icu-64.2/source/test/intltest/cpdtrtst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/cpdtrtst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -159,10 +159,10 @@ errln("Error: =operator or copy constructor failed"); } - CompoundTransliterator *clonect1a=(CompoundTransliterator*)ct1->clone(); - CompoundTransliterator *clonect1b=(CompoundTransliterator*)equalct1.clone(); - CompoundTransliterator *clonect2a=(CompoundTransliterator*)ct2->clone(); - CompoundTransliterator *clonect2b=(CompoundTransliterator*)copyct2->clone(); + CompoundTransliterator *clonect1a=ct1->clone(); + CompoundTransliterator *clonect1b=equalct1.clone(); + CompoundTransliterator *clonect2a=ct2->clone(); + CompoundTransliterator *clonect2b=copyct2->clone(); if(clonect1a->getID() != ct1->getID() || clonect1a->getCount() != ct1->getCount() || diff -Nru icu-64.2/source/test/intltest/csdetest.cpp icu-65.1/source/test/intltest/csdetest.cpp --- icu-64.2/source/test/intltest/csdetest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/csdetest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -20,6 +20,7 @@ #include "xmlparser.h" +#include #include #include @@ -27,18 +28,22 @@ #include #endif -#define NEW_ARRAY(type,count) (type *) /*uprv_*/malloc((count) * sizeof(type)) -#define DELETE_ARRAY(array) /*uprv_*/free((void *) (array)) #define CH_SPACE 0x0020 #define CH_SLASH 0x002F -#define TEST_ASSERT(x) {if (!(x)) { \ - errln("Failure in file %s, line %d", __FILE__, __LINE__);}} - -#define TEST_ASSERT_SUCCESS(errcode) { if (U_FAILURE(errcode)) { \ - errcheckln(errcode, "Failure in file %s, line %d, status = \"%s\"", __FILE__, __LINE__, u_errorName(errcode));\ - return;}} +#define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(x)) { \ + errln("Failure in file %s, line %d", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_SUCCESS(errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(errcode)) { \ + errcheckln(errcode, "Failure in file %s, line %d, status = \"%s\"", __FILE__, __LINE__, u_errorName(errcode)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END //--------------------------------------------------------------------------- @@ -142,23 +147,18 @@ length = source.extract(0, sLength, NULL, codepage); if (length > 0) { - bytes = NEW_ARRAY(char, length + 1); + bytes = new char[length + 1]; source.extract(0, sLength, bytes, codepage); } return bytes; } -static void freeBytes(char *bytes) -{ - DELETE_ARRAY(bytes); -} - void CharsetDetectionTest::checkEncoding(const UnicodeString &testString, const UnicodeString &encoding, const UnicodeString &id) { int32_t splits = 0; int32_t testLength = testString.length(); - UnicodeString *eSplit = split(encoding, CH_SLASH, splits); + std::unique_ptr eSplit(split(encoding, CH_SLASH, splits)); UErrorCode status = U_ZERO_ERROR; int32_t cpLength = eSplit[0].length(); char codepage[64]; @@ -169,16 +169,16 @@ LocalUCharsetDetectorPointer csd(ucsdet_open(&status)); int32_t byteLength = 0; - char *bytes = extractBytes(testString, codepage, byteLength); + std::unique_ptr bytes(extractBytes(testString, codepage, byteLength)); - if (bytes == NULL) { + if (! bytes) { #if !UCONFIG_NO_LEGACY_CONVERSION dataerrln("Can't open a " + encoding + " converter for " + id); #endif return; } - ucsdet_setText(csd.getAlias(), bytes, byteLength, &status); + ucsdet_setText(csd.getAlias(), bytes.get(), byteLength, &status); int32_t matchCount = 0; const UCharsetMatch **matches = ucsdet_detectAll(csd.getAlias(), &matchCount, &status); @@ -191,7 +191,7 @@ if (matchCount == 0) { errln("Encoding detection failure for " + id + ": expected " + eSplit[0] + ", got no matches"); - goto bail; + return; } if (name.compare(eSplit[0]) != 0) { @@ -206,15 +206,15 @@ printf("%s (%s) %d\n", name, lang, confidence); } #endif - goto bail; + return; } if (splits > 1 && lang.compare(eSplit[1]) != 0) { errln("Language detection failure for " + id + ", " + eSplit[0] + ": expected " + eSplit[1] + ", got " + lang); - goto bail; + return; } - decoded = NEW_ARRAY(UChar, testLength); + decoded = new UChar[testLength]; dLength = ucsdet_getUChars(matches[0], decoded, testLength, &status); if (testString.compare(decoded, dLength) != 0) { @@ -231,11 +231,7 @@ } - DELETE_ARRAY(decoded); - -bail: - freeBytes(bytes); - delete[] eSplit; + delete[] decoded; } const char *CharsetDetectionTest::getPath(char buffer[2048], const char *filename) { @@ -328,7 +324,7 @@ char *bytes = extractBytes(s, "UTF-8", byteLength); UCharsetDetector *csd = ucsdet_open(&status); const UCharsetMatch *match; - UChar *detected = NEW_ARRAY(UChar, sLength); + UChar *detected = new UChar[sLength]; ucsdet_setText(csd, bytes, byteLength, &status); match = ucsdet_detect(csd, &status); @@ -347,8 +343,8 @@ ucsdet_setDeclaredEncoding(csd, "UTF-8", 5, &status); /* for coverage */ bail: - DELETE_ARRAY(detected); - freeBytes(bytes); + delete[] detected; + delete[] bytes; ucsdet_close(csd); } @@ -364,66 +360,55 @@ 0x064a, 0x062a, 0x0000}; UnicodeString s(chars); int32_t beLength = 0, leLength = 0; - char *beBytes = extractBytes(s, "UTF-16BE", beLength); - char *leBytes = extractBytes(s, "UTF-16LE", leLength); - UCharsetDetector *csd = ucsdet_open(&status); + std::unique_ptrbeBytes(extractBytes(s, "UTF-16BE", beLength)); + std::unique_ptrleBytes(extractBytes(s, "UTF-16LE", leLength)); + LocalUCharsetDetectorPointer csd(ucsdet_open(&status)); const UCharsetMatch *match; const char *name; int32_t conf; - ucsdet_setText(csd, beBytes, beLength, &status); - match = ucsdet_detect(csd, &status); + ucsdet_setText(csd.getAlias(), beBytes.get(), beLength, &status); + match = ucsdet_detect(csd.getAlias(), &status); if (match == NULL) { errln("Encoding detection failure for UTF-16BE: got no matches."); - goto try_le; - } - - name = ucsdet_getName(match, &status); - conf = ucsdet_getConfidence(match, &status); + } else { - if (strcmp(name, "UTF-16BE") != 0) { - errln("Encoding detection failure for UTF-16BE: got %s", name); - goto try_le; // no point in looking at confidence if we got the wrong character set. - } + name = ucsdet_getName(match, &status); + conf = ucsdet_getConfidence(match, &status); - if (conf != 100) { - errln("Did not get 100%% confidence for UTF-16BE: got %d", conf); + if (strcmp(name, "UTF-16BE") != 0) { + errln("Encoding detection failure for UTF-16BE: got %s", name); + } else if (conf != 100) { + errln("Did not get 100%% confidence for UTF-16BE: got %d", conf); + } } -try_le: - ucsdet_setText(csd, leBytes, leLength, &status); - match = ucsdet_detect(csd, &status); + ucsdet_setText(csd.getAlias(), leBytes.get(), leLength, &status); + match = ucsdet_detect(csd.getAlias(), &status); if (match == NULL) { errln("Encoding detection failure for UTF-16LE: got no matches."); - goto bail; + return; } name = ucsdet_getName(match, &status); conf = ucsdet_getConfidence(match, &status); - if (strcmp(name, "UTF-16LE") != 0) { errln("Enconding detection failure for UTF-16LE: got %s", name); - goto bail; // no point in looking at confidence if we got the wrong character set. + return; } if (conf != 100) { errln("Did not get 100%% confidence for UTF-16LE: got %d", conf); } - -bail: - freeBytes(leBytes); - freeBytes(beBytes); - ucsdet_close(csd); } void CharsetDetectionTest::InputFilterTest() { UErrorCode status = U_ZERO_ERROR; - UnicodeString ss = " Un tr\\u00E8s petit peu de Fran\\u00E7ais. "; - UnicodeString s = ss.unescape(); + UnicodeString s(u" Un très petit peu de Français. "); int32_t byteLength = 0; char *bytes = extractBytes(s, "ISO-8859-1", byteLength); UCharsetDetector *csd = ucsdet_open(&status); @@ -480,7 +465,7 @@ } bail: - freeBytes(bytes); + delete[] bytes; ucsdet_close(csd); } @@ -527,8 +512,8 @@ } bail: - freeBytes(bWindows); - freeBytes(bISO); + delete[] bWindows; + delete[] bISO; ucsdet_close(csd); #endif @@ -674,8 +659,8 @@ } bail: - freeBytes(bytes); - freeBytes(bytes_r); + delete[] bytes; + delete[] bytes_r; ucsdet_close(csd); #endif } @@ -764,8 +749,8 @@ } bail: - freeBytes(bytes); - freeBytes(bytes_r); + delete[] bytes; + delete[] bytes_r; ucsdet_close(csd); #endif } @@ -825,23 +810,23 @@ "It also includes some \\u201CC1\\u201D bytes.", -1, US_INV); UnicodeString sWindows = ssWindows.unescape(); int32_t lISO = 0, lWindows = 0; - char *bISO = extractBytes(sISO, "ISO-8859-1", lISO); - char *bWindows = extractBytes(sWindows, "windows-1252", lWindows); + std::unique_ptr bISO(extractBytes(sISO, "ISO-8859-1", lISO)); + std::unique_ptr bWindows(extractBytes(sWindows, "windows-1252", lWindows)); // First do a plain vanilla detect of 1252 text - UCharsetDetector *csd1 = ucsdet_open(&status); - ucsdet_setText(csd1, bWindows, lWindows, &status); - const UCharsetMatch *match1 = ucsdet_detect(csd1, &status); + LocalUCharsetDetectorPointer csd1(ucsdet_open(&status)); + ucsdet_setText(csd1.getAlias(), bWindows.get(), lWindows, &status); + const UCharsetMatch *match1 = ucsdet_detect(csd1.getAlias(), &status); const char *name1 = ucsdet_getName(match1, &status); TEST_ASSERT_SUCCESS(status); TEST_ASSERT(strcmp(name1, "windows-1252")==0); // Next, using a completely separate detector, detect some 8859-1 text - UCharsetDetector *csd2 = ucsdet_open(&status); - ucsdet_setText(csd2, bISO, lISO, &status); - const UCharsetMatch *match2 = ucsdet_detect(csd2, &status); + LocalUCharsetDetectorPointer csd2(ucsdet_open(&status)); + ucsdet_setText(csd2.getAlias(), bISO.get(), lISO, &status); + const UCharsetMatch *match2 = ucsdet_detect(csd2.getAlias(), &status); const char *name2 = ucsdet_getName(match2, &status); TEST_ASSERT_SUCCESS(status); TEST_ASSERT(strcmp(name2, "ISO-8859-1")==0); @@ -852,10 +837,5 @@ name1 = ucsdet_getName(match1, &status); TEST_ASSERT_SUCCESS(status); TEST_ASSERT(strcmp(name1, "windows-1252")==0); - - ucsdet_close(csd1); - ucsdet_close(csd2); - freeBytes(bISO); - freeBytes(bWindows); #endif } diff -Nru icu-64.2/source/test/intltest/dadrcal.cpp icu-65.1/source/test/intltest/dadrcal.cpp --- icu-64.2/source/test/intltest/dadrcal.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dadrcal.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -366,7 +366,7 @@ void DataDrivenCalendarTest::testConvert(TestData *testData, const DataMap *settings, UBool forward) { UErrorCode status = U_ZERO_ERROR; - Calendar *toCalendar= NULL; + LocalPointer toCalendar; const DataMap *currentCase= NULL; char toCalLoc[256] = ""; char fromCalLoc[256] = ""; @@ -374,7 +374,7 @@ UnicodeString testSetting = settings->getString("ToCalendar", status); if (U_SUCCESS(status)) { testSetting.extract(0, testSetting.length(), toCalLoc, (const char*)0); - toCalendar = Calendar::createInstance(toCalLoc, status); + toCalendar.adoptInstead(Calendar::createInstance(toCalLoc, status)); if (U_FAILURE(status)) { dataerrln(UnicodeString("Unable to instantiate ToCalendar for ")+testSetting); return; @@ -393,11 +393,11 @@ int n = 0; while (testData->nextCase(currentCase, status)) { ++n; - Calendar *fromCalendar= NULL; + LocalPointer fromCalendar; UnicodeString locale = currentCase->getString("locale", status); if (U_SUCCESS(status)) { locale.extract(0, locale.length(), fromCalLoc, (const char*)0); // default codepage. Invariant codepage doesn't have '@'! - fromCalendar = Calendar::createInstance(fromCalLoc, status); + fromCalendar.adoptInstead(Calendar::createInstance(fromCalLoc, status)); if (U_FAILURE(status)) { errln("Unable to instantiate fromCalendar for "+locale); return; @@ -435,16 +435,13 @@ if (forward) { logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/" +to); - testConvert(n, fromSet, fromCalendar, toSet, toCalendar, forward); + testConvert(n, fromSet, fromCalendar.getAlias(), toSet, toCalendar.getAlias(), forward); } else { logln((UnicodeString)"#"+n+" "+locale+"/"+from+" <<< "+toCalLoc+"/" +to); - testConvert(n, toSet, toCalendar, fromSet, fromCalendar, forward); + testConvert(n, toSet, toCalendar.getAlias(), fromSet, fromCalendar.getAlias(), forward); } - - delete fromCalendar; } - delete toCalendar; } void DataDrivenCalendarTest::processTest(TestData *testData) { diff -Nru icu-64.2/source/test/intltest/datadrivennumberformattestsuite.cpp icu-65.1/source/test/intltest/datadrivennumberformattestsuite.cpp --- icu-64.2/source/test/intltest/datadrivennumberformattestsuite.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/datadrivennumberformattestsuite.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -38,7 +38,7 @@ } UnicodeString columnValues[kNumberFormatTestTupleFieldCount]; ENumberFormatTestTupleField columnTypes[kNumberFormatTestTupleFieldCount]; - int32_t columnCount; + int32_t columnCount = 0; int32_t state = 0; while(U_SUCCESS(status)) { // Read a new line if necessary. diff -Nru icu-64.2/source/test/intltest/dcfmapts.cpp icu-65.1/source/test/intltest/dcfmapts.cpp --- icu-64.2/source/test/intltest/dcfmapts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dcfmapts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -453,9 +453,10 @@ void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){ UErrorCode status = U_ZERO_ERROR; - CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status); + LocalPointercpi(new CurrencyPluralInfo(status), status); if(U_FAILURE(status)) { errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created"); + return; } CurrencyPluralInfo cpi1 = *cpi; @@ -479,19 +480,18 @@ errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); } - DecimalFormat *df = new DecimalFormat(status); + LocalPointerdf(new DecimalFormat(status)); if(U_FAILURE(status)) { errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status)); return; } - df->adoptCurrencyPluralInfo(cpi); + df->adoptCurrencyPluralInfo(cpi.orphan()); df->getCurrencyPluralInfo(); df->setCurrencyPluralInfo(cpi1); - delete df; } void IntlTestDecimalFormatAPI::testRounding(/*char *par*/) @@ -642,14 +642,15 @@ } -#define ASSERT_EQUAL(expect, actual) { \ +#define ASSERT_EQUAL(expect, actual) UPRV_BLOCK_MACRO_BEGIN { \ /* ICU-20080: Use temporary variables to avoid strange compiler behaviour \ (with the nice side-effect of avoiding repeated function calls too). */ \ auto lhs = (expect); \ auto rhs = (actual); \ char tmp[200]; \ sprintf(tmp, "(%g==%g)", (double)lhs, (double)rhs); \ - assertTrue(tmp, (lhs==rhs), FALSE, TRUE, __FILE__, __LINE__); } + assertTrue(tmp, (lhs==rhs), FALSE, TRUE, __FILE__, __LINE__); \ +} UPRV_BLOCK_MACRO_END #if defined(_MSC_VER) // Ignore the noisy warning 4805 (comparisons between int and bool) in the function below as we use the ICU TRUE/FALSE macros diff -Nru icu-64.2/source/test/intltest/dcfmtest.cpp icu-65.1/source/test/intltest/dcfmtest.cpp --- icu-64.2/source/test/intltest/dcfmtest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dcfmtest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -79,21 +79,41 @@ // Error Checking / Reporting macros used in all of the tests. // //--------------------------------------------------------------------------- -#define DF_CHECK_STATUS {if (U_FAILURE(status)) \ - {dataerrln("DecimalFormatTest failure at line %d. status=%s", \ - __LINE__, u_errorName(status)); return 0;}} - -#define DF_ASSERT(expr) {if ((expr)==FALSE) {errln("DecimalFormatTest failure at line %d.\n", __LINE__);};} - -#define DF_ASSERT_FAIL(expr, errcode) {UErrorCode status=U_ZERO_ERROR; (expr);\ -if (status!=errcode) {dataerrln("DecimalFormatTest failure at line %d. Expected status=%s, got %s", \ - __LINE__, u_errorName(errcode), u_errorName(status));};} - -#define DF_CHECK_STATUS_L(line) {if (U_FAILURE(status)) {errln( \ - "DecimalFormatTest failure at line %d, from %d. status=%d\n",__LINE__, (line), status); }} - -#define DF_ASSERT_L(expr, line) {if ((expr)==FALSE) { \ - errln("DecimalFormatTest failure at line %d, from %d.", __LINE__, (line)); return;}} +#define DF_CHECK_STATUS UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + dataerrln("DecimalFormatTest failure at line %d. status=%s", \ + __LINE__, u_errorName(status)); \ + return 0; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define DF_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("DecimalFormatTest failure at line %d.\n", __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define DF_ASSERT_FAIL(expr, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + UErrorCode status=U_ZERO_ERROR; \ + (expr); \ + if (status!=errcode) { \ + dataerrln("DecimalFormatTest failure at line %d. Expected status=%s, got %s", \ + __LINE__, u_errorName(errcode), u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define DF_CHECK_STATUS_L(line) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + errln("DecimalFormatTest failure at line %d, from %d. status=%d\n",__LINE__, (line), status); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define DF_ASSERT_L(expr, line) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("DecimalFormatTest failure at line %d, from %d.", __LINE__, (line)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END @@ -106,7 +126,7 @@ class InvariantStringPiece: public StringPiece { public: InvariantStringPiece(const UnicodeString &s); - ~InvariantStringPiece() {}; + ~InvariantStringPiece() {} private: MaybeStackArray buf; }; @@ -130,7 +150,7 @@ class UnicodeStringPiece: public StringPiece { public: UnicodeStringPiece(const UnicodeString &s); - ~UnicodeStringPiece() {}; + ~UnicodeStringPiece() {} private: MaybeStackArray buf; }; @@ -546,7 +566,7 @@ errln("ICU Error \"%s\"\n", u_errorName(status)); delete retPtr; retPtr = NULL; - }; + } return retPtr; } diff -Nru icu-64.2/source/test/intltest/dtfmapts.cpp icu-65.1/source/test/intltest/dtfmapts.cpp --- icu-64.2/source/test/intltest/dtfmapts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtfmapts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -235,7 +235,7 @@ } const NumberFormat *nf = def->getNumberFormat(); - NumberFormat *newNf = (NumberFormat*) nf->clone(); + NumberFormat *newNf = nf->clone(); de->adoptNumberFormat(newNf); it->setNumberFormat(*newNf); if( *(de->getNumberFormat()) != *(it->getNumberFormat())) { diff -Nru icu-64.2/source/test/intltest/dtfmrgts.cpp icu-65.1/source/test/intltest/dtfmrgts.cpp --- icu-64.2/source/test/intltest/dtfmrgts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtfmrgts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -290,23 +290,17 @@ { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *fmt; UnicodeString myDate; - fmt = new SimpleDateFormat( UnicodeString("yyyy/MM/dd"), status ); + SimpleDateFormat fmt(UnicodeString(u"yyyy/MM/dd"), status ); if (failure(status, "new SimpleDateFormat", TRUE)) return; myDate = "1997/01/01"; - aux917( fmt, myDate ); - - delete fmt; - fmt = NULL; - - fmt = new SimpleDateFormat( UnicodeString("yyyyMMdd"), status ); + aux917( &fmt, myDate ); + + SimpleDateFormat fmt2( UnicodeString(u"yyyyMMdd"), status ); if(failure(status, "new SimpleDateFormat")) return; myDate = "19970101"; - aux917( fmt, myDate ); - - delete fmt; + aux917(&fmt2, myDate ); } void DateFormatRegressionTest::aux917( SimpleDateFormat *fmt, UnicodeString& str ) { @@ -349,23 +343,22 @@ logln( "dateString= " + dateString ); logln("Using yyyy-DDD.hh:mm:ss"); UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *formatter = new SimpleDateFormat(UnicodeString("yyyy-DDD.hh:mm:ss"), status); + SimpleDateFormat formatter(UnicodeString("yyyy-DDD.hh:mm:ss"), status); if (failure(status, "new SimpleDateFormat", TRUE)) return; ParsePosition pos(0); - UDate myDate = formatter->parse( dateString, pos ); + UDate myDate = formatter.parse( dateString, pos ); UnicodeString myString; - DateFormat *fmt = DateFormat::createDateTimeInstance( DateFormat::FULL, - DateFormat::LONG); - if (fmt == NULL) { + LocalPointer fmt(DateFormat::createDateTimeInstance( DateFormat::FULL, + DateFormat::LONG)); + if (!fmt.isValid()) { dataerrln("Error calling DateFormat::createDateTimeInstance"); - delete formatter; return; } myString = fmt->format( myDate, myString); logln( myString ); - Calendar *cal = new GregorianCalendar(status); + LocalPointer cal(new GregorianCalendar(status)); failure(status, "new GregorianCalendar"); cal->setTime(myDate, status); failure(status, "cal->setTime"); @@ -376,12 +369,10 @@ // this is an odd usage of "ddd" and it doesn't // work now that date values are range checked per #3579. logln("Using yyyy-ddd.hh:mm:ss"); - delete formatter; - formatter = NULL; - formatter = new SimpleDateFormat(UnicodeString("yyyy-ddd.hh:mm:ss"), status); + SimpleDateFormat formatter2(UnicodeString(u"yyyy-ddd.hh:mm:ss"), status); if(failure(status, "new SimpleDateFormat")) return; pos.setIndex(0); - myDate = formatter->parse( dateString, pos ); + myDate = formatter2.parse( dateString, pos ); myString = fmt->format( myDate, myString ); logln( myString ); cal->setTime(myDate, status); @@ -389,10 +380,6 @@ if ((cal->get(UCAL_DAY_OF_YEAR, status) != 40) || failure(status, "cal->get")) errln((UnicodeString) "Fail: Got " + cal->get(UCAL_DAY_OF_YEAR, status) + " Want 40"); - - delete formatter; - delete fmt; - delete cal; } /** @@ -719,22 +706,20 @@ void DateFormatRegressionTest::Test4101483(void) { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString("z"), Locale::getUS(), status); + SimpleDateFormat sdf(UnicodeString("z"), Locale::getUS(), status); if (failure(status, "new SimpleDateFormat", TRUE)) return; FieldPosition fp(UDAT_TIMEZONE_FIELD); //Date d = date(9234567890L); UDate d = 9234567890.0; //StringBuffer buf = new StringBuffer(""); UnicodeString buf; - sdf->format(d, buf, fp); + sdf.format(d, buf, fp); //logln(sdf.format(d, buf, fp).toString()); logln(dateToString(d) + " => " + buf); logln(UnicodeString("beginIndex = ") + fp.getBeginIndex()); logln(UnicodeString("endIndex = ") + fp.getEndIndex()); if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field"); - - delete sdf; } /** @@ -752,22 +737,20 @@ // choose a date that is the FIRST of some month // and some arbitrary time UDate d = date(97, 3, 1, 1, 1, 1); - SimpleDateFormat *df = new SimpleDateFormat(UnicodeString("MMMM"), Locale::getUS(), status); + SimpleDateFormat df(UnicodeString(u"MMMM"), Locale::getUS(), status); if (failure(status, "new SimpleDateFormat", TRUE)) return; UnicodeString s; s = dateToString(d, s); UnicodeString s2; FieldPosition pos(FieldPosition::DONT_CARE); - s2 = df->format(d, s2, pos); + s2 = df.format(d, s2, pos); logln("Date=" + s); logln("DF=" + s2); UnicodeString substr; s2.extract(0,2, substr); if (s.indexOf(substr) == -1) - errln("Months should match"); - - delete df; + errln("Months should match"); } /** @@ -775,29 +758,23 @@ */ void DateFormatRegressionTest::Test4103341(void) { - TimeZone *saveZone =TimeZone::createDefault(); - //try { - + LocalPointer saveZone(TimeZone::createDefault()); + if (!saveZone.isValid()) { + dataerrln("TimeZone::createDefault() failed."); + return; + } // {sfb} changed from setDefault to adoptDefault TimeZone::adoptDefault(TimeZone::createTimeZone("CST")); UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *simple = new SimpleDateFormat(UnicodeString("MM/dd/yyyy HH:mm"), status); + SimpleDateFormat simple(UnicodeString("MM/dd/yyyy HH:mm"), status); if(U_FAILURE(status)) { - dataerrln("Couldn't create SimpleDateFormat, error %s", u_errorName(status)); - delete simple; - return; - } - failure(status, "new SimpleDateFormat"); - TimeZone *temp = TimeZone::createDefault(); - if(simple->getTimeZone() != *temp) + dataerrln("Couldn't create SimpleDateFormat, error %s", u_errorName(status)); + } else { + LocalPointer temp(TimeZone::createDefault()); + if(simple.getTimeZone() != *temp) errln("Fail: SimpleDateFormat not using default zone"); - //} - //finally { - TimeZone::adoptDefault(saveZone); - //} - - delete temp; - delete simple; + } + TimeZone::adoptDefault(saveZone.orphan()); } /** @@ -1018,17 +995,15 @@ { UErrorCode status = U_ZERO_ERROR; UnicodeString dateFormat = "MM/dd/yy HH:mm:ss zzz"; - SimpleDateFormat *fmt = new SimpleDateFormat(dateFormat, status); + SimpleDateFormat fmt (dateFormat, status); if (failure(status, "new SimpleDateFormat", TRUE)) return; ParsePosition p0(0); - UDate d = fmt->parse("01/22/92 04:52:00 GMT", p0); + UDate d = fmt.parse("01/22/92 04:52:00 GMT", p0); logln(dateToString(d)); if(p0 == ParsePosition(0)) errln("Fail: failed to parse 'GMT'"); // In the failure case an exception is thrown by parse(); // if no exception is thrown, the test passes. - - delete fmt; } /** @@ -1040,19 +1015,17 @@ UnicodeString pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'"; logln("pattern=" + pattern); UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *format = new SimpleDateFormat(pattern, Locale::getUS(), status); + SimpleDateFormat format(pattern, Locale::getUS(), status); if (failure(status, "new SimpleDateFormat", TRUE)) return; UnicodeString result; FieldPosition pos(FieldPosition::DONT_CARE); - result = format->format(date(1998-1900, UCAL_JUNE, 30, 13, 30, 0), result, pos); + result = format.format(date(1998-1900, UCAL_JUNE, 30, 13, 30, 0), result, pos); if (result != "TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')") { errln("Fail: result=" + result); } else { logln("Pass: result=" + result); } - - delete format; } /** @@ -1461,7 +1434,7 @@ if (U_FAILURE(status)) { errln("Error getting time to format"); return; - }; + } sdf->adoptCalendar(cal); UnicodeString result; UnicodeString correct("-0330", ""); diff -Nru icu-64.2/source/test/intltest/dtfmttst.cpp icu-65.1/source/test/intltest/dtfmttst.cpp --- icu-64.2/source/test/intltest/dtfmttst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtfmttst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -29,7 +29,12 @@ #include "windttst.h" #endif -#define ASSERT_OK(status) if(U_FAILURE(status)) {errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); return; } +#define ASSERT_OK(status) UPRV_BLOCK_MACRO_BEGIN { \ + if(U_FAILURE(status)) { \ + errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END // ***************************************************************************** // class DateFormatTest @@ -122,6 +127,7 @@ TESTCASE_AUTO(TestMinuteSecondFieldsInOddPlaces); TESTCASE_AUTO(TestDayPeriodParsing); TESTCASE_AUTO(TestParseRegression13744); + TESTCASE_AUTO(TestAdoptCalendarLeak); TESTCASE_AUTO_END; } @@ -377,12 +383,12 @@ DateFormatTest::TestTwoDigitYearDSTParse(void) { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat* fullFmt = new SimpleDateFormat((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status); - SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status); + SimpleDateFormat fullFmt((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status); + SimpleDateFormat fmt((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status); //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH); - UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", ""); - TimeZone* defaultTZ = TimeZone::createDefault(); - TimeZone* PST = TimeZone::createTimeZone("PST"); + UnicodeString s(u"03-Apr-04 2:20:47 o'clock AM PST"); + LocalPointer defaultTZ(TimeZone::createDefault()); + LocalPointer PST(TimeZone::createTimeZone("PST")); int32_t defaultOffset = defaultTZ->getRawOffset(); int32_t PSTOffset = PST->getRawOffset(); int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000); @@ -396,8 +402,8 @@ return; } - UDate d = fmt->parse(*s, status); - logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str)); + UDate d = fmt.parse(s, status); + logln(s + " P> " + fullFmt.format(d, str)); int32_t y, m, day, hr, min, sec; dateToFields(d, y, m, day, hr, min, sec); hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0; @@ -407,12 +413,6 @@ if (U_FAILURE(status)) errln((UnicodeString)"FAIL: " + (int32_t)status); - - delete s; - delete fmt; - delete fullFmt; - delete PST; - delete defaultTZ; } // ------------------------------------- @@ -1290,18 +1290,17 @@ int32_t DATA_length = UPRV_LENGTHOF(DATA); for (int32_t i=0; isetCalendar(*greenwichcalendar); + fmt.setCalendar(*greenwichcalendar); UnicodeString result; - result = fmt->format(greenwichdate, result); + result = fmt.format(greenwichdate, result); logln(DATA[i] + result); if (result != DATA[i+1]) errln("FAIL: Expected " + DATA[i+1] + ", got " + result); - delete fmt; } } //} @@ -3406,7 +3405,7 @@ }; UErrorCode status = U_ZERO_ERROR; - Calendar *cal = GregorianCalendar::createInstance(status); + LocalPointer cal(GregorianCalendar::createInstance(status)); if (failure(status, "GregorianCalendar::createInstance", TRUE)) return; SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status); if (failure(status, "SimpleDateFormat constructor", TRUE)) return; @@ -3434,13 +3433,12 @@ cal->adoptTimeZone(tz); UnicodeString result; FieldPosition pos(FieldPosition::DONT_CARE); - fmt.format(*cal,result,pos); + fmt.format(*cal.getAlias(), result,pos); if (result != info[4]) { errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" + info[4] + "' but got: '" + result + "'"); } } - delete cal; } void DateFormatTest::TestRoundtripWithCalendar(void) { @@ -3590,98 +3588,94 @@ { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("ar"), status); + SimpleDateFormat fmt1(UnicodeString(u"y-M-d"), Locale("ar"), status); if (failure(status, "new SimpleDateFormat", TRUE)) return; UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00); UnicodeString str1; - str1 = fmt1->format(dt1, str1); + str1 = fmt1.format(dt1, str1); logln(str1); - UDate dt11 = fmt1->parse(str1, status); + UDate dt11 = fmt1.parse(str1, status); failure(status, "fmt->parse"); UnicodeString str11; - str11 = fmt1->format(dt11, str11); + str11 = fmt1.format(dt11, str11); logln(str11); if (str1 != str11) { errln((UnicodeString)"FAIL: Different dates str1:" + str1 + " str2:" + str11); } - delete fmt1; ///////////////// status = U_ZERO_ERROR; - SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("y M d"), Locale("ar"), status); + SimpleDateFormat fmt2(UnicodeString(u"y M d"), Locale("ar"), status); failure(status, "new SimpleDateFormat"); UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00); UnicodeString str2; - str2 = fmt2->format(dt2, str2); + str2 = fmt2.format(dt2, str2); logln(str2); - UDate dt22 = fmt2->parse(str2, status); + UDate dt22 = fmt2.parse(str2, status); failure(status, "fmt->parse"); UnicodeString str22; - str22 = fmt2->format(dt22, str22); + str22 = fmt2.format(dt22, str22); logln(str22); if (str2 != str22) { errln((UnicodeString)"FAIL: Different dates str1:" + str2 + " str2:" + str22); } - delete fmt2; ///////////////// status = U_ZERO_ERROR; - SimpleDateFormat *fmt3 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("en-us"), status); + SimpleDateFormat fmt3(UnicodeString("y-M-d"), Locale("en-us"), status); failure(status, "new SimpleDateFormat"); UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00); UnicodeString str3; - str3 = fmt3->format(dt3, str3); + str3 = fmt3.format(dt3, str3); logln(str3); - UDate dt33 = fmt3->parse(str3, status); + UDate dt33 = fmt3.parse(str3, status); failure(status, "fmt->parse"); UnicodeString str33; - str33 = fmt3->format(dt33, str33); + str33 = fmt3.format(dt33, str33); logln(str33); if (str3 != str33) { errln((UnicodeString)"FAIL: Different dates str1:" + str3 + " str2:" + str33); } - delete fmt3; ///////////////// status = U_ZERO_ERROR; - SimpleDateFormat *fmt4 = new SimpleDateFormat(UnicodeString("y M d"), Locale("en-us"), status); + SimpleDateFormat fmt4(UnicodeString("y M d"), Locale("en-us"), status); failure(status, "new SimpleDateFormat"); UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00); UnicodeString str4; - str4 = fmt4->format(dt4, str4); + str4 = fmt4.format(dt4, str4); logln(str4); - UDate dt44 = fmt4->parse(str4, status); + UDate dt44 = fmt4.parse(str4, status); failure(status, "fmt->parse"); UnicodeString str44; - str44 = fmt4->format(dt44, str44); + str44 = fmt4.format(dt44, str44); logln(str44); if (str4 != str44) { errln((UnicodeString)"FAIL: Different dates str1:" + str4 + " str2:" + str44); } - delete fmt4; } @@ -3857,15 +3851,15 @@ for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) { Locale locale = Locale::createFromName(itemPtr->localeStr); UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *formatter = new SimpleDateFormat(itemPtr->datePattern, locale, status); - if (formatter == NULL || U_FAILURE(status)) { + SimpleDateFormat formatter(itemPtr->datePattern, locale, status); + if (U_FAILURE(status)) { dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status)); return; } - formatter->setLenient(itemPtr->lenient); - formatter->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status); - UDate date1 = formatter->parse(itemPtr->dateString, status); + formatter.setLenient(itemPtr->lenient); + formatter.setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status); + UDate date1 = formatter.parse(itemPtr->dateString, status); if (U_FAILURE(status)) { if (!itemPtr->expectFail) { errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient + @@ -3876,14 +3870,12 @@ ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." ); } else if (!itemPtr->lenient) { UnicodeString formatted; - formatter->format(date1, formatted); + formatter.format(date1, formatted); if (formatted != itemPtr->dateString) { errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient + ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\"."); } } - - delete formatter; } } @@ -3935,20 +3927,19 @@ void DateFormatTest::TestFormalChineseDate() { UErrorCode status = U_ZERO_ERROR; - UnicodeString pattern ("y\\u5e74M\\u6708d\\u65e5", -1, US_INV ); - pattern = pattern.unescape(); - UnicodeString override ("y=hanidec;M=hans;d=hans", -1, US_INV ); + UnicodeString pattern(u"y\u5e74M\u6708d\u65e5"); + UnicodeString numsys_override(u"y=hanidec;M=hans;d=hans"); // create formatter - SimpleDateFormat *sdf = new SimpleDateFormat(pattern,override,Locale::getChina(),status); - if (failure(status, "new SimpleDateFormat with override", TRUE)) { + SimpleDateFormat sdf(pattern, numsys_override, Locale::getChina(),status); + if (failure(status, "new SimpleDateFormat with override", true)) { return; } UDate thedate = date(2009-1900, UCAL_JULY, 28); FieldPosition pos(FieldPosition::DONT_CARE); UnicodeString result; - sdf->format(thedate,result,pos); + sdf.format(thedate,result,pos); UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5"; expected = expected.unescape(); @@ -3956,37 +3947,34 @@ dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected); } - UDate parsedate = sdf->parse(expected,status); + UDate parsedate = sdf.parse(expected,status); if ( parsedate != thedate ) { UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV ); - SimpleDateFormat *usf = new SimpleDateFormat(pat1,Locale::getEnglish(),status); + SimpleDateFormat usf(pat1, Locale::getEnglish(), status); UnicodeString parsedres,expres; - usf->format(parsedate,parsedres,pos); - usf->format(thedate,expres,pos); + usf.format(parsedate,parsedres,pos); + usf.format(thedate,expres,pos); dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres); - delete usf; } - delete sdf; } // Test case for #8675 // Incorrect parse offset with stand alone GMT string on 2nd or later iteration. void DateFormatTest::TestStandAloneGMTParse() { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status); + SimpleDateFormat sdf("ZZZZ", Locale(""), status); if (U_SUCCESS(status)) { - UnicodeString inText("GMT$$$"); + UnicodeString inText(u"GMT$$$"); for (int32_t i = 0; i < 10; i++) { ParsePosition pos(0); - sdf->parse(inText, pos); + sdf.parse(inText, pos); if (pos.getIndex() != 3) { errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3"); } } - delete sdf; } else { dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status)); } @@ -4011,7 +3999,7 @@ for (int32_t i = 0; TestData[i][0]; i++) { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString(TestData[i][0]), status); + SimpleDateFormat sdf(UnicodeString(TestData[i][0]), status); if (failure(status, "new SimpleDateFormat", TRUE)) return; int32_t startPos, resPos; @@ -4029,14 +4017,12 @@ ParsePosition pos(startPos); //UDate d = sdf->parse(input, pos); - (void)sdf->parse(input, pos); + (void)sdf.parse(input, pos); if (pos.getIndex() != resPos) { errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - " + pos.getIndex() + ", expected - " + resPos); } - - delete sdf; } } @@ -4308,20 +4294,20 @@ const TestNonGregoItem * itemPtr; for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) { Locale locale = Locale::createFromName(itemPtr->locale); - DateFormat * dfmt = NULL; + LocalPointer dfmt; UErrorCode status = U_ZERO_ERROR; if (itemPtr->style != DateFormat::kNone) { - dfmt = DateFormat::createDateInstance(itemPtr->style, locale); + dfmt.adoptInstead(DateFormat::createDateInstance(itemPtr->style, locale)); } else { - dfmt = new SimpleDateFormat(itemPtr->pattern, locale, status); + dfmt.adoptInstead(new SimpleDateFormat(itemPtr->pattern, locale, status)); } if (U_FAILURE(status)) { dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale); - } else if (dfmt == NULL) { + } else if (!dfmt.isValid()) { dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale); } else { - Calendar * cal = (dfmt->getCalendar())->clone(); - if (cal == NULL) { + LocalPointercal((dfmt->getCalendar())->clone()); + if (!cal.isValid()) { dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale); } else { const CalAndFmtTestItem * caftItemPtr; @@ -4357,9 +4343,7 @@ } } } - delete cal; } - delete dfmt; } } } @@ -4789,7 +4773,7 @@ FieldPosition pos(FieldPosition::DONT_CARE); fmt->format(test_date,result, pos); - UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();; + UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape(); if (result != expected) errln("FAIL: Expected " + expected + " get: " + result); @@ -5247,7 +5231,7 @@ sdf.setTimeZone(*tz); sdf.applyPattern(UnicodeString("hh:mm:ss BBBB")); - assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", UnicodeString("01:00:00 a.\\u00A0m.").unescape(), + assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", u"01:00:00 de la mañana", sdf.format(k010000, out.remove())); sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode); @@ -5557,6 +5541,20 @@ assertEquals("Error index", inDate.length(), pos.getErrorIndex()); } +void DateFormatTest::TestAdoptCalendarLeak() { + UErrorCode status = U_ZERO_ERROR; + // This test relies on the locale fullName exceeding ULOC_FULLNAME_CAPACITY + // in order for setKeywordValue to fail. + SimpleDateFormat sdf( + "d.M.y", + Locale("de__POSIX@colstrength=primary;currency=eur;em=default;" + "hours=h23;lb=strict;lw=normal;measure=metric;numbers=latn;" + "rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna"), + status); + ASSERT_OK(status); + sdf.adoptCalendar(Calendar::createInstance(status)); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ //eof diff -Nru icu-64.2/source/test/intltest/dtfmttst.h icu-65.1/source/test/intltest/dtfmttst.h --- icu-64.2/source/test/intltest/dtfmttst.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtfmttst.h 2019-10-03 11:16:41.000000000 +0000 @@ -262,6 +262,7 @@ void TestMinuteSecondFieldsInOddPlaces(); void TestDayPeriodParsing(); void TestParseRegression13744(); + void TestAdoptCalendarLeak(); private: UBool showParse(DateFormat &format, const UnicodeString &formattedString); diff -Nru icu-64.2/source/test/intltest/dtifmtts.cpp icu-65.1/source/test/intltest/dtifmtts.cpp --- icu-64.2/source/test/intltest/dtifmtts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtifmtts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -132,7 +132,7 @@ status = U_ZERO_ERROR; logln("Testing DateIntervalFormat clone"); - DateIntervalFormat* another = (DateIntervalFormat*)dtitvfmt->clone(); + DateIntervalFormat* another = dtitvfmt->clone(); if ( (*another) != (*dtitvfmt) ) { dataerrln("%s:%d ERROR: clone failed", __FILE__, __LINE__); } @@ -224,7 +224,7 @@ } status = U_ZERO_ERROR; - DateFormat* nonConstFmt = (DateFormat*)fmt->clone(); + DateFormat* nonConstFmt = fmt->clone(); dtitvfmt->adoptDateFormat(nonConstFmt, status); anotherFmt = dtitvfmt->getDateFormat(); if ( (*fmt) != (*anotherFmt) || U_FAILURE(status) ) { @@ -250,7 +250,7 @@ logln("Testing DateIntervalFormat constructor and assigment operator"); status = U_ZERO_ERROR; - DateFormat* constFmt = (constFmt*)dtitvfmt->getDateFormat()->clone(); + DateFormat* constFmt = dtitvfmt->getDateFormat()->clone(); inf = dtitvfmt->getDateIntervalInfo()->clone(); @@ -1483,7 +1483,7 @@ GregorianCalendar* gregCal = new GregorianCalendar(loc, ec); if (!assertSuccess("GregorianCalendar()", ec)) return; const DateFormat* dformat = dtitvfmt->getDateFormat(); - DateFormat* newOne = (DateFormat*)dformat->clone(); + DateFormat* newOne = dformat->clone(); newOne->adoptCalendar(gregCal); //dtitvfmt->adoptDateFormat(newOne, ec); dtitvfmt->setDateFormat(*newOne, ec); @@ -1640,7 +1640,7 @@ dataerrln("FAIL: DateIntervalFormat::createInstance failed for Locale::getEnglish()"); return; } - LocalPointer clone(dynamic_cast(formatter->clone())); + LocalPointer clone(formatter->clone()); if (*formatter != *clone) { errln("%s:%d DateIntervalFormat and clone are not equal.", __FILE__, __LINE__); return; @@ -1689,6 +1689,49 @@ UPRV_LENGTHOF(expectedFieldPositions)); } + { + const char16_t* message = u"FormattedDateInterval identical dates test: no span field"; + const char16_t* expectedString = u"July 20, 2018"; + LocalPointer input1(Calendar::createInstance("en-GB", status)); + input1->set(2018, 6, 20); + FormattedDateInterval result = fmt->formatToValue(*input1, *input1, status); + static const UFieldPositionWithCategory expectedFieldPositions[] = { + // field, begin index, end index + {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4}, + {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7}, + {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 9, 13}}; + checkMixedFormattedValue( + message, + result, + expectedString, + expectedFieldPositions, + UPRV_LENGTHOF(expectedFieldPositions)); + } + + // Test sample code + { + LocalPointer input1(Calendar::createInstance("en-GB", status)); + LocalPointer input2(Calendar::createInstance("en-GB", status)); + input1->set(2018, 6, 20); + input2->set(2018, 7, 3); + + // Let fmt be a DateIntervalFormat for locale en-US and skeleton dMMMMy + // Let input1 be July 20, 2018 and input2 be August 3, 2018: + FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status); + assertEquals("Expected output from format", + u"July 20 \u2013 August 3, 2018", result.toString(status)); + ConstrainedFieldPosition cfpos; + cfpos.constrainField(UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0); + if (result.nextPosition(cfpos, status)) { + assertEquals("Expect start index", 0, cfpos.getStart()); + assertEquals("Expect end index", 7, cfpos.getLimit()); + } else { + // No such span: can happen if input dates are equal. + } + assertFalse("No more than one occurrence of the field", + result.nextPosition(cfpos, status)); + } + // To test the fallback pattern behavior, make a custom DateIntervalInfo. DateIntervalInfo dtitvinf(status); dtitvinf.setFallbackIntervalPattern("<< {1} --- {0} >>", status); diff -Nru icu-64.2/source/test/intltest/dtptngts.cpp icu-65.1/source/test/intltest/dtptngts.cpp --- icu-64.2/source/test/intltest/dtptngts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtptngts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -41,11 +41,13 @@ TESTCASE(5, testSkeletonsWithDayPeriods); TESTCASE(6, testGetFieldDisplayNames); TESTCASE(7, testJjMapping); + TESTCASE(8, test20640_HourCyclArsEnNH); + TESTCASE(9, testFallbackWithDefaultRootLocale); default: name = ""; break; } } -#define MAX_LOCALE 11 +#define MAX_LOCALE 12 /** * Test various generic API methods of DateTimePatternGenerator for API coverage. @@ -84,11 +86,12 @@ {"zh", "Hans", "CN", ""}, // 7 {"zh", "TW", "", "calendar=roc"}, // 8 {"ru", "", "", ""}, // 9 - {"zh", "", "", "calendar=chinese"}, // 10 + {"zh", "", "", "calendar=chinese"}, // 10 + {"ja", "JP", "TRADITIONAL", ""}, // 11 }; // For Weds, Jan 13, 1999, 23:58:59 - UnicodeString patternResults[] = { + UnicodeString patternResults_en_US[] = { // en_US // 0 en_US UnicodeString("1/1999"), // 00: yM UnicodeString("Jan 1999"), // 01: yMMM @@ -107,7 +110,9 @@ UnicodeString("13 Wed"), // 14: Ed -> d EEE UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a" UnicodeString("11:58"), // 16: JJmm + }; + UnicodeString patternResults_en_US_japanese[] = { // en_US@calendar=japanese // 1 en_US@calendar=japanese UnicodeString("1/11 H"), // 0: yM UnicodeString("Jan 11 Heisei"), // 1: yMMM @@ -126,7 +131,9 @@ UnicodeString("13 Wed"), // 14: Ed -> d EEE UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a" UnicodeString("11:58"), // 16: JJmm + }; + UnicodeString patternResults_de_DE[] = { // de_DE // 2 de_DE UnicodeString("1.1999"), // 00: yM UnicodeString("Jan. 1999"), // 01: yMMM @@ -145,7 +152,9 @@ UnicodeString("Mi., 13."), // 14: Ed -> EEE d. UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "HH:mm:ss,SSS" UnicodeString("23:58"), // 16: JJmm + }; + UnicodeString patternResults_fi[] = { // fi // 3 fi UnicodeString("1.1999"), // 00: yM (fixed expected result per ticket:6626:) UnicodeString("tammi 1999"), // 01: yMMM @@ -164,7 +173,9 @@ UnicodeString("ke 13."), // 14: Ed -> ccc d. UnicodeString("23.58.59,123"), // 15: jmmssSSS -> "H.mm.ss,SSS" UnicodeString("23.58"), // 16: JJmm + }; + UnicodeString patternResults_es[] = { // es // 4 es UnicodeString("1/1999"), // 00: yM -> "M/y" UnicodeString("ene. 1999"), // 01: yMMM -> "MMM y" @@ -183,7 +194,9 @@ CharsToUnicodeString("mi\\u00E9. 13"), // 14: Ed -> "EEE d" UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS" UnicodeString("23:58"), // 16: JJmm + }; + UnicodeString patternResults_ja[] = { // ja // 5 ja UnicodeString("1999/1"), // 00: yM -> y/M CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> y\u5E74M\u6708 @@ -202,7 +215,9 @@ CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(EEE) UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS" UnicodeString("23:58"), // 16: JJmm + }; + UnicodeString patternResults_ja_japanese[] = { // ja@calendar=japanese // 6 ja@calendar=japanese UnicodeString("H11/1"), // 00: yM -> GGGGGy/m CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708 @@ -221,7 +236,9 @@ CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(EEE) UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS" UnicodeString("23:58"), // 16: JJmm + }; + UnicodeString patternResults_zh_Hans_CN[] = { // zh_Hans_CN // 7 zh_Hans_CN CharsToUnicodeString("1999\\u5E741\\u6708"), // 00: yM -> y\u5E74M\u6708 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> yyyy\u5E74MMM (fixed expected result per ticket:6626:) @@ -240,7 +257,9 @@ CharsToUnicodeString("13\\u65E5\\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS" UnicodeString("11:58"), // 16: JJmm + }; + UnicodeString patternResults_zh_TW_roc[] = { // zh_TW@calendar=roc // 8 zh_TW@calendar=roc CharsToUnicodeString("\\u6C11\\u570B88/1"), // 00: yM -> Gy/M CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708 @@ -259,7 +278,9 @@ CharsToUnicodeString("13 \\u9031\\u4E09"), // 14: Ed -> d E CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS" UnicodeString("11:58"), // 16: JJmm + }; + UnicodeString patternResults_ru[] = { // ru // 9 ru UnicodeString("01.1999"), // 00: yM -> MM.y CharsToUnicodeString("\\u044F\\u043D\\u0432. 1999 \\u0433."), // 01: yMMM -> LLL y @@ -278,7 +299,9 @@ CharsToUnicodeString("\\u0441\\u0440, 13"), // 14: Ed -> EEE, d UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS" UnicodeString("23:58"), // 16: JJmm + }; + UnicodeString patternResults_zh_chinese[] = { // zh@calendar=chinese // 10 zh@calendar=chinese CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 00: yMMM CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 01: yMMM @@ -297,8 +320,42 @@ CharsToUnicodeString("26\\u65E5\\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSS UnicodeString("11:58"), // 16: JJmm + }; - UnicodeString(), + UnicodeString patternResults_ja_jp_traditional[] = { + // ja_JP_TRADITIONAL // 11 ja_JP_TRADITIONAL + u"AD1999/1", // 00: yM + u"西暦1999年1月", // 01: yMMM + u"1999年1月13日", // 02: yMd + u"西暦1999年1月13日", // 03: yMMMd + u"1/13", // 04: Md + u"1月13日", // 05: MMMd + u"1月13日", // 06: MMMMd + u"西暦1999/Q1", // 07: yQQQ + u"午後11:58", // 08: hhmm + u"23:58", // 09: HHmm + u"23:58", // 10: jjmm + u"58:59", // 11: mmss + u"西暦1999年1月", // 12: yyyyMMMM + u"1月13日(水)", // 13: MMMEd + u"13日(水)", // 14: Ed + u"23:58:59.123", // 15: jmmssSSS + u"23:58", // 16: JJmm + }; + + UnicodeString* patternResults[] = { + patternResults_en_US, // 0 + patternResults_en_US_japanese, // 1 + patternResults_de_DE, // 2 + patternResults_fi, // 3 + patternResults_es, // 4 + patternResults_ja, // 5 + patternResults_ja_japanese, // 6 + patternResults_zh_Hans_CN, // 7 + patternResults_zh_TW_roc, // 8 + patternResults_ru, // 9 + patternResults_zh_chinese, // 10 + patternResults_ja_jp_traditional, // 11 }; UnicodeString patternTests2[] = { @@ -634,6 +691,7 @@ UDate testDate= LocaleTest::date(99, 0, 13, 23, 58, 59) + 123.0; while (localeIndex < MAX_LOCALE ) { + resultIndex=0; int32_t dataIndex=0; UnicodeString bestPattern; @@ -652,9 +710,12 @@ SimpleDateFormat sdf(bestPattern, loc, status); resultDate.remove(); resultDate = sdf.format(testDate, resultDate); - if ( resultDate != patternResults[resultIndex] ) { + if ( resultDate != patternResults[localeIndex][resultIndex] ) { + auto* calendar = sdf.getCalendar(); errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex-1) + UnicodeString("], localeIndex ") + localeIndex + - UnicodeString(". Got: \"") + resultDate + UnicodeString("\" Expected: \"") + patternResults[resultIndex] + "\"" ); + u". Got: \"" + resultDate + + u"\" with calendar " + calendar->getType() + + u" Expected: \"" + patternResults[localeIndex][resultIndex] + u"\""); } resultIndex++; @@ -1328,12 +1389,13 @@ for (; *charPtr != (UChar)0; charPtr++) { if (jPatSkeleton.indexOf(*charPtr) >= 0) { if (shortPatSkeleton.indexOf(*charPtr) < 0) { - char jcBuf[2], spBuf[32]; + char jcBuf[2], spBuf[32], jpBuf[32]; u_austrncpy(jcBuf, charPtr, 1); jcBuf[1] = 0; shortPattern.extract(0, shortPattern.length(), spBuf, 32); + jPattern.extract(0, jPattern.length(), jpBuf, 32); const char* dfmtCalType = (dfmt->getCalendar())->getType(); - errln("ERROR: locale %s, expected j resolved char %s to occur in short time pattern %s for %s", localeID, jcBuf, spBuf, dfmtCalType); + errln("ERROR: locale %s, expected j resolved char %s to occur in short time pattern '%s' for %s (best pattern: '%s')", localeID, jcBuf, spBuf, dfmtCalType, jpBuf); } break; } @@ -1341,4 +1403,77 @@ } } +void IntlTestDateTimePatternGeneratorAPI::test20640_HourCyclArsEnNH() { + IcuTestErrorCode status(*this, "test20640_HourCyclArsEnNH"); + + const struct TestCase { + const char* localeName; + const char16_t* expectedDtpgPattern; + const char16_t* expectedTimePattern; + } cases[] = { + // ars is interesting because it does not have a region, but it aliases + // to ar_SA, which has a region. + {"ars", u"h a", u"h:mm a"}, + // en_NH is interesting because NH is a deprecated region code; + // formerly New Hebrides, now Vanuatu => VU => h. + {"en_NH", u"h a", u"h:mm a"}, + // ch_ZH is a typo (should be zh_CN), but we should fail gracefully. + // {"cn_ZH", u"HH", u"H:mm"}, // TODO(ICU-20653): Desired behavior + {"cn_ZH", u"HH", u"h:mm a"}, // Actual behavior + // a non-BCP47 locale without a country code should not fail + {"ja_TRADITIONAL", u"H時", u"H:mm"}, + }; + + for (auto& cas : cases) { + status.setScope(cas.localeName); + + Locale loc(cas.localeName); + LocalPointer dtf(DateFormat::createTimeInstance(DateFormat::kShort, loc), status); + LocalPointer dtpg(DateTimePatternGenerator::createInstance(loc, status)); + if (status.errIfFailureAndReset()) { + return; + } + + UnicodeString timePattern; + dynamic_cast(dtf.getAlias())->toPattern(timePattern); + UnicodeString dtpgPattern = dtpg->getBestPattern(u"j", status); + if (status.errIfFailureAndReset()) { + return; + } + + assertEquals(UnicodeString("dtpgPattern ") + cas.localeName, + cas.expectedDtpgPattern, dtpgPattern); + assertEquals(UnicodeString("timePattern ") + cas.localeName, + cas.expectedTimePattern, timePattern); + } + +} + +void IntlTestDateTimePatternGeneratorAPI::testFallbackWithDefaultRootLocale() { + UErrorCode status = U_ZERO_ERROR; + char original[ULOC_FULLNAME_CAPACITY]; + + uprv_strcpy(original, uloc_getDefault()); + uloc_setDefault("root", &status); + if (U_FAILURE(status)) { + errln("ERROR: Failed to change the default locale to root! Default is: %s\n", uloc_getDefault()); + } + + DateTimePatternGenerator* dtpg = icu::DateTimePatternGenerator::createInstance("abcdedf", status); + + if (U_FAILURE(status)) { + errln("ERROR: expected createInstance with invalid locale to succeed. Status: %s", u_errorName(status)); + } + if (status != U_USING_DEFAULT_WARNING) { + errln("ERROR: expected createInstance to return U_USING_DEFAULT_WARNING for invalid locale and default root locale. Status: %s", u_errorName(status)); + } + + delete dtpg; + + uloc_setDefault(original, &status); + if (U_FAILURE(status)) { + errln("ERROR: Failed to change the default locale back to %s\n", original); + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/dtptngts.h icu-65.1/source/test/intltest/dtptngts.h --- icu-64.2/source/test/intltest/dtptngts.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/dtptngts.h 2019-10-03 11:16:41.000000000 +0000 @@ -33,6 +33,8 @@ void testSkeletonsWithDayPeriods(); void testGetFieldDisplayNames(); void testJjMapping(); + void test20640_HourCyclArsEnNH(); + void testFallbackWithDefaultRootLocale(); }; #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/erarulestest.cpp icu-65.1/source/test/intltest/erarulestest.cpp --- icu-64.2/source/test/intltest/erarulestest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/erarulestest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -8,6 +8,7 @@ #include "unicode/calendar.h" #include "unicode/localpointer.h" #include "unicode/unistr.h" +#include "unicode/timezone.h" #include "erarules.h" #include "erarulestest.h" @@ -73,7 +74,7 @@ + calId); } - LocalPointer cal(Calendar::createInstance("en", status)); + LocalPointer cal(Calendar::createInstance(*TimeZone::getGMT(), "en", status)); if (U_FAILURE(status)) { errln("Failed to create a Calendar instance."); continue; diff -Nru icu-64.2/source/test/intltest/formatted_string_builder_test.cpp icu-65.1/source/test/intltest/formatted_string_builder_test.cpp --- icu-64.2/source/test/intltest/formatted_string_builder_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/intltest/formatted_string_builder_test.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,328 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/utf16.h" +#include "putilimp.h" +#include "intltest.h" +#include "formatted_string_builder.h" +#include "formattedval_impl.h" + + +class FormattedStringBuilderTest : public IntlTest { + public: + void testInsertAppendUnicodeString(); + void testSplice(); + void testInsertAppendCodePoint(); + void testCopy(); + void testFields(); + void testUnlimitedCapacity(); + void testCodePoints(); + + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0); + + private: + void assertEqualsImpl(const UnicodeString &a, const FormattedStringBuilder &b); +}; + +static const char16_t *EXAMPLE_STRINGS[] = { + u"", + u"xyz", + u"The quick brown fox jumps over the lazy dog", + u"😁", + u"mixed 😇 and ASCII", + u"with combining characters like 🇦🇧🇨🇩", + u"A very very very very very very very very very very long string to force heap"}; + +void FormattedStringBuilderTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *) { + if (exec) { + logln("TestSuite FormattedStringBuilderTest: "); + } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(testInsertAppendUnicodeString); + TESTCASE_AUTO(testSplice); + TESTCASE_AUTO(testInsertAppendCodePoint); + TESTCASE_AUTO(testCopy); + TESTCASE_AUTO(testFields); + TESTCASE_AUTO(testUnlimitedCapacity); + TESTCASE_AUTO(testCodePoints); + TESTCASE_AUTO_END; +} + +void FormattedStringBuilderTest::testInsertAppendUnicodeString() { + UErrorCode status = U_ZERO_ERROR; + UnicodeString sb1; + FormattedStringBuilder sb2; + for (const char16_t* strPtr : EXAMPLE_STRINGS) { + UnicodeString str(strPtr); + + FormattedStringBuilder sb3; + sb1.append(str); + // Note: UNUM_FIELD_COUNT is like passing null in Java + sb2.append(str, UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb2", status); + sb3.append(str, UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb3", status); + assertEqualsImpl(sb1, sb2); + assertEqualsImpl(str, sb3); + + UnicodeString sb4; + FormattedStringBuilder sb5; + sb4.append(u"😇"); + sb4.append(str); + sb4.append(u"xx"); + sb5.append(u"😇xx", UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb5", status); + sb5.insert(2, str, UNUM_FIELD_COUNT, status); + assertSuccess("Inserting into sb5", status); + assertEqualsImpl(sb4, sb5); + + int start = uprv_min(1, str.length()); + int end = uprv_min(10, str.length()); + sb4.insert(3, str, start, end - start); // UnicodeString uses length instead of end index + sb5.insert(3, str, start, end, UNUM_FIELD_COUNT, status); + assertSuccess("Inserting into sb5 again", status); + assertEqualsImpl(sb4, sb5); + + UnicodeString sb4cp(sb4); + FormattedStringBuilder sb5cp(sb5); + sb4.append(sb4cp); + sb5.append(sb5cp, status); + assertSuccess("Appending again to sb5", status); + assertEqualsImpl(sb4, sb5); + } +} + +void FormattedStringBuilderTest::testSplice() { + static const struct TestCase { + const char16_t* input; + const int32_t startThis; + const int32_t endThis; + } cases[] = { + { u"", 0, 0 }, + { u"abc", 0, 0 }, + { u"abc", 1, 1 }, + { u"abc", 1, 2 }, + { u"abc", 0, 2 }, + { u"abc", 0, 3 }, + { u"lorem ipsum dolor sit amet", 8, 8 }, + { u"lorem ipsum dolor sit amet", 8, 11 }, // 3 chars, equal to replacement "xyz" + { u"lorem ipsum dolor sit amet", 8, 18 } }; // 10 chars, larger than several replacements + + UErrorCode status = U_ZERO_ERROR; + UnicodeString sb1; + FormattedStringBuilder sb2; + for (auto cas : cases) { + for (const char16_t* replacementPtr : EXAMPLE_STRINGS) { + UnicodeString replacement(replacementPtr); + + // Test replacement with full string + sb1.remove(); + sb1.append(cas.input); + sb1.replace(cas.startThis, cas.endThis - cas.startThis, replacement); + sb2.clear(); + sb2.append(cas.input, UNUM_FIELD_COUNT, status); + sb2.splice(cas.startThis, cas.endThis, replacement, 0, replacement.length(), UNUM_FIELD_COUNT, status); + assertSuccess("Splicing into sb2 first time", status); + assertEqualsImpl(sb1, sb2); + + // Test replacement with partial string + if (replacement.length() <= 2) { + continue; + } + sb1.remove(); + sb1.append(cas.input); + sb1.replace(cas.startThis, cas.endThis - cas.startThis, UnicodeString(replacement, 1, 2)); + sb2.clear(); + sb2.append(cas.input, UNUM_FIELD_COUNT, status); + sb2.splice(cas.startThis, cas.endThis, replacement, 1, 3, UNUM_FIELD_COUNT, status); + assertSuccess("Splicing into sb2 second time", status); + assertEqualsImpl(sb1, sb2); + } + } +} + +void FormattedStringBuilderTest::testInsertAppendCodePoint() { + static const UChar32 cases[] = { + 0, 1, 60, 127, 128, 0x7fff, 0x8000, 0xffff, 0x10000, 0x1f000, 0x10ffff}; + UErrorCode status = U_ZERO_ERROR; + UnicodeString sb1; + FormattedStringBuilder sb2; + for (UChar32 cas : cases) { + FormattedStringBuilder sb3; + sb1.append(cas); + sb2.appendCodePoint(cas, UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb2", status); + sb3.appendCodePoint(cas, UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb3", status); + assertEqualsImpl(sb1, sb2); + assertEquals("Length of sb3", U16_LENGTH(cas), sb3.length()); + assertEquals("Code point count of sb3", 1, sb3.codePointCount()); + assertEquals( + "First code unit in sb3", + !U_IS_SUPPLEMENTARY(cas) ? (char16_t) cas : U16_LEAD(cas), + sb3.charAt(0)); + + UnicodeString sb4; + FormattedStringBuilder sb5; + sb4.append(u"😇xx"); + sb4.insert(2, cas); + sb5.append(u"😇xx", UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb5", status); + sb5.insertCodePoint(2, cas, UNUM_FIELD_COUNT, status); + assertSuccess("Inserting into sb5", status); + assertEqualsImpl(sb4, sb5); + + UnicodeString sb6; + FormattedStringBuilder sb7; + sb6.append(cas); + if (U_IS_SUPPLEMENTARY(cas)) { + sb7.appendChar16(U16_TRAIL(cas), UNUM_FIELD_COUNT, status); + sb7.insertChar16(0, U16_LEAD(cas), UNUM_FIELD_COUNT, status); + } else { + sb7.insertChar16(0, cas, UNUM_FIELD_COUNT, status); + } + assertSuccess("Insert/append into sb7", status); + assertEqualsImpl(sb6, sb7); + } +} + +void FormattedStringBuilderTest::testCopy() { + UErrorCode status = U_ZERO_ERROR; + for (UnicodeString str : EXAMPLE_STRINGS) { + FormattedStringBuilder sb1; + sb1.append(str, UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb1 first time", status); + FormattedStringBuilder sb2(sb1); + assertTrue("Content should equal itself", sb1.contentEquals(sb2)); + + sb1.append("12345", UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb1 second time", status); + assertFalse("Content should no longer equal itself", sb1.contentEquals(sb2)); + } +} + +void FormattedStringBuilderTest::testFields() { + UErrorCode status = U_ZERO_ERROR; + // Note: This is a C++11 for loop that calls the UnicodeString constructor on each iteration. + for (UnicodeString str : EXAMPLE_STRINGS) { + FormattedValueStringBuilderImpl sbi(0); + FormattedStringBuilder& sb = sbi.getStringRef(); + sb.append(str, UNUM_FIELD_COUNT, status); + assertSuccess("Appending to sb", status); + sb.append(str, UNUM_CURRENCY_FIELD, status); + assertSuccess("Appending to sb", status); + assertEquals("Reference string copied twice", str.length() * 2, sb.length()); + for (int32_t i = 0; i < str.length(); i++) { + assertEquals("Null field first", + (FormattedStringBuilder::Field) UNUM_FIELD_COUNT, sb.fieldAt(i)); + assertEquals("Currency field second", + (FormattedStringBuilder::Field) UNUM_CURRENCY_FIELD, sb.fieldAt(i + str.length())); + } + + // Very basic FieldPosition test. More robust tests happen in NumberFormatTest. + // Let NumberFormatTest also take care of FieldPositionIterator material. + FieldPosition fp(UNUM_CURRENCY_FIELD); + sbi.nextFieldPosition(fp, status); + assertSuccess("Populating the FieldPosition", status); + assertEquals("Currency start position", str.length(), fp.getBeginIndex()); + assertEquals("Currency end position", str.length() * 2, fp.getEndIndex()); + + if (str.length() > 0) { + sb.insertCodePoint(2, 100, UNUM_INTEGER_FIELD, status); + assertSuccess("Inserting code point into sb", status); + assertEquals("New length", str.length() * 2 + 1, sb.length()); + assertEquals("Integer field", (FormattedStringBuilder::Field) UNUM_INTEGER_FIELD, sb.fieldAt(2)); + } + + FormattedStringBuilder old(sb); + sb.append(old, status); + assertSuccess("Appending to myself", status); + int32_t numNull = 0; + int32_t numCurr = 0; + int32_t numInt = 0; + for (int32_t i = 0; i < sb.length(); i++) { + FormattedStringBuilder::Field field = sb.fieldAt(i); + assertEquals("Field should equal location in old", old.fieldAt(i % old.length()), field); + if (field == UNUM_FIELD_COUNT) { + numNull++; + } else if (field == UNUM_CURRENCY_FIELD) { + numCurr++; + } else if (field == UNUM_INTEGER_FIELD) { + numInt++; + } else { + errln("Encountered unknown field"); + } + } + assertEquals("Number of null fields", str.length() * 2, numNull); + assertEquals("Number of currency fields", numNull, numCurr); + assertEquals("Number of integer fields", str.length() > 0 ? 2 : 0, numInt); + } +} + +void FormattedStringBuilderTest::testUnlimitedCapacity() { + UErrorCode status = U_ZERO_ERROR; + FormattedStringBuilder builder; + // The builder should never fail upon repeated appends. + for (int i = 0; i < 1000; i++) { + UnicodeString message("Iteration #"); + message += Int64ToUnicodeString(i); + assertEquals(message, builder.length(), i); + builder.appendCodePoint(u'x', UNUM_FIELD_COUNT, status); + assertSuccess(message, status); + assertEquals(message, builder.length(), i + 1); + } +} + +void FormattedStringBuilderTest::testCodePoints() { + UErrorCode status = U_ZERO_ERROR; + FormattedStringBuilder nsb; + assertEquals("First is -1 on empty string", -1, nsb.getFirstCodePoint()); + assertEquals("Last is -1 on empty string", -1, nsb.getLastCodePoint()); + assertEquals("Length is 0 on empty string", 0, nsb.codePointCount()); + + nsb.append(u"q", UNUM_FIELD_COUNT, status); + assertSuccess("Spot 1", status); + assertEquals("First is q", u'q', nsb.getFirstCodePoint()); + assertEquals("Last is q", u'q', nsb.getLastCodePoint()); + assertEquals("0th is q", u'q', nsb.codePointAt(0)); + assertEquals("Before 1st is q", u'q', nsb.codePointBefore(1)); + assertEquals("Code point count is 1", 1, nsb.codePointCount()); + + // 🚀 is two char16s + nsb.append(u"🚀", UNUM_FIELD_COUNT, status); + assertSuccess("Spot 2" ,status); + assertEquals("First is still q", u'q', nsb.getFirstCodePoint()); + assertEquals("Last is space ship", 128640, nsb.getLastCodePoint()); + assertEquals("1st is space ship", 128640, nsb.codePointAt(1)); + assertEquals("Before 1st is q", u'q', nsb.codePointBefore(1)); + assertEquals("Before 3rd is space ship", 128640, nsb.codePointBefore(3)); + assertEquals("Code point count is 2", 2, nsb.codePointCount()); +} + +void FormattedStringBuilderTest::assertEqualsImpl(const UnicodeString &a, const FormattedStringBuilder &b) { + // TODO: Why won't this compile without the IntlTest:: qualifier? + IntlTest::assertEquals("Lengths should be the same", a.length(), b.length()); + IntlTest::assertEquals("Code point counts should be the same", a.countChar32(), b.codePointCount()); + + if (a.length() != b.length()) { + return; + } + + for (int32_t i = 0; i < a.length(); i++) { + IntlTest::assertEquals( + UnicodeString(u"Char at position ") + Int64ToUnicodeString(i) + + UnicodeString(u" in \"") + a + UnicodeString("\" versus \"") + + b.toUnicodeString() + UnicodeString("\""), a.charAt(i), b.charAt(i)); + } +} + + +extern IntlTest *createFormattedStringBuilderTest() { + return new FormattedStringBuilderTest(); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/idnaconf.cpp icu-65.1/source/test/intltest/idnaconf.cpp --- icu-64.2/source/test/intltest/idnaconf.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/idnaconf.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -173,7 +173,7 @@ curOffset += 1 + t; // BACKSLAH and NewlineMark continue; } - }; + } buf.append(c); curOffset++; } diff -Nru icu-64.2/source/test/intltest/idnaref.cpp icu-65.1/source/test/intltest/idnaref.cpp --- icu-64.2/source/test/intltest/idnaref.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/idnaref.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -198,6 +198,17 @@ return b2Len; } + +static NamePrepTransform* getInstance(UErrorCode& status){ + TestIDNA *thisTest = dynamic_cast(IntlTest::gTest); + if (thisTest == nullptr && U_SUCCESS(status)) { + status = U_INTERNAL_PROGRAM_ERROR; + } + if (U_FAILURE(status)) return nullptr; + return thisTest->getInstance(status); +} + + static int32_t convertFromPuny( const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, UErrorCode& status){ @@ -288,7 +299,7 @@ b1[b1Len++] = src[j]; } - NamePrepTransform* prep = TestIDNA::getInstance(*status); + NamePrepTransform* prep = getInstance(*status); if(U_FAILURE(*status)){ goto CLEANUP; } @@ -439,7 +450,7 @@ reqLength=0; // UParseError parseError; - NamePrepTransform* prep = TestIDNA::getInstance(*status); + NamePrepTransform* prep = getInstance(*status); b1Len = 0; UBool* caseFlags = NULL; @@ -694,7 +705,7 @@ int32_t reqLength = 0; // UParseError parseError; - NamePrepTransform* prep = TestIDNA::getInstance(*status); + NamePrepTransform* prep = getInstance(*status); //initialize pointers to stack buffers UChar b1Stack[MAX_LABEL_BUFFER_SIZE]; @@ -850,7 +861,7 @@ UBool done = FALSE; - NamePrepTransform* prep = TestIDNA::getInstance(*status); + NamePrepTransform* prep = getInstance(*status); //initialize pointers to stack buffers UChar b1Stack[MAX_LABEL_BUFFER_SIZE]; diff -Nru icu-64.2/source/test/intltest/incaltst.cpp icu-65.1/source/test/intltest/incaltst.cpp --- icu-64.2/source/test/intltest/incaltst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/incaltst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -22,11 +22,12 @@ #include #include "caltest.h" -#define CHECK(status, msg) \ +#define CHECK(status, msg) UPRV_BLOCK_MACRO_BEGIN { \ if (U_FAILURE(status)) { \ - dataerrln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \ + dataerrln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \ return; \ - } + } \ +} UPRV_BLOCK_MACRO_END static UnicodeString escape( const UnicodeString&src) @@ -417,34 +418,28 @@ // First, a contrived English test.. UDate aDate = 999932400000.0; - SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=buddhist"), status); + SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=buddhist"), status); CHECK(status, "creating date format instance"); - SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); + SimpleDateFormat fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); CHECK(status, "creating gregorian date format instance"); - if(!fmt) { - errln("Couldn't create en_US instance"); + UnicodeString str; + fmt2.format(aDate, str); + logln(UnicodeString() + "Test Date: " + str); + str.remove(); + fmt.format(aDate, str); + logln(UnicodeString() + "as Buddhist Calendar: " + escape(str)); + UnicodeString expected("September 8, 2544 BE"); + if(str != expected) { + errln("Expected " + escape(expected) + " but got " + escape(str)); + } + UDate otherDate = fmt.parse(expected, status); + if(otherDate != aDate) { + UnicodeString str3; + fmt.format(otherDate, str3); + errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate + ", " + escape(str3)); } else { - UnicodeString str; - fmt2->format(aDate, str); - logln(UnicodeString() + "Test Date: " + str); - str.remove(); - fmt->format(aDate, str); - logln(UnicodeString() + "as Buddhist Calendar: " + escape(str)); - UnicodeString expected("September 8, 2544 BE"); - if(str != expected) { - errln("Expected " + escape(expected) + " but got " + escape(str)); - } - UDate otherDate = fmt->parse(expected, status); - if(otherDate != aDate) { - UnicodeString str3; - fmt->format(otherDate, str3); - errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate + ", " + escape(str3)); - } else { - logln("Parsed OK: " + expected); - } - delete fmt; + logln("Parsed OK: " + expected); } - delete fmt2; CHECK(status, "Error occurred testing Buddhist Calendar in English "); @@ -491,81 +486,68 @@ void IntlCalendarTest::TestJapaneseFormat() { - Calendar *cal; + LocalPointer cal; UErrorCode status = U_ZERO_ERROR; - cal = Calendar::createInstance("ja_JP@calendar=japanese", status); + cal.adoptInstead(Calendar::createInstance("ja_JP@calendar=japanese", status)); CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar")); - Calendar *cal2 = cal->clone(); - delete cal; - cal = NULL; + LocalPointer cal2(cal->clone()); + cal.adoptInstead(nullptr); // Test simple parse/format with adopt UDate aDate = 999932400000.0; - SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status); - SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); + SimpleDateFormat fmt(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status); + SimpleDateFormat fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); CHECK(status, "creating date format instance"); - if(!fmt) { - errln("Couldn't create en_US instance"); + UnicodeString str; + fmt2.format(aDate, str); + logln(UnicodeString() + "Test Date: " + str); + str.remove(); + fmt.format(aDate, str); + logln(UnicodeString() + "as Japanese Calendar: " + str); + UnicodeString expected("September 8, 13 Heisei"); + if(str != expected) { + errln("Expected " + expected + " but got " + str); + } + UDate otherDate = fmt.parse(expected, status); + if(otherDate != aDate) { + UnicodeString str3; + ParsePosition pp; + fmt.parse(expected, *cal2, pp); + fmt.format(otherDate, str3); + errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); + } else { - UnicodeString str; - fmt2->format(aDate, str); - logln(UnicodeString() + "Test Date: " + str); - str.remove(); - fmt->format(aDate, str); - logln(UnicodeString() + "as Japanese Calendar: " + str); - UnicodeString expected("September 8, 13 Heisei"); - if(str != expected) { - errln("Expected " + expected + " but got " + str); - } - UDate otherDate = fmt->parse(expected, status); - if(otherDate != aDate) { - UnicodeString str3; - ParsePosition pp; - fmt->parse(expected, *cal2, pp); - fmt->format(otherDate, str3); - errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); - - } else { - logln("Parsed OK: " + expected); - } - delete fmt; + logln("Parsed OK: " + expected); } // Test parse with incomplete information - fmt = new SimpleDateFormat(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status); + SimpleDateFormat fmti(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status); aDate = -3197117222000.0; CHECK(status, "creating date format instance"); - if(!fmt) { - errln("Coudln't create en_US instance"); - } else { - UnicodeString str; - fmt2->format(aDate, str); - logln(UnicodeString() + "Test Date: " + str); - str.remove(); - fmt->format(aDate, str); - logln(UnicodeString() + "as Japanese Calendar: " + str); - UnicodeString expected("Meiji 1"); - if(str != expected) { - errln("Expected " + expected + " but got " + str); - } - UDate otherDate = fmt->parse(expected, status); - if(otherDate != aDate) { - UnicodeString str3; - ParsePosition pp; - fmt->parse(expected, *cal2, pp); - fmt->format(otherDate, str3); - errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + + str.remove(); + fmt2.format(aDate, str); + logln(UnicodeString() + "Test Date: " + str); + str.remove(); + fmti.format(aDate, str); + logln(UnicodeString() + "as Japanese Calendar: " + str); + expected = u"Meiji 1"; + if(str != expected) { + errln("Expected " + expected + " but got " + str); + } + otherDate = fmti.parse(expected, status); + if(otherDate != aDate) { + UnicodeString str3; + ParsePosition pp; + fmti.parse(expected, *cal2, pp); + fmti.format(otherDate, str3); + errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) ); - } else { - logln("Parsed OK: " + expected); - } - delete fmt; + } else { + logln("Parsed OK: " + expected); } - delete cal2; - delete fmt2; CHECK(status, "Error occurred"); // Now, try in Japanese @@ -625,98 +607,83 @@ void IntlCalendarTest::TestJapanese3860() { - Calendar *cal; + LocalPointer cal; UErrorCode status = U_ZERO_ERROR; - cal = Calendar::createInstance("ja_JP@calendar=japanese", status); + cal.adoptInstead(Calendar::createInstance("ja_JP@calendar=japanese", status)); CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar")); - Calendar *cal2 = cal->clone(); - SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("HH:mm:ss.S MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); + LocalPointer cal2(cal->clone()); + SimpleDateFormat fmt2(UnicodeString("HH:mm:ss.S MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); UnicodeString str; - { // Test simple parse/format with adopt UDate aDate = 0; - + // Test parse with missing era (should default to current era, heisei) // Test parse with incomplete information logln("Testing parse w/ missing era..."); - SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("y/M/d"), Locale("ja_JP@calendar=japanese"), status); + SimpleDateFormat fmt(UnicodeString("y/M/d"), Locale("ja_JP@calendar=japanese"), status); CHECK(status, "creating date format instance"); - if(!fmt) { - errln("Couldn't create en_US instance"); - } else { - UErrorCode s2 = U_ZERO_ERROR; - cal2->clear(); - UnicodeString samplestr("1/5/9"); - logln(UnicodeString() + "Test Year: " + samplestr); - aDate = fmt->parse(samplestr, s2); - ParsePosition pp=0; - fmt->parse(samplestr, *cal2, pp); - CHECK(s2, "parsing the 1/5/9 string"); - logln("*cal2 after 159 parse:"); - str.remove(); - fmt2->format(aDate, str); - logln(UnicodeString() + "as Gregorian Calendar: " + str); - - cal2->setTime(aDate, s2); - int32_t gotYear = cal2->get(UCAL_YEAR, s2); - int32_t gotEra = cal2->get(UCAL_ERA, s2); - int32_t expectYear = 1; - int32_t expectEra = JapaneseCalendar::getCurrentEra(); - if((gotYear!=1) || (gotEra != expectEra)) { - errln(UnicodeString("parse "+samplestr+" of 'y/M/d' as Japanese Calendar, expected year ") + expectYear + + UErrorCode s2 = U_ZERO_ERROR; + cal2->clear(); + UnicodeString samplestr("1/5/9"); + logln(UnicodeString() + "Test Year: " + samplestr); + aDate = fmt.parse(samplestr, s2); + ParsePosition pp=0; + fmt.parse(samplestr, *cal2, pp); + CHECK(s2, "parsing the 1/5/9 string"); + logln("*cal2 after 159 parse:"); + str.remove(); + fmt2.format(aDate, str); + logln(UnicodeString() + "as Gregorian Calendar: " + str); + + cal2->setTime(aDate, s2); + int32_t gotYear = cal2->get(UCAL_YEAR, s2); + int32_t gotEra = cal2->get(UCAL_ERA, s2); + int32_t expectYear = 1; + int32_t expectEra = JapaneseCalendar::getCurrentEra(); + if((gotYear!=1) || (gotEra != expectEra)) { + errln(UnicodeString("parse "+samplestr+" of 'y/M/d' as Japanese Calendar, expected year ") + expectYear + UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")"); - } else { - logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra); - } - delete fmt; + } else { + logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra); } } { // Test simple parse/format with adopt UDate aDate = 0; - + // Test parse with missing era (should default to current era, heisei) // Test parse with incomplete information logln("Testing parse w/ just year..."); - SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("y"), Locale("ja_JP@calendar=japanese"), status); + SimpleDateFormat fmt(UnicodeString("y"), Locale("ja_JP@calendar=japanese"), status); CHECK(status, "creating date format instance"); - if(!fmt) { - errln("Couldn't create en_US instance"); - } else { - UErrorCode s2 = U_ZERO_ERROR; - cal2->clear(); - UnicodeString samplestr("1"); - logln(UnicodeString() + "Test Year: " + samplestr); - aDate = fmt->parse(samplestr, s2); - ParsePosition pp=0; - fmt->parse(samplestr, *cal2, pp); - CHECK(s2, "parsing the 1 string"); - logln("*cal2 after 1 parse:"); - str.remove(); - fmt2->format(aDate, str); - logln(UnicodeString() + "as Gregorian Calendar: " + str); - - cal2->setTime(aDate, s2); - int32_t gotYear = cal2->get(UCAL_YEAR, s2); - int32_t gotEra = cal2->get(UCAL_ERA, s2); - int32_t expectYear = 1; - int32_t expectEra = JapaneseCalendar::getCurrentEra(); - if((gotYear!=1) || (gotEra != expectEra)) { - errln(UnicodeString("parse "+samplestr+" of 'y' as Japanese Calendar, expected year ") + expectYear + + UErrorCode s2 = U_ZERO_ERROR; + cal2->clear(); + UnicodeString samplestr("1"); + logln(UnicodeString() + "Test Year: " + samplestr); + aDate = fmt.parse(samplestr, s2); + ParsePosition pp=0; + fmt.parse(samplestr, *cal2, pp); + CHECK(s2, "parsing the 1 string"); + logln("*cal2 after 1 parse:"); + str.remove(); + fmt2.format(aDate, str); + logln(UnicodeString() + "as Gregorian Calendar: " + str); + + cal2->setTime(aDate, s2); + int32_t gotYear = cal2->get(UCAL_YEAR, s2); + int32_t gotEra = cal2->get(UCAL_ERA, s2); + int32_t expectYear = 1; + int32_t expectEra = JapaneseCalendar::getCurrentEra(); + if((gotYear!=1) || (gotEra != expectEra)) { + errln(UnicodeString("parse "+samplestr+" of 'y' as Japanese Calendar, expected year ") + expectYear + UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")"); - } else { - logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra); - } - delete fmt; + } else { + logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra); } } - - delete cal2; - delete cal; - delete fmt2; } void IntlCalendarTest::TestForceGannenNumbering() @@ -908,48 +875,42 @@ void IntlCalendarTest::TestPersianFormat() { UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status); + SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status); CHECK(status, "creating date format instance"); - SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); + SimpleDateFormat fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status); CHECK(status, "creating gregorian date format instance"); UnicodeString gregorianDate("January 18, 2007 AD"); - UDate aDate = fmt2->parse(gregorianDate, status); - if(!fmt) { - errln("Couldn't create en_US instance"); + UDate aDate = fmt2.parse(gregorianDate, status); + UnicodeString str; + fmt.format(aDate, str); + logln(UnicodeString() + "as Persian Calendar: " + escape(str)); + UnicodeString expected("Dey 28, 1385 AP"); + if(str != expected) { + errln("Expected " + escape(expected) + " but got " + escape(str)); + } + UDate otherDate = fmt.parse(expected, status); + if(otherDate != aDate) { + UnicodeString str3; + fmt.format(otherDate, str3); + errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate + ", " + escape(str3)); } else { - UnicodeString str; - fmt->format(aDate, str); - logln(UnicodeString() + "as Persian Calendar: " + escape(str)); - UnicodeString expected("Dey 28, 1385 AP"); - if(str != expected) { - errln("Expected " + escape(expected) + " but got " + escape(str)); - } - UDate otherDate = fmt->parse(expected, status); - if(otherDate != aDate) { - UnicodeString str3; - fmt->format(otherDate, str3); - errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate + ", " + escape(str3)); - } else { - logln("Parsed OK: " + expected); - } - // Two digit year parsing problem #4732 - fmt->applyPattern("yy-MM-dd"); - str.remove(); - fmt->format(aDate, str); - expected.setTo("85-10-28"); - if(str != expected) { - errln("Expected " + escape(expected) + " but got " + escape(str)); - } - otherDate = fmt->parse(expected, status); - if (otherDate != aDate) { - errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate); - } else { - logln("Parsed OK: " + expected); - } - delete fmt; + logln("Parsed OK: " + expected); } - delete fmt2; - + // Two digit year parsing problem #4732 + fmt.applyPattern("yy-MM-dd"); + str.remove(); + fmt.format(aDate, str); + expected.setTo("85-10-28"); + if(str != expected) { + errln("Expected " + escape(expected) + " but got " + escape(str)); + } + otherDate = fmt.parse(expected, status); + if (otherDate != aDate) { + errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate); + } else { + logln("Parsed OK: " + expected); + } + CHECK(status, "Error occured testing Persian Calendar in English "); } diff -Nru icu-64.2/source/test/intltest/intltest.cpp icu-65.1/source/test/intltest/intltest.cpp --- icu-64.2/source/test/intltest/intltest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/intltest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -593,6 +593,7 @@ quick = caller->quick; threadCount = caller->threadCount; testoutfp = caller->testoutfp; + write_golden_data = caller->write_golden_data; LL_indentlevel = caller->LL_indentlevel + indentLevel_offset; numProps = caller->numProps; for (int32_t i = 0; i < numProps; i++) { @@ -637,6 +638,13 @@ return rval; } +UBool IntlTest::setWriteGoldenData( UBool write_golden_data ) +{ + UBool rval = this->write_golden_data; + this->write_golden_data = write_golden_data; + return rval; +} + UBool IntlTest::setNoErrMsg( UBool no_err_msgVal ) { UBool rval = this->no_err_msg; @@ -1116,7 +1124,7 @@ // All error messages generated by tests funnel through here. // Multithreaded tests can concurrently generate errors, requiring synchronization // to keep each message together. - static UMutex messageMutex = U_MUTEX_INITIALIZER; + static UMutex messageMutex; Mutex lock(&messageMutex); // string that starts with a LineFeed character and continues @@ -1224,6 +1232,7 @@ UBool utf8 = FALSE; const char *summary_file = NULL; UBool warnOnMissingData = FALSE; + UBool writeGoldenData = FALSE; UBool defaultDataFound = FALSE; int32_t threadCount = 12; UErrorCode errorCode = U_ZERO_ERROR; @@ -1265,6 +1274,9 @@ else if (strcmp("notime", str) == 0 || strcmp("T", str) == 0) no_time = TRUE; + else if (strcmp("goldens", str) == 0 || + strcmp("G", str) == 0) + writeGoldenData = TRUE; else if (strncmp("E", str, 1) == 0) summary_file = str+1; else if (strcmp("x", str)==0) { @@ -1338,6 +1350,7 @@ major.setLeaks( leaks ); major.setThreadCount( threadCount ); major.setWarnOnMissingData( warnOnMissingData ); + major.setWriteGoldenData( writeGoldenData ); major.setNotime (no_time); for (int32_t i = 0; i < nProps; i++) { major.setProperty(props[i]); @@ -1371,9 +1384,10 @@ fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off")); fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off")); fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off")); - fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off")); - fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off")); + fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off")); + fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off")); fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off")); + fprintf(stdout, " Write golden data (G) : %s\n", (writeGoldenData? "On" : "Off")); fprintf(stdout, " Threads : %d\n", threadCount); for (int32_t i = 0; i < nProps; i++) { fprintf(stdout, " Custom property (prop:) : %s\n", props[i]); @@ -2105,6 +2119,42 @@ } #endif +std::string vectorToString(const std::vector& strings) { + std::string result = "{"; + bool first = true; + for (auto element : strings) { + if (first) { + first = false; + } else { + result += ", "; + } + result += "\""; + result += element; + result += "\""; + } + result += "}"; + return result; +} + +UBool IntlTest::assertEquals(const char* message, + const std::vector& expected, + const std::vector& actual) { + if (expected != actual) { + std::string expectedAsString = vectorToString(expected); + std::string actualAsString = vectorToString(actual); + errln((UnicodeString)"FAIL: " + message + + "; got " + actualAsString.c_str() + + "; expected " + expectedAsString.c_str()); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + logln((UnicodeString)"Ok: " + message + "; got " + vectorToString(actual).c_str()); + } +#endif + return TRUE; +} + static char ASSERT_BUF[256]; static const char* extractToAssertBuf(const UnicodeString& message) { @@ -2169,6 +2219,11 @@ const UnicodeSet& actual) { return assertEquals(extractToAssertBuf(message), expected, actual); } +UBool IntlTest::assertEquals(const UnicodeString& message, + const std::vector& expected, + const std::vector& actual) { + return assertEquals(extractToAssertBuf(message), expected, actual); +} #if !UCONFIG_NO_FORMATTING UBool IntlTest::assertEquals(const UnicodeString& message, diff -Nru icu-64.2/source/test/intltest/intltest.h icu-65.1/source/test/intltest/intltest.h --- icu-64.2/source/test/intltest/intltest.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/intltest.h 2019-10-03 11:16:41.000000000 +0000 @@ -18,6 +18,9 @@ #include "unicode/testlog.h" #include "unicode/uniset.h" +#include +#include + U_NAMESPACE_USE #if U_PLATFORM == U_PF_OS390 @@ -84,7 +87,7 @@ //| TESTCASE_AUTO_END; //| } #define TESTCASE_AUTO_BEGIN \ - for(;;) { \ + do { \ int32_t testCaseAutoNumber = 0 #define TESTCASE_AUTO(test) \ @@ -96,7 +99,7 @@ test(); \ } \ break; \ - } + } else (void)0 #define TESTCASE_AUTO_CLASS(TestClass) \ if (index == testCaseAutoNumber++) { \ @@ -108,7 +111,7 @@ callTest(test, par); \ } \ break; \ - } + } else (void)0 #define TESTCASE_AUTO_CREATE_CLASS(TestClass) \ if (index == testCaseAutoNumber++) { \ @@ -120,12 +123,12 @@ callTest(*test, par); \ } \ break; \ - } + } else (void)0 #define TESTCASE_AUTO_END \ name = ""; \ break; \ - } + } while (TRUE) // WHERE Macro yields a literal string of the form "source_file_name:line number " @@ -147,6 +150,7 @@ virtual UBool setLeaks( UBool leaks = TRUE ); virtual UBool setNotime( UBool no_time = TRUE ); virtual UBool setWarnOnMissingData( UBool warn_on_missing_data = TRUE ); + virtual UBool setWriteGoldenData( UBool write_golden_data = TRUE ); virtual int32_t setThreadCount( int32_t count = 1); virtual int32_t getErrors( void ); @@ -297,6 +301,8 @@ UBool assertEquals(const char* message, double expected, double actual); UBool assertEquals(const char* message, UErrorCode expected, UErrorCode actual); UBool assertEquals(const char* message, const UnicodeSet& expected, const UnicodeSet& actual); + UBool assertEquals(const char* message, + const std::vector& expected, const std::vector& actual); #if !UCONFIG_NO_FORMATTING UBool assertEquals(const char* message, const Formattable& expected, const Formattable& actual, UBool possibleDataError=FALSE); @@ -315,6 +321,8 @@ UBool assertEquals(const UnicodeString& message, double expected, double actual); UBool assertEquals(const UnicodeString& message, UErrorCode expected, UErrorCode actual); UBool assertEquals(const UnicodeString& message, const UnicodeSet& expected, const UnicodeSet& actual); + UBool assertEquals(const UnicodeString& message, + const std::vector& expected, const std::vector& actual); virtual void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide ! @@ -332,6 +340,7 @@ UBool quick; UBool leaks; UBool warn_on_missing_data; + UBool write_golden_data; UBool no_time; int32_t threadCount; diff -Nru icu-64.2/source/test/intltest/intltest.vcxproj icu-65.1/source/test/intltest/intltest.vcxproj --- icu-64.2/source/test/intltest/intltest.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/intltest.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -34,121 +34,55 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Debug\ - .\x64\Debug\ - true - .\x86\Release\ - .\x86\Release\ - false - .\x64\Release\ - .\x64\Release\ - false + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false + + $(OutDir)\intltest.tlb + ..\..\..\include;..\..\common;..\..\i18n;..\..\tools\toolutil;..\..\tools\ctestfw;%(AdditionalIncludeDirectories) U_ATTRIBUTE_DEPRECATED=;%(PreprocessorDefinitions) false Level3 - - - - - .\x86\Debug/intltest.tlb - - - MultiThreadedDebug - .\x86\Debug/intltest.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true - EditAndContinue Default + $(OutDir)/intltest.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/intltest.pdb - .\x86\Debug/intltest.exe - icuucd.lib;icuind.lib;icutud.lib;icutestd.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Debug/intltest.pdb Console - false - false - - + $(OutDir)/intltest.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - .\x64\Debug/intltest.tlb - + + - MultiThreadedDebug - .\x64\Debug/intltest.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ true - ProgramDatabase - Default + MultiThreadedDebugDLL - .\x64\Debug/intltest.exe icuucd.lib;icuind.lib;icutud.lib;icutestd.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/intltest.pdb - Console - false - - - .\x86\Release/intltest.tlb - + + - MultiThreaded - .\x86\Release/intltest.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - Default + MultiThreadedDLL + true - .\x86\Release/intltest.exe icuuc.lib;icuin.lib;icutu.lib;icutest.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Release/intltest.pdb - Console - false - - - - - - - .\x64\Release/intltest.tlb - - - MultiThreaded - .\x64\Release/intltest.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default - - - .\x64\Release/intltest.exe - icuuc.lib;icuin.lib;icutu.lib;icutest.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Release/intltest.pdb - Console @@ -232,6 +166,7 @@ + @@ -251,12 +186,12 @@ - - + + @@ -365,6 +300,7 @@ + diff -Nru icu-64.2/source/test/intltest/intltest.vcxproj.filters icu-65.1/source/test/intltest/intltest.vcxproj.filters --- icu-64.2/source/test/intltest/intltest.vcxproj.filters 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/intltest.vcxproj.filters 2019-10-03 11:16:41.000000000 +0000 @@ -217,6 +217,9 @@ formatting + + formatting + formatting @@ -274,10 +277,7 @@ formatting - - formatting - - + formatting @@ -292,6 +292,9 @@ formatting + + formatting + formatting @@ -540,9 +543,13 @@ formatting + locales & resources + + locales & resources + diff -Nru icu-64.2/source/test/intltest/itformat.cpp icu-65.1/source/test/intltest/itformat.cpp --- icu-64.2/source/test/intltest/itformat.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/itformat.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -72,6 +72,8 @@ extern IntlTest *createNumberFormatSpecificationTest(); extern IntlTest *createScientificNumberFormatterTest(); extern IntlTest *createFormattedValueTest(); +extern IntlTest *createFormattedStringBuilderTest(); +extern IntlTest *createStringSegmentTest(); #define TESTCLASS(id, TestClass) \ @@ -227,6 +229,24 @@ callTest(*test, par); } break; + case 54: + name = "FormattedStringBuilderTest"; + if (exec) { + logln("FormattedStringBuilderTest test---"); + logln((UnicodeString)""); + LocalPointer test(createFormattedStringBuilderTest()); + callTest(*test, par); + } + break; + case 55: + name = "StringSegmentTest"; + if (exec) { + logln("StringSegmentTest test---"); + logln((UnicodeString)""); + LocalPointer test(createStringSegmentTest()); + callTest(*test, par); + } + break; default: name = ""; break; //needed to end loop } if (exec) { diff -Nru icu-64.2/source/test/intltest/itrbnf.cpp icu-65.1/source/test/intltest/itrbnf.cpp --- icu-64.2/source/test/intltest/itrbnf.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/itrbnf.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -166,7 +166,7 @@ // test clone { logln("Testing Clone"); - RuleBasedNumberFormat* rbnfClone = (RuleBasedNumberFormat *)formatter->clone(); + RuleBasedNumberFormat* rbnfClone = formatter->clone(); if(rbnfClone != NULL) { if(!(*rbnfClone == *formatter)) { errln("Clone should be semantically equivalent to the original!"); diff -Nru icu-64.2/source/test/intltest/itspoof.cpp icu-65.1/source/test/intltest/itspoof.cpp --- icu-64.2/source/test/intltest/itspoof.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/itspoof.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -29,22 +29,37 @@ #include #include -#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ - errcheckln(status, "Failure at file %s, line %d, error = %s", __FILE__, __LINE__, u_errorName(status));}} - -#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ - errln("Test Failure at file %s, line %d: \"%s\" is false.", __FILE__, __LINE__, #expr);};} - -#define TEST_ASSERT_MSG(expr, msg) {if ((expr)==FALSE) { \ - dataerrln("Test Failure at file %s, line %d, %s: \"%s\" is false.", __FILE__, __LINE__, msg, #expr);};} - -#define TEST_ASSERT_EQ(a, b) { if ((a) != (b)) { \ - errln("Test Failure at file %s, line %d: \"%s\" (%d) != \"%s\" (%d)", \ - __FILE__, __LINE__, #a, (a), #b, (b)); }} - -#define TEST_ASSERT_NE(a, b) { if ((a) == (b)) { \ - errln("Test Failure at file %s, line %d: \"%s\" (%d) == \"%s\" (%d)", \ - __FILE__, __LINE__, #a, (a), #b, (b)); }} +#define TEST_ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + errcheckln(status, "Failure at file %s, line %d, error = %s", __FILE__, __LINE__, u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("Test Failure at file %s, line %d: \"%s\" is false.", __FILE__, __LINE__, #expr); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_MSG(expr, msg) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + dataerrln("Test Failure at file %s, line %d, %s: \"%s\" is false.", __FILE__, __LINE__, msg, #expr); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_EQ(a, b) UPRV_BLOCK_MACRO_BEGIN { \ + if ((a) != (b)) { \ + errln("Test Failure at file %s, line %d: \"%s\" (%d) != \"%s\" (%d)", \ + __FILE__, __LINE__, #a, (a), #b, (b)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_NE(a, b) UPRV_BLOCK_MACRO_BEGIN { \ + if ((a) == (b)) { \ + errln("Test Failure at file %s, line %d: \"%s\" (%d) == \"%s\" (%d)", \ + __FILE__, __LINE__, #a, (a), #b, (b)); \ + } \ +} UPRV_BLOCK_MACRO_END /* * TEST_SETUP and TEST_TEARDOWN @@ -52,7 +67,7 @@ * Put arbitrary test code between SETUP and TEARDOWN. * "sc" is the ready-to-go SpoofChecker for use in the tests. */ -#define TEST_SETUP { \ +#define TEST_SETUP UPRV_BLOCK_MACRO_BEGIN { \ UErrorCode status = U_ZERO_ERROR; \ USpoofChecker *sc; \ sc = uspoof_open(&status); \ @@ -67,7 +82,7 @@ TEST_ASSERT_SUCCESS(status); \ uspoof_closeCheckResult(checkResult); \ uspoof_close(sc); \ -} +} UPRV_BLOCK_MACRO_END @@ -128,9 +143,9 @@ } -#define CHECK_SKELETON(type, input, expected) { \ +#define CHECK_SKELETON(type, input, expected) UPRV_BLOCK_MACRO_BEGIN { \ checkSkeleton(sc, type, input, expected, __LINE__); \ - } +} UPRV_BLOCK_MACRO_END // testSkeleton. Spot check a number of confusable skeleton substitutions from the @@ -639,7 +654,7 @@ TEST_ASSERT_MSG((expectedSet.size() > 1) == mixedNumberFailure, msgBuf); const UnicodeSet* actualSet = UnicodeSet::fromUSet(uspoof_getCheckResultNumerics(checkResult, &status)); TEST_ASSERT_MSG(expectedSet == *actualSet, msgBuf); - TEST_TEARDOWN + TEST_TEARDOWN; } } diff -Nru icu-64.2/source/test/intltest/itutil.cpp icu-65.1/source/test/intltest/itutil.cpp --- icu-64.2/source/test/intltest/itutil.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/itutil.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -35,6 +35,7 @@ #include "usettest.h" extern IntlTest *createBytesTrieTest(); +extern IntlTest *createLocaleMatcherTest(); static IntlTest *createLocalPointerTest(); extern IntlTest *createUCharsTrieTest(); static IntlTest *createEnumSetTest(); @@ -46,113 +47,40 @@ extern IntlTest *createStaticUnicodeSetsTest(); #endif - -#define CASE(id, test) case id: \ - name = #test; \ - if (exec) { \ - logln(#test "---"); logln(); \ - test t; \ - callTest(t, par); \ - } \ - break - void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par ) { if (exec) logln("TestSuite Utilities: "); - switch (index) { - CASE(0, MultithreadTest); - CASE(1, StringTest); - CASE(2, UnicodeStringTest); - CASE(3, LocaleTest); - CASE(4, CharIterTest); - CASE(5, UObjectTest); - CASE(6, UnicodeTest); - CASE(7, ResourceBundleTest); - CASE(8, NewResourceBundleTest); - CASE(9, PUtilTest); - CASE(10, UVector32Test); - CASE(11, UVectorTest); - CASE(12, UTextTest); - CASE(13, LocaleAliasTest); - CASE(14, UnicodeSetTest); - CASE(15, ErrorCodeTest); - case 16: - name = "LocalPointerTest"; - if (exec) { - logln("TestSuite LocalPointerTest---"); logln(); - LocalPointer test(createLocalPointerTest()); - callTest(*test, par); - } - break; - case 17: - name = "BytesTrieTest"; - if (exec) { - logln("TestSuite BytesTrieTest---"); logln(); - LocalPointer test(createBytesTrieTest()); - callTest(*test, par); - } - break; - case 18: - name = "UCharsTrieTest"; - if (exec) { - logln("TestSuite UCharsTrieTest---"); logln(); - LocalPointer test(createUCharsTrieTest()); - callTest(*test, par); - } - break; - case 19: - name = "EnumSetTest"; - if (exec) { - logln("TestSuite EnumSetTest---"); logln(); - LocalPointer test(createEnumSetTest()); - callTest(*test, par); - } - break; - case 20: - name = "SimpleFormatterTest"; - if (exec) { - logln("TestSuite SimpleFormatterTest---"); logln(); - LocalPointer test(createSimpleFormatterTest()); - callTest(*test, par); - } - break; - case 21: - name = "UnifiedCacheTest"; - if (exec) { - logln("TestSuite UnifiedCacheTest---"); logln(); - LocalPointer test(createUnifiedCacheTest()); - callTest(*test, par); - } - break; - case 22: - name = "QuantityFormatterTest"; - if (exec) { - logln("TestSuite QuantityFormatterTest---"); logln(); - LocalPointer test(createQuantityFormatterTest()); - callTest(*test, par); - } - break; - case 23: - name = "PluralMapTest"; - if (exec) { - logln("TestSuite PluralMapTest---"); logln(); - LocalPointer test(createPluralMapTest()); - callTest(*test, par); - } - break; - case 24: - name = "StaticUnicodeSetsTest"; + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO_CLASS(MultithreadTest); + TESTCASE_AUTO_CLASS(StringTest); + TESTCASE_AUTO_CLASS(UnicodeStringTest); + TESTCASE_AUTO_CLASS(LocaleTest); + TESTCASE_AUTO_CLASS(CharIterTest); + TESTCASE_AUTO_CLASS(UObjectTest); + TESTCASE_AUTO_CLASS(UnicodeTest); + TESTCASE_AUTO_CLASS(ResourceBundleTest); + TESTCASE_AUTO_CLASS(NewResourceBundleTest); + TESTCASE_AUTO_CLASS(PUtilTest); + TESTCASE_AUTO_CLASS(UVector32Test); + TESTCASE_AUTO_CLASS(UVectorTest); + TESTCASE_AUTO_CLASS(UTextTest); + TESTCASE_AUTO_CLASS(LocaleAliasTest); + TESTCASE_AUTO_CLASS(UnicodeSetTest); + TESTCASE_AUTO_CLASS(ErrorCodeTest); + TESTCASE_AUTO_CREATE_CLASS(LocalPointerTest); + TESTCASE_AUTO_CREATE_CLASS(BytesTrieTest); + TESTCASE_AUTO_CREATE_CLASS(UCharsTrieTest); + TESTCASE_AUTO_CREATE_CLASS(EnumSetTest); + TESTCASE_AUTO_CREATE_CLASS(SimpleFormatterTest); + TESTCASE_AUTO_CREATE_CLASS(UnifiedCacheTest); + TESTCASE_AUTO_CREATE_CLASS(QuantityFormatterTest); + TESTCASE_AUTO_CREATE_CLASS(PluralMapTest); #if !UCONFIG_NO_FORMATTING - if (exec) { - logln("TestSuite StaticUnicodeSetsTest---"); logln(); - LocalPointer test(createStaticUnicodeSetsTest()); - callTest(*test, par); - } + TESTCASE_AUTO_CREATE_CLASS(StaticUnicodeSetsTest); #endif - break; - CASE(25, LocaleBuilderTest); - default: name = ""; break; //needed to end loop - } + TESTCASE_AUTO_CLASS(LocaleBuilderTest); + TESTCASE_AUTO_CREATE_CLASS(LocaleMatcherTest); + TESTCASE_AUTO_END; } void ErrorCodeTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/) { diff -Nru icu-64.2/source/test/intltest/localebuildertest.cpp icu-65.1/source/test/intltest/localebuildertest.cpp --- icu-64.2/source/test/intltest/localebuildertest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/localebuildertest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -55,10 +55,21 @@ void LocaleBuilderTest::Verify(LocaleBuilder& bld, const char* expected, const char* msg) { UErrorCode status = U_ZERO_ERROR; + UErrorCode copyStatus = U_ZERO_ERROR; + UErrorCode errorStatus = U_ILLEGAL_ARGUMENT_ERROR; + if (bld.copyErrorTo(copyStatus)) { + errln(msg, u_errorName(copyStatus)); + } + if (!bld.copyErrorTo(errorStatus) || errorStatus != U_ILLEGAL_ARGUMENT_ERROR) { + errln("Should always get the previous error and return FALSE"); + } Locale loc = bld.build(status); if (U_FAILURE(status)) { errln(msg, u_errorName(status)); } + if (status != copyStatus) { + errln(msg, u_errorName(status)); + } std::string tag = loc.toLanguageTag(status); if (U_FAILURE(status)) { errln("loc.toLanguageTag() got Error: %s\n", @@ -190,39 +201,67 @@ status = U_ZERO_ERROR; bld.clear(); while (true) { + status = U_ZERO_ERROR; + UErrorCode copyStatus = U_ZERO_ERROR; method = testCase[i++]; if (strcmp("L", method) == 0) { - bld.setLanguage(testCase[i++]).build(status); + bld.setLanguage(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("S", method) == 0) { - bld.setScript(testCase[i++]).build(status); + bld.setScript(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("R", method) == 0) { - bld.setRegion(testCase[i++]).build(status); + bld.setRegion(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("V", method) == 0) { - bld.setVariant(testCase[i++]).build(status); + bld.setVariant(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("K", method) == 0) { const char* key = testCase[i++]; const char* type = testCase[i++]; - bld.setUnicodeLocaleKeyword(key, type).build(status); + bld.setUnicodeLocaleKeyword(key, type); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("A", method) == 0) { - bld.addUnicodeLocaleAttribute(testCase[i++]).build(status); + bld.addUnicodeLocaleAttribute(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("E", method) == 0) { const char* key = testCase[i++]; const char* value = testCase[i++]; - bld.setExtension(key[0], value).build(status); + bld.setExtension(key[0], value); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("P", method) == 0) { - bld.setExtension('x', testCase[i++]).build(status); + bld.setExtension('x', testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("U", method) == 0) { - bld.setLocale(Locale(testCase[i++])).build(status); + bld.setLocale(Locale(testCase[i++])); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("B", method) == 0) { - bld.setLanguageTag(testCase[i++]).build(status); + bld.setLanguageTag(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } // clear / remove else if (strcmp("C", method) == 0) { - bld.clear().build(status); + bld.clear(); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("N", method) == 0) { - bld.clearExtensions().build(status); + bld.clearExtensions(); + bld.copyErrorTo(copyStatus); + bld.build(status); } else if (strcmp("D", method) == 0) { - bld.removeUnicodeLocaleAttribute(testCase[i++]).build(status); + bld.removeUnicodeLocaleAttribute(testCase[i++]); + bld.copyErrorTo(copyStatus); + bld.build(status); } // result else if (strcmp("X", method) == 0) { @@ -232,6 +271,9 @@ } else if (strcmp("T", method) == 0) { status = U_ZERO_ERROR; Locale loc = bld.build(status); + if (status != copyStatus) { + errln("copyErrorTo not matching"); + } if (U_FAILURE(status) || strcmp(loc.getName(), testCase[i + 1]) != 0) { errln("FAIL: Wrong locale ID - %s %s %s", loc.getName(), @@ -248,6 +290,9 @@ errln("Unknown test case method: There is an error in the test case data."); break; } + if (status != copyStatus) { + errln("copyErrorTo not matching"); + } if (U_FAILURE(status)) { if (strcmp("X", testCase[i]) == 0) { // This failure is expected @@ -1183,7 +1228,7 @@ errln("setExtension('u', \"%s\") got Error: %s\n", extension, u_errorName(status)); } - }; + } } void LocaleBuilderTest::TestSetExtensionValidateUIllFormed() { @@ -1319,7 +1364,7 @@ errln("setExtension('t', \"%s\") got Error: %s\n", extension, u_errorName(status)); } - }; + } } void LocaleBuilderTest::TestSetExtensionValidateTIllFormed() { @@ -1424,7 +1469,7 @@ errln("setExtension('x', \"%s\") got Error: %s\n", extension, u_errorName(status)); } - }; + } } void LocaleBuilderTest::TestSetExtensionValidatePUIllFormed() { @@ -1513,7 +1558,7 @@ errln("setExtension('%c', \"%s\") got Error: %s\n", ch, extension, u_errorName(status)); } - }; + } const char* someChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()-_=+;:,.<>?"; diff -Nru icu-64.2/source/test/intltest/localematchertest.cpp icu-65.1/source/test/intltest/localematchertest.cpp --- icu-64.2/source/test/intltest/localematchertest.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/intltest/localematchertest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,589 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localematchertest.cpp +// created: 2019jul04 Markus W. Scherer + +#include +#include + +#include "unicode/utypes.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "charstr.h" +#include "cmemory.h" +#include "intltest.h" +#include "localeprioritylist.h" +#include "ucbuf.h" + +#define ARRAY_RANGE(array) (array), ((array) + UPRV_LENGTHOF(array)) + +namespace { + +const char *locString(const Locale *loc) { + return loc != nullptr ? loc->getName() : "(null)"; +} + +struct TestCase { + int32_t lineNr = 0; + + CharString supported; + CharString def; + UnicodeString favor; + UnicodeString threshold; + CharString desired; + CharString expMatch; + CharString expDesired; + CharString expCombined; + + void reset() { + supported.clear(); + def.clear(); + favor.remove(); + threshold.remove(); + } +}; + +} // namespace + +class LocaleMatcherTest : public IntlTest { +public: + LocaleMatcherTest() {} + + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=NULL); + + void testEmpty(); + void testCopyErrorTo(); + void testBasics(); + void testSupportedDefault(); + void testUnsupportedDefault(); + void testDemotion(); + void testMatch(); + void testResolvedLocale(); + void testDataDriven(); + +private: + UBool dataDriven(const TestCase &test, IcuTestErrorCode &errorCode); +}; + +extern IntlTest *createLocaleMatcherTest() { + return new LocaleMatcherTest(); +} + +void LocaleMatcherTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) { + if(exec) { + logln("TestSuite LocaleMatcherTest: "); + } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(testEmpty); + TESTCASE_AUTO(testCopyErrorTo); + TESTCASE_AUTO(testBasics); + TESTCASE_AUTO(testSupportedDefault); + TESTCASE_AUTO(testUnsupportedDefault); + TESTCASE_AUTO(testDemotion); + TESTCASE_AUTO(testMatch); + TESTCASE_AUTO(testResolvedLocale); + TESTCASE_AUTO(testDataDriven); + TESTCASE_AUTO_END; +} + +void LocaleMatcherTest::testEmpty() { + IcuTestErrorCode errorCode(*this, "testEmpty"); + LocaleMatcher matcher = LocaleMatcher::Builder().build(errorCode); + const Locale *best = matcher.getBestMatch(Locale::getFrench(), errorCode); + assertEquals("getBestMatch(fr)", "(null)", locString(best)); + LocaleMatcher::Result result = matcher.getBestMatchResult("fr", errorCode); + assertEquals("getBestMatchResult(fr).des", "(null)", locString(result.getDesiredLocale())); + assertEquals("getBestMatchResult(fr).desIndex", -1, result.getDesiredIndex()); + assertEquals("getBestMatchResult(fr).supp", + "(null)", locString(result.getSupportedLocale())); + assertEquals("getBestMatchResult(fr).suppIndex", + -1, result.getSupportedIndex()); +} + +void LocaleMatcherTest::testCopyErrorTo() { + IcuTestErrorCode errorCode(*this, "testCopyErrorTo"); + // The builder does not set any errors except out-of-memory. + // Test what we can. + LocaleMatcher::Builder builder; + UErrorCode success = U_ZERO_ERROR; + assertFalse("no error", builder.copyErrorTo(success)); + assertTrue("still success", U_SUCCESS(success)); + UErrorCode failure = U_INVALID_FORMAT_ERROR; + assertTrue("failure passed in", builder.copyErrorTo(failure)); + assertEquals("same failure", U_INVALID_FORMAT_ERROR, failure); +} + +void LocaleMatcherTest::testBasics() { + IcuTestErrorCode errorCode(*this, "testBasics"); + Locale locales[] = { "fr", "en_GB", "en" }; + { + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocales(ARRAY_RANGE(locales)).build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("fromRange.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("fromRange.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("fromRange.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("fromRange.getBestMatch(ja_JP)", "fr", locString(best)); + } + // Code coverage: Variations of setting supported locales. + { + std::vector locales{ "fr", "en_GB", "en" }; + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocales(locales.begin(), locales.end()).build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("fromRange.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("fromRange.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("fromRange.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("fromRange.getBestMatch(ja_JP)", "fr", locString(best)); + } + { + Locale::RangeIterator iter(ARRAY_RANGE(locales)); + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocales(iter).build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("fromIter.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("fromIter.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("fromIter.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("fromIter.getBestMatch(ja_JP)", "fr", locString(best)); + } + { + Locale *pointers[] = { locales, locales + 1, locales + 2 }; + // Lambda with explicit reference return type to prevent copy-constructing a temporary + // which would be destructed right away. + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocalesViaConverter( + ARRAY_RANGE(pointers), [](const Locale *p) -> const Locale & { return *p; }). + build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("viaConverter.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("viaConverter.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("viaConverter.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("viaConverter.getBestMatch(ja_JP)", "fr", locString(best)); + } + { + LocaleMatcher matcher = LocaleMatcher::Builder(). + addSupportedLocale(locales[0]). + addSupportedLocale(locales[1]). + addSupportedLocale(locales[2]). + build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("added.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("added.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("added.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("added.getBestMatch(ja_JP)", "fr", locString(best)); + } + { + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocalesFromListString( + " el, fr;q=0.555555, en-GB ; q = 0.88 , el; q =0, en;q=0.88 , fr "). + build(errorCode); + const Locale *best = matcher.getBestMatchForListString("el, fr, fr;q=0, en-GB", errorCode); + assertEquals("fromList.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("fromList.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("fromList.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("fromList.getBestMatch(ja_JP)", "fr", locString(best)); + } + // more API coverage + { + LocalePriorityList list("fr, en-GB", errorCode); + LocalePriorityList::Iterator iter(list.iterator()); + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocales(iter). + addSupportedLocale(Locale::getEnglish()). + setDefaultLocale(&Locale::getGerman()). + build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("withDefault.getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("withDefault.getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("withDefault.getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("withDefault.getBestMatch(ja_JP)", "de", locString(best)); + + Locale desired("en_GB"); // distinct object from Locale.UK + LocaleMatcher::Result result = matcher.getBestMatchResult(desired, errorCode); + assertTrue("withDefault: exactly desired en-GB object", + &desired == result.getDesiredLocale()); + assertEquals("withDefault: en-GB desired index", 0, result.getDesiredIndex()); + assertEquals("withDefault: en-GB supported", + "en_GB", locString(result.getSupportedLocale())); + assertEquals("withDefault: en-GB supported index", 1, result.getSupportedIndex()); + + LocalePriorityList list2("ja-JP, en-US", errorCode); + LocalePriorityList::Iterator iter2(list2.iterator()); + result = matcher.getBestMatchResult(iter2, errorCode); + assertEquals("withDefault: ja-JP, en-US desired index", 1, result.getDesiredIndex()); + assertEquals("withDefault: ja-JP, en-US desired", + "en_US", locString(result.getDesiredLocale())); + + desired = Locale("en", "US"); // distinct object from Locale.US + result = matcher.getBestMatchResult(desired, errorCode); + assertTrue("withDefault: exactly desired en-US object", + &desired == result.getDesiredLocale()); + assertEquals("withDefault: en-US desired index", 0, result.getDesiredIndex()); + assertEquals("withDefault: en-US supported", "en", locString(result.getSupportedLocale())); + assertEquals("withDefault: en-US supported index", 2, result.getSupportedIndex()); + + result = matcher.getBestMatchResult("ja_JP", errorCode); + assertEquals("withDefault: ja-JP desired", "(null)", locString(result.getDesiredLocale())); + assertEquals("withDefault: ja-JP desired index", -1, result.getDesiredIndex()); + assertEquals("withDefault: ja-JP supported", "de", locString(result.getSupportedLocale())); + assertEquals("withDefault: ja-JP supported index", -1, result.getSupportedIndex()); + } +} + +void LocaleMatcherTest::testSupportedDefault() { + // The default locale is one of the supported locales. + IcuTestErrorCode errorCode(*this, "testSupportedDefault"); + Locale locales[] = { "fr", "en_GB", "en" }; + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocales(ARRAY_RANGE(locales)). + setDefaultLocale(&locales[1]). + build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("getBestMatch(ja_JP)", "en_GB", locString(best)); + LocaleMatcher::Result result = matcher.getBestMatchResult("ja_JP", errorCode); + assertEquals("getBestMatchResult(ja_JP).supp", + "en_GB", locString(result.getSupportedLocale())); + assertEquals("getBestMatchResult(ja_JP).suppIndex", + 1, result.getSupportedIndex()); +} + +void LocaleMatcherTest::testUnsupportedDefault() { + // The default locale does not match any of the supported locales. + IcuTestErrorCode errorCode(*this, "testUnsupportedDefault"); + Locale locales[] = { "fr", "en_GB", "en" }; + Locale def("de"); + LocaleMatcher matcher = LocaleMatcher::Builder(). + setSupportedLocales(ARRAY_RANGE(locales)). + setDefaultLocale(&def). + build(errorCode); + const Locale *best = matcher.getBestMatch("en_GB", errorCode); + assertEquals("getBestMatch(en_GB)", "en_GB", locString(best)); + best = matcher.getBestMatch("en_US", errorCode); + assertEquals("getBestMatch(en_US)", "en", locString(best)); + best = matcher.getBestMatch("fr_FR", errorCode); + assertEquals("getBestMatch(fr_FR)", "fr", locString(best)); + best = matcher.getBestMatch("ja_JP", errorCode); + assertEquals("getBestMatch(ja_JP)", "de", locString(best)); + LocaleMatcher::Result result = matcher.getBestMatchResult("ja_JP", errorCode); + assertEquals("getBestMatchResult(ja_JP).supp", + "de", locString(result.getSupportedLocale())); + assertEquals("getBestMatchResult(ja_JP).suppIndex", + -1, result.getSupportedIndex()); +} + +void LocaleMatcherTest::testDemotion() { + IcuTestErrorCode errorCode(*this, "testDemotion"); + Locale supported[] = { "fr", "de-CH", "it" }; + Locale desired[] = { "fr-CH", "de-CH", "it" }; + { + LocaleMatcher noDemotion = LocaleMatcher::Builder(). + setSupportedLocales(ARRAY_RANGE(supported)). + setDemotionPerDesiredLocale(ULOCMATCH_DEMOTION_NONE).build(errorCode); + Locale::RangeIterator desiredIter(ARRAY_RANGE(desired)); + assertEquals("no demotion", + "de_CH", locString(noDemotion.getBestMatch(desiredIter, errorCode))); + } + + { + LocaleMatcher regionDemotion = LocaleMatcher::Builder(). + setSupportedLocales(ARRAY_RANGE(supported)). + setDemotionPerDesiredLocale(ULOCMATCH_DEMOTION_REGION).build(errorCode); + Locale::RangeIterator desiredIter(ARRAY_RANGE(desired)); + assertEquals("region demotion", + "fr", locString(regionDemotion.getBestMatch(desiredIter, errorCode))); + } +} + +void LocaleMatcherTest::testMatch() { + IcuTestErrorCode errorCode(*this, "testMatch"); + LocaleMatcher matcher = LocaleMatcher::Builder().build(errorCode); + + // Java test function testMatch_exact() + Locale en_CA("en_CA"); + assertEquals("exact match", 1.0, matcher.internalMatch(en_CA, en_CA, errorCode)); + + // testMatch_none + Locale ar_MK("ar_MK"); + double match = matcher.internalMatch(ar_MK, en_CA, errorCode); + assertTrue("mismatch: 0<=match<0.2", 0 <= match && match < 0.2); + + // testMatch_matchOnMaximized + Locale und_TW("und_TW"); + Locale zh("zh"); + Locale zh_Hant("zh_Hant"); + double matchZh = matcher.internalMatch(und_TW, zh, errorCode); + double matchZhHant = matcher.internalMatch(und_TW, zh_Hant, errorCode); + assertTrue("und_TW should be closer to zh_Hant than to zh", + matchZh < matchZhHant); + Locale en_Hant_TW("en_Hant_TW"); + double matchEnHantTw = matcher.internalMatch(en_Hant_TW, zh_Hant, errorCode); + assertTrue("zh_Hant should be closer to und_TW than to en_Hant_TW", + matchEnHantTw < matchZhHant); + assertTrue("zh should be closer to und_TW than to en_Hant_TW", + matchEnHantTw < matchZh); +} + +void LocaleMatcherTest::testResolvedLocale() { + IcuTestErrorCode errorCode(*this, "testResolvedLocale"); + LocaleMatcher matcher = LocaleMatcher::Builder(). + addSupportedLocale("ar-EG"). + build(errorCode); + Locale desired("ar-SA-u-nu-latn"); + LocaleMatcher::Result result = matcher.getBestMatchResult(desired, errorCode); + assertEquals("best", "ar_EG", locString(result.getSupportedLocale())); + Locale resolved = result.makeResolvedLocale(errorCode); + assertEquals("ar-EG + ar-SA-u-nu-latn = ar-SA-u-nu-latn", + "ar-SA-u-nu-latn", + resolved.toLanguageTag(errorCode).data()); +} + +namespace { + +bool toInvariant(const UnicodeString &s, CharString &inv, ErrorCode &errorCode) { + if (errorCode.isSuccess()) { + inv.clear().appendInvariantChars(s, errorCode); + return errorCode.isSuccess(); + } + return false; +} + +bool getSuffixAfterPrefix(const UnicodeString &s, int32_t limit, + const UnicodeString &prefix, UnicodeString &suffix) { + if (prefix.length() <= limit && s.startsWith(prefix)) { + suffix.setTo(s, prefix.length(), limit - prefix.length()); + return true; + } else { + return false; + } +} + +bool getInvariantSuffixAfterPrefix(const UnicodeString &s, int32_t limit, + const UnicodeString &prefix, CharString &suffix, + ErrorCode &errorCode) { + UnicodeString u_suffix; + return getSuffixAfterPrefix(s, limit, prefix, u_suffix) && + toInvariant(u_suffix, suffix, errorCode); +} + +bool readTestCase(const UnicodeString &line, TestCase &test, IcuTestErrorCode &errorCode) { + if (errorCode.isFailure()) { return false; } + ++test.lineNr; + // Start of comment, or end of line, minus trailing spaces. + int32_t limit = line.indexOf(u'#'); + if (limit < 0) { + limit = line.length(); + // Remove trailing CR LF. + char16_t c; + while (limit > 0 && ((c = line.charAt(limit - 1)) == u'\n' || c == u'\r')) { + --limit; + } + } + // Remove spaces before comment or at the end of the line. + char16_t c; + while (limit > 0 && ((c = line.charAt(limit - 1)) == u' ' || c == u'\t')) { + --limit; + } + if (limit == 0) { // empty line + return false; + } + if (line.startsWith(u"** test: ")) { + test.reset(); + } else if (getInvariantSuffixAfterPrefix(line, limit, u"@supported=", + test.supported, errorCode)) { + } else if (getInvariantSuffixAfterPrefix(line, limit, u"@default=", + test.def, errorCode)) { + } else if (getSuffixAfterPrefix(line, limit, u"@favor=", test.favor)) { + } else if (getSuffixAfterPrefix(line, limit, u"@threshold=", test.threshold)) { + } else { + int32_t matchSep = line.indexOf(u">>"); + // >> before an inline comment, and followed by more than white space. + if (0 <= matchSep && (matchSep + 2) < limit) { + toInvariant(line.tempSubStringBetween(0, matchSep).trim(), test.desired, errorCode); + test.expDesired.clear(); + test.expCombined.clear(); + int32_t start = matchSep + 2; + int32_t expLimit = line.indexOf(u'|', start); + if (expLimit < 0) { + toInvariant(line.tempSubStringBetween(start, limit).trim(), + test.expMatch, errorCode); + } else { + toInvariant(line.tempSubStringBetween(start, expLimit).trim(), + test.expMatch, errorCode); + start = expLimit + 1; + expLimit = line.indexOf(u'|', start); + if (expLimit < 0) { + toInvariant(line.tempSubStringBetween(start, limit).trim(), + test.expDesired, errorCode); + } else { + toInvariant(line.tempSubStringBetween(start, expLimit).trim(), + test.expDesired, errorCode); + toInvariant(line.tempSubStringBetween(expLimit + 1, limit).trim(), + test.expCombined, errorCode); + } + } + return errorCode.isSuccess(); + } else { + errorCode.set(U_INVALID_FORMAT_ERROR); + } + } + return false; +} + +Locale *getLocaleOrNull(const CharString &s, Locale &locale) { + if (s == "null") { + return nullptr; + } else { + return &(locale = Locale(s.data())); + } +} + +} // namespace + +UBool LocaleMatcherTest::dataDriven(const TestCase &test, IcuTestErrorCode &errorCode) { + LocaleMatcher::Builder builder; + builder.setSupportedLocalesFromListString(test.supported.toStringPiece()); + if (!test.def.isEmpty()) { + Locale defaultLocale(test.def.data()); + builder.setDefaultLocale(&defaultLocale); + } + if (!test.favor.isEmpty()) { + ULocMatchFavorSubtag favor; + if (test.favor == u"normal") { + favor = ULOCMATCH_FAVOR_LANGUAGE; + } else if (test.favor == u"script") { + favor = ULOCMATCH_FAVOR_SCRIPT; + } else { + errln(UnicodeString(u"unsupported FavorSubtag value ") + test.favor); + return FALSE; + } + builder.setFavorSubtag(favor); + } + if (!test.threshold.isEmpty()) { + infoln("skipping test case on line %d with non-default threshold: not exposed via API", + (int)test.lineNr); + return TRUE; + // int32_t threshold = Integer.valueOf(test.threshold); + // builder.internalSetThresholdDistance(threshold); + } + LocaleMatcher matcher = builder.build(errorCode); + if (errorCode.errIfFailureAndReset("LocaleMatcher::Builder::build()")) { + return FALSE; + } + + Locale expMatchLocale(""); + Locale *expMatch = getLocaleOrNull(test.expMatch, expMatchLocale); + if (test.expDesired.isEmpty() && test.expCombined.isEmpty()) { + StringPiece desiredSP = test.desired.toStringPiece(); + const Locale *bestSupported = matcher.getBestMatchForListString(desiredSP, errorCode); + if (!assertEquals("bestSupported from string", + locString(expMatch), locString(bestSupported))) { + return FALSE; + } + LocalePriorityList desired(test.desired.toStringPiece(), errorCode); + LocalePriorityList::Iterator desiredIter = desired.iterator(); + if (desired.getLength() == 1) { + const Locale &desiredLocale = desiredIter.next(); + bestSupported = matcher.getBestMatch(desiredLocale, errorCode); + UBool ok = assertEquals("bestSupported from Locale", + locString(expMatch), locString(bestSupported)); + + LocaleMatcher::Result result = matcher.getBestMatchResult(desiredLocale, errorCode); + return ok & assertEquals("result.getSupportedLocale from Locale", + locString(expMatch), locString(result.getSupportedLocale())); + } else { + bestSupported = matcher.getBestMatch(desiredIter, errorCode); + return assertEquals("bestSupported from Locale iterator", + locString(expMatch), locString(bestSupported)); + } + } else { + LocalePriorityList desired(test.desired.toStringPiece(), errorCode); + LocalePriorityList::Iterator desiredIter = desired.iterator(); + LocaleMatcher::Result result = matcher.getBestMatchResult(desiredIter, errorCode); + UBool ok = assertEquals("result.getSupportedLocale from Locales", + locString(expMatch), locString(result.getSupportedLocale())); + if (!test.expDesired.isEmpty()) { + Locale expDesiredLocale(""); + Locale *expDesired = getLocaleOrNull(test.expDesired, expDesiredLocale); + ok &= assertEquals("result.getDesiredLocale from Locales", + locString(expDesired), locString(result.getDesiredLocale())); + } + if (!test.expCombined.isEmpty()) { + if (test.expMatch.contains("-u-")) { + logKnownIssue("20727", + UnicodeString(u"ignoring makeResolvedLocale() line ") + test.lineNr); + return ok; + } + Locale expCombinedLocale(""); + Locale *expCombined = getLocaleOrNull(test.expCombined, expCombinedLocale); + Locale combined = result.makeResolvedLocale(errorCode); + ok &= assertEquals("combined Locale from Locales", + locString(expCombined), locString(&combined)); + } + return ok; + } +} + +void LocaleMatcherTest::testDataDriven() { + IcuTestErrorCode errorCode(*this, "testDataDriven"); + CharString path(getSourceTestData(errorCode), errorCode); + path.appendPathPart("localeMatcherTest.txt", errorCode); + const char *codePage = "UTF-8"; + LocalUCHARBUFPointer f(ucbuf_open(path.data(), &codePage, TRUE, FALSE, errorCode)); + if(errorCode.errIfFailureAndReset("ucbuf_open(localeMatcherTest.txt)")) { + return; + } + int32_t lineLength; + const UChar *p; + UnicodeString line; + TestCase test; + int32_t numPassed = 0; + while ((p = ucbuf_readline(f.getAlias(), &lineLength, errorCode)) != nullptr && + errorCode.isSuccess()) { + line.setTo(FALSE, p, lineLength); + if (!readTestCase(line, test, errorCode)) { + if (errorCode.errIfFailureAndReset( + "test data syntax error on line %d", (int)test.lineNr)) { + infoln(line); + } + continue; + } + UBool ok = dataDriven(test, errorCode); + if (errorCode.errIfFailureAndReset("test error on line %d", (int)test.lineNr)) { + infoln(line); + } else if (!ok) { + infoln("test failure on line %d", (int)test.lineNr); + infoln(line); + } else { + ++numPassed; + } + } + infoln("number of passing test cases: %d", (int)numPassed); +} diff -Nru icu-64.2/source/test/intltest/locnmtst.cpp icu-65.1/source/test/intltest/locnmtst.cpp --- icu-64.2/source/test/intltest/locnmtst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/locnmtst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -20,13 +20,12 @@ the macro is ugly but makes the tests pretty. */ -#define test_assert(test) \ - { \ - if(!(test)) \ - errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \ - else \ - logln("PASS: asserted " #test); \ - } +#define test_assert(test) UPRV_BLOCK_MACRO_BEGIN { \ + if(!(test)) \ + errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \ + else \ + logln("PASS: asserted " #test); \ +} UPRV_BLOCK_MACRO_END /* Usage: @@ -38,25 +37,25 @@ the macro is ugly but makes the tests pretty. */ -#define test_assert_print(test,print) \ - { \ - if(!(test)) \ - errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \ - else \ - logln("PASS: asserted " #test "-> " + UnicodeString(print)); \ - } +#define test_assert_print(test,print) UPRV_BLOCK_MACRO_BEGIN { \ + if(!(test)) \ + errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \ + else \ + logln("PASS: asserted " #test "-> " + UnicodeString(print)); \ +} UPRV_BLOCK_MACRO_END -#define test_assert_equal(target,value) \ - { \ +#define test_assert_equal(target,value) UPRV_BLOCK_MACRO_BEGIN { \ if (UnicodeString(target)!=(value)) { \ - logln("unexpected value '" + (value) + "'"); \ - dataerrln("FAIL: " #target " == " #value " was not true. In " __FILE__ " on line %d", __LINE__); \ + logln("unexpected value '" + (value) + "'"); \ + dataerrln("FAIL: " #target " == " #value " was not true. In " __FILE__ " on line %d", __LINE__); \ } else { \ - logln("PASS: asserted " #target " == " #value); \ + logln("PASS: asserted " #target " == " #value); \ } \ - } +} UPRV_BLOCK_MACRO_END -#define test_dumpLocale(l) { logln(#l " = " + UnicodeString(l.getName(), "")); } +#define test_dumpLocale(l) UPRV_BLOCK_MACRO_BEGIN { \ + logln(#l " = " + UnicodeString(l.getName(), "")); \ +} UPRV_BLOCK_MACRO_END LocaleDisplayNamesTest::LocaleDisplayNamesTest() { } @@ -82,6 +81,7 @@ TESTCASE(11, TestPrivateUse); TESTCASE(12, TestUldnDisplayContext); TESTCASE(13, TestUldnWithGarbage); + TESTCASE(14, TestSubstituteHandling); #endif default: name = ""; @@ -422,4 +422,161 @@ delete ldn; } +static const char unknown_region[] = "wx"; +static const char unknown_lang[] = "xy"; +static const char unknown_script[] = "wxyz"; +static const char unknown_variant[] = "abc"; +static const char unknown_key[] = "efg"; +static const char unknown_ca_value[] = "ijk"; +static const char known_lang_unknown_script[] = "en-wxyz"; +static const char unknown_lang_unknown_script[] = "xy-wxyz"; +static const char unknown_lang_known_script[] = "xy-Latn"; +static const char unknown_lang_unknown_region[] = "xy-wx"; +static const char known_lang_unknown_region[] = "en-wx"; +static const char unknown_lang_known_region[] = "xy-US"; +static const char unknown_lang_unknown_script_unknown_region[] = "xy-wxyz-wx"; +static const char known_lang_unknown_script_unknown_region[] = "en-wxyz-wx"; +static const char unknown_lang_known_script_unknown_region[] = "xy-Latn-wx"; +static const char unknown_lang_known_script_known_region[] = "xy-wxyz-US"; +static const char known_lang[] = "en"; +static const char known_lang_known_script[] = "en-Latn"; +static const char known_lang_known_region[] = "en-US"; +static const char known_lang_known_script_known_region[] = "en-Latn-US"; + +void LocaleDisplayNamesTest::VerifySubstitute(LocaleDisplayNames* ldn) { + UnicodeString temp; + // Ensure the default is UDISPCTX_SUBSTITUTE + UDisplayContext context = ldn->getContext(UDISPCTX_TYPE_SUBSTITUTE_HANDLING); + test_assert(UDISPCTX_SUBSTITUTE == context); + + ldn->regionDisplayName(unknown_region, temp); + test_assert_equal(unknown_region, temp); + ldn->languageDisplayName(unknown_lang, temp); + test_assert_equal(unknown_lang, temp); + ldn->scriptDisplayName(unknown_script, temp); + test_assert_equal(unknown_script, temp); + ldn->variantDisplayName(unknown_variant, temp); + test_assert_equal(unknown_variant, temp); + ldn->keyDisplayName(unknown_key, temp); + test_assert_equal(unknown_key, temp); + ldn->keyValueDisplayName("ca", unknown_ca_value, temp); + test_assert_equal(unknown_ca_value, temp); + + ldn->localeDisplayName(unknown_lang, temp); + test_assert_equal(unknown_lang, temp); + ldn->localeDisplayName(known_lang_unknown_script, temp); + test_assert_equal("Englisch (Wxyz)", temp); + ldn->localeDisplayName(unknown_lang_unknown_script, temp); + test_assert_equal("xy (Wxyz)", temp); + ldn->localeDisplayName(unknown_lang_known_script, temp); + test_assert_equal("xy (Lateinisch)", temp); + ldn->localeDisplayName(unknown_lang_unknown_region, temp); + test_assert_equal("xy (WX)", temp); + ldn->localeDisplayName(known_lang_unknown_region, temp); + test_assert_equal("Englisch (WX)", temp); + ldn->localeDisplayName(unknown_lang_known_region, temp); + test_assert_equal("xy (Vereinigte Staaten)", temp); + ldn->localeDisplayName(unknown_lang_unknown_script_unknown_region, temp); + test_assert_equal("xy (Wxyz, WX)", temp); + ldn->localeDisplayName(known_lang_unknown_script_unknown_region, temp); + test_assert_equal("Englisch (Wxyz, WX)", temp); + ldn->localeDisplayName(unknown_lang_known_script_unknown_region, temp); + test_assert_equal("xy (Lateinisch, WX)", temp); + ldn->localeDisplayName(unknown_lang_known_script_known_region, temp); + test_assert_equal("xy (Wxyz, Vereinigte Staaten)", temp); + + ldn->localeDisplayName(known_lang, temp); + test_assert_equal("Englisch", temp); + ldn->localeDisplayName(known_lang_known_script, temp); + test_assert_equal("Englisch (Lateinisch)", temp); + ldn->localeDisplayName(known_lang_known_region, temp); + test_assert_equal("Englisch (Vereinigte Staaten)", temp); + ldn->localeDisplayName(known_lang_known_script_known_region, temp); + test_assert_equal("Englisch (Lateinisch, Vereinigte Staaten)", temp); +} + +void LocaleDisplayNamesTest::VerifyNoSubstitute(LocaleDisplayNames* ldn) { + UnicodeString temp(""); + std::string utf8; + // Ensure the default is UDISPCTX_SUBSTITUTE + UDisplayContext context = ldn->getContext(UDISPCTX_TYPE_SUBSTITUTE_HANDLING); + test_assert(UDISPCTX_NO_SUBSTITUTE == context); + + ldn->regionDisplayName(unknown_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->languageDisplayName(unknown_lang, temp); + test_assert(TRUE == temp.isBogus()); + ldn->scriptDisplayName(unknown_script, temp); + test_assert(TRUE == temp.isBogus()); + ldn->variantDisplayName(unknown_variant, temp); + test_assert(TRUE == temp.isBogus()); + ldn->keyDisplayName(unknown_key, temp); + test_assert(TRUE == temp.isBogus()); + ldn->keyValueDisplayName("ca", unknown_ca_value, temp); + test_assert(TRUE == temp.isBogus()); + + ldn->localeDisplayName(unknown_lang, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(known_lang_unknown_script, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_unknown_script, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_known_script, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_unknown_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(known_lang_unknown_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_known_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_unknown_script_unknown_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(known_lang_unknown_script_unknown_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_known_script_unknown_region, temp); + test_assert(TRUE == temp.isBogus()); + ldn->localeDisplayName(unknown_lang_known_script_known_region, temp); + test_assert(TRUE == temp.isBogus()); + + ldn->localeDisplayName(known_lang, temp); + test_assert_equal("Englisch", temp); + ldn->localeDisplayName(known_lang_known_script, temp); + test_assert_equal("Englisch (Lateinisch)", temp); + ldn->localeDisplayName(known_lang_known_region, temp); + test_assert_equal("Englisch (Vereinigte Staaten)", temp); + ldn->localeDisplayName(known_lang_known_script_known_region, temp); + test_assert_equal("Englisch (Lateinisch, Vereinigte Staaten)", temp); +} + +void LocaleDisplayNamesTest::TestSubstituteHandling() { + // With substitute as default + logln("Context: none\n"); + std::unique_ptr ldn(LocaleDisplayNames::createInstance(Locale::getGermany())); + VerifySubstitute(ldn.get()); + + // With explicit set substitute, and standard names + logln("Context: UDISPCTX_SUBSTITUTE, UDISPCTX_STANDARD_NAMES\n"); + UDisplayContext context_1[] = { UDISPCTX_SUBSTITUTE, UDISPCTX_STANDARD_NAMES }; + ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_1, 2)); + VerifySubstitute(ldn.get()); + + // With explicit set substitute and dialect names + logln("Context: UDISPCTX_SUBSTITUTE, UDISPCTX_DIALECT_NAMES\n"); + UDisplayContext context_2[] = { UDISPCTX_SUBSTITUTE, UDISPCTX_DIALECT_NAMES }; + ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_2, 2)); + VerifySubstitute(ldn.get()); + + // With explicit set no_substitute, and standard names + logln("Context: UDISPCTX_NO_SUBSTITUTE, UDISPCTX_STANDARD_NAMES\n"); + UDisplayContext context_3[] = { UDISPCTX_NO_SUBSTITUTE, UDISPCTX_STANDARD_NAMES }; + ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_3, 2)); + VerifyNoSubstitute(ldn.get()); + + // With explicit set no_substitute and dialect names + logln("Context: UDISPCTX_NO_SUBSTITUTE, UDISPCTX_DIALECT_NAMES\n"); + UDisplayContext context_4[] = { UDISPCTX_NO_SUBSTITUTE, UDISPCTX_DIALECT_NAMES }; + ldn.reset(LocaleDisplayNames::createInstance(Locale::getGermany(), context_4, 2)); + VerifyNoSubstitute(ldn.get()); +} + #endif /* UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/locnmtst.h icu-65.1/source/test/intltest/locnmtst.h --- icu-64.2/source/test/intltest/locnmtst.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/locnmtst.h 2019-10-03 11:16:41.000000000 +0000 @@ -37,5 +37,10 @@ void TestPrivateUse(void); void TestUldnDisplayContext(void); void TestUldnWithGarbage(void); + void TestSubstituteHandling(void); + + void VerifySubstitute(LocaleDisplayNames* ldn); + void VerifyNoSubstitute(LocaleDisplayNames* ldn); #endif + }; diff -Nru icu-64.2/source/test/intltest/loctest.cpp icu-65.1/source/test/intltest/loctest.cpp --- icu-64.2/source/test/intltest/loctest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/loctest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -6,6 +6,7 @@ * others. All Rights Reserved. ********************************************************************/ +#include #include #include #include @@ -146,13 +147,12 @@ the macro is ugly but makes the tests pretty. */ -#define test_assert(test) \ - { \ - if(!(test)) \ - errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \ - else \ - logln("PASS: asserted " #test); \ - } +#define test_assert(test) UPRV_BLOCK_MACRO_BEGIN { \ + if(!(test)) \ + errln("FAIL: " #test " was not true. In " __FILE__ " on line %d", __LINE__ ); \ + else \ + logln("PASS: asserted " #test); \ +} UPRV_BLOCK_MACRO_END /* Usage: @@ -164,16 +164,17 @@ the macro is ugly but makes the tests pretty. */ -#define test_assert_print(test,print) \ - { \ - if(!(test)) \ - errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \ - else \ - logln("PASS: asserted " #test "-> " + UnicodeString(print)); \ - } +#define test_assert_print(test,print) UPRV_BLOCK_MACRO_BEGIN { \ + if(!(test)) \ + errln("FAIL: " #test " was not true. " + UnicodeString(print) ); \ + else \ + logln("PASS: asserted " #test "-> " + UnicodeString(print)); \ +} UPRV_BLOCK_MACRO_END -#define test_dumpLocale(l) { logln(#l " = " + UnicodeString(l.getName(), "")); } +#define test_dumpLocale(l) UPRV_BLOCK_MACRO_BEGIN { \ + logln(#l " = " + UnicodeString(l.getName(), "")); \ +} UPRV_BLOCK_MACRO_END LocaleTest::LocaleTest() : dataTable(NULL) @@ -221,6 +222,7 @@ TESTCASE_AUTO(Test4147317); TESTCASE_AUTO(Test4147552); TESTCASE_AUTO(TestVariantParsing); + TESTCASE_AUTO(Test20639_DeprecatesISO3Language); #if !UCONFIG_NO_FORMATTING TESTCASE_AUTO(Test4105828); #endif @@ -233,7 +235,9 @@ TESTCASE_AUTO(TestCreateUnicodeKeywords); TESTCASE_AUTO(TestKeywordVariantParsing); TESTCASE_AUTO(TestCreateKeywordSet); + TESTCASE_AUTO(TestCreateKeywordSetEmpty); TESTCASE_AUTO(TestCreateUnicodeKeywordSet); + TESTCASE_AUTO(TestCreateUnicodeKeywordSetEmpty); TESTCASE_AUTO(TestGetKeywordValueStdString); TESTCASE_AUTO(TestGetUnicodeKeywordValueStdString); TESTCASE_AUTO(TestSetKeywordValue); @@ -251,6 +255,7 @@ TESTCASE_AUTO(TestBug13277); TESTCASE_AUTO(TestBug13554); TESTCASE_AUTO(TestBug20410); + TESTCASE_AUTO(TestConstructorAcceptsBCP47); TESTCASE_AUTO(TestForLanguageTag); TESTCASE_AUTO(TestToLanguageTag); TESTCASE_AUTO(TestMoveAssign); @@ -262,6 +267,10 @@ TESTCASE_AUTO(TestUndScript); TESTCASE_AUTO(TestUndRegion); TESTCASE_AUTO(TestUndCAPI); + TESTCASE_AUTO(TestRangeIterator); + TESTCASE_AUTO(TestPointerConvertingIterator); + TESTCASE_AUTO(TestTagConvertingIterator); + TESTCASE_AUTO(TestCapturingTagConvertingIterator); TESTCASE_AUTO_END; } @@ -898,8 +907,8 @@ ; /* TODO: Change this test to be more like the cloctst version? */ - if (testCount != 595) - errln("Expected getISOLanguages() to return 595 languages; it returned %d", testCount); + if (testCount != 596) + errln("Expected getISOLanguages() to return 596 languages; it returned %d", testCount); else { for (i = 0; i < 15; i++) { int32_t j; @@ -1574,6 +1583,27 @@ } } +void LocaleTest::Test20639_DeprecatesISO3Language() { + IcuTestErrorCode status(*this, "Test20639_DeprecatesISO3Language"); + + const struct TestCase { + const char* localeName; + const char* expectedISO3Language; + } cases[] = { + {"nb", "nob"}, + {"no", "nor"}, // why not nob? + {"he", "heb"}, + {"iw", "heb"}, + {"ro", "ron"}, + {"mo", "mol"}, + }; + for (auto& cas : cases) { + Locale loc(cas.localeName); + const char* actual = loc.getISO3Language(); + assertEquals(cas.localeName, cas.expectedISO3Language, actual); + } +} + #if !UCONFIG_NO_FORMATTING /** @@ -1913,6 +1943,21 @@ } void +LocaleTest::TestCreateKeywordSetEmpty(void) { + IcuTestErrorCode status(*this, "TestCreateKeywordSetEmpty()"); + + static const Locale l("de"); + + std::set result; + l.getKeywords( + std::insert_iterator(result, result.begin()), + status); + status.errIfFailureAndReset("\"%s\"", l.getName()); + + assertEquals("set::size()", 0, static_cast(result.size())); +} + +void LocaleTest::TestCreateUnicodeKeywordSet(void) { IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSet()"); @@ -1932,6 +1977,21 @@ } void +LocaleTest::TestCreateUnicodeKeywordSetEmpty(void) { + IcuTestErrorCode status(*this, "TestCreateUnicodeKeywordSetEmpty()"); + + static const Locale l("de"); + + std::set result; + l.getUnicodeKeywords( + std::insert_iterator(result, result.begin()), + status); + status.errIfFailureAndReset("\"%s\"", l.getName()); + + assertEquals("set::size()", 0, static_cast(result.size())); +} + +void LocaleTest::TestGetKeywordValueStdString(void) { IcuTestErrorCode status(*this, "TestGetKeywordValueStdString()"); @@ -2640,7 +2700,7 @@ #if !UCONFIG_NO_FORMATTING UErrorCode status = U_ZERO_ERROR; UDate date = uprv_getUTCtime(); - UChar TMP[4]; + UChar TMP[4] = {0, 0, 0, 0}; int32_t index = 0; int32_t resLen = 0; UnicodeString tempStr, resultStr; @@ -3046,6 +3106,45 @@ assertEquals(locid4, expected4.getName(), result4.getName()); } +void LocaleTest::TestConstructorAcceptsBCP47() { + IcuTestErrorCode status(*this, "TestConstructorAcceptsBCP47"); + + Locale loc1("ar-EG-u-nu-latn"); + Locale loc2("ar-EG@numbers=latn"); + Locale loc3("ar-EG"); + std::string val; + + // Check getKeywordValue "numbers" + val = loc1.getKeywordValue("numbers", status); + assertEquals("BCP47 syntax has ICU keyword value", "latn", val.c_str()); + + val = loc2.getKeywordValue("numbers", status); + assertEquals("ICU syntax has ICU keyword value", "latn", val.c_str()); + + val = loc3.getKeywordValue("numbers", status); + assertEquals("Default, ICU keyword", "", val.c_str()); + + // Check getUnicodeKeywordValue "nu" + val = loc1.getUnicodeKeywordValue("nu", status); + assertEquals("BCP47 syntax has short unicode keyword value", "latn", val.c_str()); + + val = loc2.getUnicodeKeywordValue("nu", status); + assertEquals("ICU syntax has short unicode keyword value", "latn", val.c_str()); + + val = loc3.getUnicodeKeywordValue("nu", status); + status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, short unicode keyword"); + + // Check getUnicodeKeywordValue "numbers" + val = loc1.getUnicodeKeywordValue("numbers", status); + assertEquals("BCP47 syntax has long unicode keyword value", "latn", val.c_str()); + + val = loc2.getUnicodeKeywordValue("numbers", status); + assertEquals("ICU syntax has long unicode keyword value", "latn", val.c_str()); + + val = loc3.getUnicodeKeywordValue("numbers", status); + status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default, long unicode keyword"); +} + void LocaleTest::TestForLanguageTag() { IcuTestErrorCode status(*this, "TestForLanguageTag()"); @@ -3738,3 +3837,118 @@ assertTrue("reslen >= 0", reslen >= 0); assertEquals("uloc_getLanguage()", empty, tmp); } + +#define ARRAY_RANGE(array) (array), ((array) + UPRV_LENGTHOF(array)) + +void LocaleTest::TestRangeIterator() { + IcuTestErrorCode status(*this, "TestRangeIterator"); + Locale locales[] = { "fr", "en_GB", "en" }; + Locale::RangeIterator iter(ARRAY_RANGE(locales)); + + assertTrue("0.hasNext()", iter.hasNext()); + const Locale &l0 = iter.next(); + assertEquals("0.next()", "fr", l0.getName()); + assertTrue("&0.next()", &l0 == &locales[0]); + + assertTrue("1.hasNext()", iter.hasNext()); + const Locale &l1 = iter.next(); + assertEquals("1.next()", "en_GB", l1.getName()); + assertTrue("&1.next()", &l1 == &locales[1]); + + assertTrue("2.hasNext()", iter.hasNext()); + const Locale &l2 = iter.next(); + assertEquals("2.next()", "en", l2.getName()); + assertTrue("&2.next()", &l2 == &locales[2]); + + assertFalse("3.hasNext()", iter.hasNext()); +} + +void LocaleTest::TestPointerConvertingIterator() { + IcuTestErrorCode status(*this, "TestPointerConvertingIterator"); + Locale locales[] = { "fr", "en_GB", "en" }; + Locale *pointers[] = { locales, locales + 1, locales + 2 }; + // Lambda with explicit reference return type to prevent copy-constructing a temporary + // which would be destructed right away. + Locale::ConvertingIterator> iter( + ARRAY_RANGE(pointers), [](const Locale *p) -> const Locale & { return *p; }); + + assertTrue("0.hasNext()", iter.hasNext()); + const Locale &l0 = iter.next(); + assertEquals("0.next()", "fr", l0.getName()); + assertTrue("&0.next()", &l0 == pointers[0]); + + assertTrue("1.hasNext()", iter.hasNext()); + const Locale &l1 = iter.next(); + assertEquals("1.next()", "en_GB", l1.getName()); + assertTrue("&1.next()", &l1 == pointers[1]); + + assertTrue("2.hasNext()", iter.hasNext()); + const Locale &l2 = iter.next(); + assertEquals("2.next()", "en", l2.getName()); + assertTrue("&2.next()", &l2 == pointers[2]); + + assertFalse("3.hasNext()", iter.hasNext()); +} + +namespace { + +class LocaleFromTag { +public: + LocaleFromTag() : locale(Locale::getRoot()) {} + const Locale &operator()(const char *tag) { return locale = Locale(tag); } + +private: + // Store the locale in the converter, rather than return a reference to a temporary, + // or a value which could go out of scope with the caller's reference to it. + Locale locale; +}; + +} // namespace + +void LocaleTest::TestTagConvertingIterator() { + IcuTestErrorCode status(*this, "TestTagConvertingIterator"); + const char *tags[] = { "fr", "en_GB", "en" }; + LocaleFromTag converter; + Locale::ConvertingIterator iter(ARRAY_RANGE(tags), converter); + + assertTrue("0.hasNext()", iter.hasNext()); + const Locale &l0 = iter.next(); + assertEquals("0.next()", "fr", l0.getName()); + + assertTrue("1.hasNext()", iter.hasNext()); + const Locale &l1 = iter.next(); + assertEquals("1.next()", "en_GB", l1.getName()); + + assertTrue("2.hasNext()", iter.hasNext()); + const Locale &l2 = iter.next(); + assertEquals("2.next()", "en", l2.getName()); + + assertFalse("3.hasNext()", iter.hasNext()); +} + +void LocaleTest::TestCapturingTagConvertingIterator() { + IcuTestErrorCode status(*this, "TestCapturingTagConvertingIterator"); + const char *tags[] = { "fr", "en_GB", "en" }; + // Store the converted locale in a locale variable, + // rather than return a reference to a temporary, + // or a value which could go out of scope with the caller's reference to it. + Locale locale; + // Lambda with explicit reference return type to prevent copy-constructing a temporary + // which would be destructed right away. + Locale::ConvertingIterator> iter( + ARRAY_RANGE(tags), [&](const char *tag) -> const Locale & { return locale = Locale(tag); }); + + assertTrue("0.hasNext()", iter.hasNext()); + const Locale &l0 = iter.next(); + assertEquals("0.next()", "fr", l0.getName()); + + assertTrue("1.hasNext()", iter.hasNext()); + const Locale &l1 = iter.next(); + assertEquals("1.next()", "en_GB", l1.getName()); + + assertTrue("2.hasNext()", iter.hasNext()); + const Locale &l2 = iter.next(); + assertEquals("2.next()", "en", l2.getName()); + + assertFalse("3.hasNext()", iter.hasNext()); +} diff -Nru icu-64.2/source/test/intltest/loctest.h icu-65.1/source/test/intltest/loctest.h --- icu-64.2/source/test/intltest/loctest.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/loctest.h 2019-10-03 11:16:41.000000000 +0000 @@ -69,6 +69,8 @@ void Test4147315(void); void Test4147317(void); void Test4147552(void); + + void Test20639_DeprecatesISO3Language(); void TestVariantParsing(void); @@ -79,7 +81,9 @@ /* Test getting keyword values */ void TestKeywordVariantParsing(void); void TestCreateKeywordSet(void); + void TestCreateKeywordSetEmpty(void); void TestCreateUnicodeKeywordSet(void); + void TestCreateUnicodeKeywordSetEmpty(void); void TestGetKeywordValueStdString(void); void TestGetUnicodeKeywordValueStdString(void); @@ -115,6 +119,7 @@ void TestBug13277(); void TestBug13554(); void TestBug20410(); + void TestConstructorAcceptsBCP47(); void TestAddLikelySubtags(); void TestMinimizeSubtags(); @@ -136,6 +141,10 @@ void TestUndScript(); void TestUndRegion(); void TestUndCAPI(); + void TestRangeIterator(); + void TestPointerConvertingIterator(); + void TestTagConvertingIterator(); + void TestCapturingTagConvertingIterator(); private: void _checklocs(const char* label, diff -Nru icu-64.2/source/test/intltest/Makefile.in icu-65.1/source/test/intltest/Makefile.in --- icu-64.2/source/test/intltest/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -44,7 +44,8 @@ fldset.o dadrfmt.o dadrcal.o dcfmapts.o decoll.o dtfmapts.o dtfmrgts.o dtfmtrtts.o dtfmttst.o \ dtptngts.o encoll.o escoll.o ficoll.o frcoll.o g7coll.o intltest.o \ itercoll.o itformat.o itmajor.o itutil.o jacoll.o lcukocol.o \ -loctest.o localebuildertest.o miscdtfm.o mnkytst.o msfmrgts.o nmfmapts.o nmfmtrt.o \ +loctest.o localebuildertest.o localematchertest.o \ +miscdtfm.o mnkytst.o msfmrgts.o nmfmapts.o nmfmtrt.o \ numfmtst.o numrgts.o plurults.o plurfmts.o pptest.o regcoll.o restest.o restsnew.o \ sdtfmtts.o svccoll.o tchcfmt.o selfmts.o \ tfsmalls.o tmsgfmt.o trcoll.o tscoll.o tsdate.o tsdcfmsy.o tsdtfmsy.o \ @@ -64,10 +65,10 @@ numberformattesttuple.o pluralmaptest.o \ numbertest_affixutils.o numbertest_api.o numbertest_decimalquantity.o \ numbertest_modifiers.o numbertest_patternmodifier.o numbertest_patternstring.o \ -numbertest_stringbuilder.o numbertest_stringsegment.o \ +string_segment_test.o \ numbertest_parse.o numbertest_doubleconversion.o numbertest_skeletons.o \ static_unisets_test.o numfmtdatadriventest.o numbertest_range.o erarulestest.o \ -formattedvaluetest.o +formattedvaluetest.o formatted_string_builder_test.o numbertest_permutation.o DEPS = $(OBJECTS:.o=.d) diff -Nru icu-64.2/source/test/intltest/measfmttest.cpp icu-65.1/source/test/intltest/measfmttest.cpp --- icu-64.2/source/test/intltest/measfmttest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/measfmttest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -28,6 +28,7 @@ #include "charstr.h" #include "cstr.h" #include "unicode/reldatefmt.h" +#include "unicode/rbnf.h" struct ExpectedResult { const Measure *measures; @@ -52,6 +53,7 @@ void TestCompatible59(); void TestCompatible63(); void TestCompatible64(); + void TestCompatible65(); void TestGetAvailable(); void TestExamplesInDocs(); void TestFormatPeriodEn(); @@ -75,6 +77,8 @@ void TestUnitPerUnitResolution(); void TestIndividualPluralFallback(); void Test20332_PersonUnits(); + void TestNumericTime(); + void TestNumericTimeSomeSpecialFormats(); void verifyFormat( const char *description, const MeasureFormat &fmt, @@ -152,6 +156,7 @@ TESTCASE_AUTO(TestCompatible59); TESTCASE_AUTO(TestCompatible63); TESTCASE_AUTO(TestCompatible64); + TESTCASE_AUTO(TestCompatible65); TESTCASE_AUTO(TestGetAvailable); TESTCASE_AUTO(TestExamplesInDocs); TESTCASE_AUTO(TestFormatPeriodEn); @@ -175,6 +180,8 @@ TESTCASE_AUTO(TestUnitPerUnitResolution); TESTCASE_AUTO(TestIndividualPluralFallback); TESTCASE_AUTO(Test20332_PersonUnits); + TESTCASE_AUTO(TestNumericTime); + TESTCASE_AUTO(TestNumericTimeSomeSpecialFormats); TESTCASE_AUTO_END; } @@ -1522,6 +1529,357 @@ assertSuccess("", status); } +void MeasureFormatTest::TestCompatible65() { + UErrorCode status = U_ZERO_ERROR; + LocalPointer measureUnit; + MeasureUnit measureUnitValue; + measureUnit.adoptInstead(MeasureUnit::createGForce(status)); + measureUnitValue = MeasureUnit::getGForce(); + measureUnit.adoptInstead(MeasureUnit::createMeterPerSecondSquared(status)); + measureUnitValue = MeasureUnit::getMeterPerSecondSquared(); + measureUnit.adoptInstead(MeasureUnit::createArcMinute(status)); + measureUnitValue = MeasureUnit::getArcMinute(); + measureUnit.adoptInstead(MeasureUnit::createArcSecond(status)); + measureUnitValue = MeasureUnit::getArcSecond(); + measureUnit.adoptInstead(MeasureUnit::createDegree(status)); + measureUnitValue = MeasureUnit::getDegree(); + measureUnit.adoptInstead(MeasureUnit::createRadian(status)); + measureUnitValue = MeasureUnit::getRadian(); + measureUnit.adoptInstead(MeasureUnit::createRevolutionAngle(status)); + measureUnitValue = MeasureUnit::getRevolutionAngle(); + measureUnit.adoptInstead(MeasureUnit::createAcre(status)); + measureUnitValue = MeasureUnit::getAcre(); + measureUnit.adoptInstead(MeasureUnit::createDunam(status)); + measureUnitValue = MeasureUnit::getDunam(); + measureUnit.adoptInstead(MeasureUnit::createHectare(status)); + measureUnitValue = MeasureUnit::getHectare(); + measureUnit.adoptInstead(MeasureUnit::createSquareCentimeter(status)); + measureUnitValue = MeasureUnit::getSquareCentimeter(); + measureUnit.adoptInstead(MeasureUnit::createSquareFoot(status)); + measureUnitValue = MeasureUnit::getSquareFoot(); + measureUnit.adoptInstead(MeasureUnit::createSquareInch(status)); + measureUnitValue = MeasureUnit::getSquareInch(); + measureUnit.adoptInstead(MeasureUnit::createSquareKilometer(status)); + measureUnitValue = MeasureUnit::getSquareKilometer(); + measureUnit.adoptInstead(MeasureUnit::createSquareMeter(status)); + measureUnitValue = MeasureUnit::getSquareMeter(); + measureUnit.adoptInstead(MeasureUnit::createSquareMile(status)); + measureUnitValue = MeasureUnit::getSquareMile(); + measureUnit.adoptInstead(MeasureUnit::createSquareYard(status)); + measureUnitValue = MeasureUnit::getSquareYard(); + measureUnit.adoptInstead(MeasureUnit::createKarat(status)); + measureUnitValue = MeasureUnit::getKarat(); + measureUnit.adoptInstead(MeasureUnit::createMilligramPerDeciliter(status)); + measureUnitValue = MeasureUnit::getMilligramPerDeciliter(); + measureUnit.adoptInstead(MeasureUnit::createMillimolePerLiter(status)); + measureUnitValue = MeasureUnit::getMillimolePerLiter(); + measureUnit.adoptInstead(MeasureUnit::createMole(status)); + measureUnitValue = MeasureUnit::getMole(); + measureUnit.adoptInstead(MeasureUnit::createPartPerMillion(status)); + measureUnitValue = MeasureUnit::getPartPerMillion(); + measureUnit.adoptInstead(MeasureUnit::createPercent(status)); + measureUnitValue = MeasureUnit::getPercent(); + measureUnit.adoptInstead(MeasureUnit::createPermille(status)); + measureUnitValue = MeasureUnit::getPermille(); + measureUnit.adoptInstead(MeasureUnit::createPermyriad(status)); + measureUnitValue = MeasureUnit::getPermyriad(); + measureUnit.adoptInstead(MeasureUnit::createLiterPer100Kilometers(status)); + measureUnitValue = MeasureUnit::getLiterPer100Kilometers(); + measureUnit.adoptInstead(MeasureUnit::createLiterPerKilometer(status)); + measureUnitValue = MeasureUnit::getLiterPerKilometer(); + measureUnit.adoptInstead(MeasureUnit::createMilePerGallon(status)); + measureUnitValue = MeasureUnit::getMilePerGallon(); + measureUnit.adoptInstead(MeasureUnit::createMilePerGallonImperial(status)); + measureUnitValue = MeasureUnit::getMilePerGallonImperial(); + measureUnit.adoptInstead(MeasureUnit::createBit(status)); + measureUnitValue = MeasureUnit::getBit(); + measureUnit.adoptInstead(MeasureUnit::createByte(status)); + measureUnitValue = MeasureUnit::getByte(); + measureUnit.adoptInstead(MeasureUnit::createGigabit(status)); + measureUnitValue = MeasureUnit::getGigabit(); + measureUnit.adoptInstead(MeasureUnit::createGigabyte(status)); + measureUnitValue = MeasureUnit::getGigabyte(); + measureUnit.adoptInstead(MeasureUnit::createKilobit(status)); + measureUnitValue = MeasureUnit::getKilobit(); + measureUnit.adoptInstead(MeasureUnit::createKilobyte(status)); + measureUnitValue = MeasureUnit::getKilobyte(); + measureUnit.adoptInstead(MeasureUnit::createMegabit(status)); + measureUnitValue = MeasureUnit::getMegabit(); + measureUnit.adoptInstead(MeasureUnit::createMegabyte(status)); + measureUnitValue = MeasureUnit::getMegabyte(); + measureUnit.adoptInstead(MeasureUnit::createPetabyte(status)); + measureUnitValue = MeasureUnit::getPetabyte(); + measureUnit.adoptInstead(MeasureUnit::createTerabit(status)); + measureUnitValue = MeasureUnit::getTerabit(); + measureUnit.adoptInstead(MeasureUnit::createTerabyte(status)); + measureUnitValue = MeasureUnit::getTerabyte(); + measureUnit.adoptInstead(MeasureUnit::createCentury(status)); + measureUnitValue = MeasureUnit::getCentury(); + measureUnit.adoptInstead(MeasureUnit::createDay(status)); + measureUnitValue = MeasureUnit::getDay(); + measureUnit.adoptInstead(MeasureUnit::createDayPerson(status)); + measureUnitValue = MeasureUnit::getDayPerson(); + measureUnit.adoptInstead(MeasureUnit::createDecade(status)); + measureUnitValue = MeasureUnit::getDecade(); + measureUnit.adoptInstead(MeasureUnit::createHour(status)); + measureUnitValue = MeasureUnit::getHour(); + measureUnit.adoptInstead(MeasureUnit::createMicrosecond(status)); + measureUnitValue = MeasureUnit::getMicrosecond(); + measureUnit.adoptInstead(MeasureUnit::createMillisecond(status)); + measureUnitValue = MeasureUnit::getMillisecond(); + measureUnit.adoptInstead(MeasureUnit::createMinute(status)); + measureUnitValue = MeasureUnit::getMinute(); + measureUnit.adoptInstead(MeasureUnit::createMonth(status)); + measureUnitValue = MeasureUnit::getMonth(); + measureUnit.adoptInstead(MeasureUnit::createMonthPerson(status)); + measureUnitValue = MeasureUnit::getMonthPerson(); + measureUnit.adoptInstead(MeasureUnit::createNanosecond(status)); + measureUnitValue = MeasureUnit::getNanosecond(); + measureUnit.adoptInstead(MeasureUnit::createSecond(status)); + measureUnitValue = MeasureUnit::getSecond(); + measureUnit.adoptInstead(MeasureUnit::createWeek(status)); + measureUnitValue = MeasureUnit::getWeek(); + measureUnit.adoptInstead(MeasureUnit::createWeekPerson(status)); + measureUnitValue = MeasureUnit::getWeekPerson(); + measureUnit.adoptInstead(MeasureUnit::createYear(status)); + measureUnitValue = MeasureUnit::getYear(); + measureUnit.adoptInstead(MeasureUnit::createYearPerson(status)); + measureUnitValue = MeasureUnit::getYearPerson(); + measureUnit.adoptInstead(MeasureUnit::createAmpere(status)); + measureUnitValue = MeasureUnit::getAmpere(); + measureUnit.adoptInstead(MeasureUnit::createMilliampere(status)); + measureUnitValue = MeasureUnit::getMilliampere(); + measureUnit.adoptInstead(MeasureUnit::createOhm(status)); + measureUnitValue = MeasureUnit::getOhm(); + measureUnit.adoptInstead(MeasureUnit::createVolt(status)); + measureUnitValue = MeasureUnit::getVolt(); + measureUnit.adoptInstead(MeasureUnit::createBritishThermalUnit(status)); + measureUnitValue = MeasureUnit::getBritishThermalUnit(); + measureUnit.adoptInstead(MeasureUnit::createCalorie(status)); + measureUnitValue = MeasureUnit::getCalorie(); + measureUnit.adoptInstead(MeasureUnit::createElectronvolt(status)); + measureUnitValue = MeasureUnit::getElectronvolt(); + measureUnit.adoptInstead(MeasureUnit::createFoodcalorie(status)); + measureUnitValue = MeasureUnit::getFoodcalorie(); + measureUnit.adoptInstead(MeasureUnit::createJoule(status)); + measureUnitValue = MeasureUnit::getJoule(); + measureUnit.adoptInstead(MeasureUnit::createKilocalorie(status)); + measureUnitValue = MeasureUnit::getKilocalorie(); + measureUnit.adoptInstead(MeasureUnit::createKilojoule(status)); + measureUnitValue = MeasureUnit::getKilojoule(); + measureUnit.adoptInstead(MeasureUnit::createKilowattHour(status)); + measureUnitValue = MeasureUnit::getKilowattHour(); + measureUnit.adoptInstead(MeasureUnit::createThermUs(status)); + measureUnitValue = MeasureUnit::getThermUs(); + measureUnit.adoptInstead(MeasureUnit::createNewton(status)); + measureUnitValue = MeasureUnit::getNewton(); + measureUnit.adoptInstead(MeasureUnit::createPoundForce(status)); + measureUnitValue = MeasureUnit::getPoundForce(); + measureUnit.adoptInstead(MeasureUnit::createGigahertz(status)); + measureUnitValue = MeasureUnit::getGigahertz(); + measureUnit.adoptInstead(MeasureUnit::createHertz(status)); + measureUnitValue = MeasureUnit::getHertz(); + measureUnit.adoptInstead(MeasureUnit::createKilohertz(status)); + measureUnitValue = MeasureUnit::getKilohertz(); + measureUnit.adoptInstead(MeasureUnit::createMegahertz(status)); + measureUnitValue = MeasureUnit::getMegahertz(); + measureUnit.adoptInstead(MeasureUnit::createDotPerCentimeter(status)); + measureUnitValue = MeasureUnit::getDotPerCentimeter(); + measureUnit.adoptInstead(MeasureUnit::createDotPerInch(status)); + measureUnitValue = MeasureUnit::getDotPerInch(); + measureUnit.adoptInstead(MeasureUnit::createEm(status)); + measureUnitValue = MeasureUnit::getEm(); + measureUnit.adoptInstead(MeasureUnit::createMegapixel(status)); + measureUnitValue = MeasureUnit::getMegapixel(); + measureUnit.adoptInstead(MeasureUnit::createPixel(status)); + measureUnitValue = MeasureUnit::getPixel(); + measureUnit.adoptInstead(MeasureUnit::createPixelPerCentimeter(status)); + measureUnitValue = MeasureUnit::getPixelPerCentimeter(); + measureUnit.adoptInstead(MeasureUnit::createPixelPerInch(status)); + measureUnitValue = MeasureUnit::getPixelPerInch(); + measureUnit.adoptInstead(MeasureUnit::createAstronomicalUnit(status)); + measureUnitValue = MeasureUnit::getAstronomicalUnit(); + measureUnit.adoptInstead(MeasureUnit::createCentimeter(status)); + measureUnitValue = MeasureUnit::getCentimeter(); + measureUnit.adoptInstead(MeasureUnit::createDecimeter(status)); + measureUnitValue = MeasureUnit::getDecimeter(); + measureUnit.adoptInstead(MeasureUnit::createFathom(status)); + measureUnitValue = MeasureUnit::getFathom(); + measureUnit.adoptInstead(MeasureUnit::createFoot(status)); + measureUnitValue = MeasureUnit::getFoot(); + measureUnit.adoptInstead(MeasureUnit::createFurlong(status)); + measureUnitValue = MeasureUnit::getFurlong(); + measureUnit.adoptInstead(MeasureUnit::createInch(status)); + measureUnitValue = MeasureUnit::getInch(); + measureUnit.adoptInstead(MeasureUnit::createKilometer(status)); + measureUnitValue = MeasureUnit::getKilometer(); + measureUnit.adoptInstead(MeasureUnit::createLightYear(status)); + measureUnitValue = MeasureUnit::getLightYear(); + measureUnit.adoptInstead(MeasureUnit::createMeter(status)); + measureUnitValue = MeasureUnit::getMeter(); + measureUnit.adoptInstead(MeasureUnit::createMicrometer(status)); + measureUnitValue = MeasureUnit::getMicrometer(); + measureUnit.adoptInstead(MeasureUnit::createMile(status)); + measureUnitValue = MeasureUnit::getMile(); + measureUnit.adoptInstead(MeasureUnit::createMileScandinavian(status)); + measureUnitValue = MeasureUnit::getMileScandinavian(); + measureUnit.adoptInstead(MeasureUnit::createMillimeter(status)); + measureUnitValue = MeasureUnit::getMillimeter(); + measureUnit.adoptInstead(MeasureUnit::createNanometer(status)); + measureUnitValue = MeasureUnit::getNanometer(); + measureUnit.adoptInstead(MeasureUnit::createNauticalMile(status)); + measureUnitValue = MeasureUnit::getNauticalMile(); + measureUnit.adoptInstead(MeasureUnit::createParsec(status)); + measureUnitValue = MeasureUnit::getParsec(); + measureUnit.adoptInstead(MeasureUnit::createPicometer(status)); + measureUnitValue = MeasureUnit::getPicometer(); + measureUnit.adoptInstead(MeasureUnit::createPoint(status)); + measureUnitValue = MeasureUnit::getPoint(); + measureUnit.adoptInstead(MeasureUnit::createSolarRadius(status)); + measureUnitValue = MeasureUnit::getSolarRadius(); + measureUnit.adoptInstead(MeasureUnit::createYard(status)); + measureUnitValue = MeasureUnit::getYard(); + measureUnit.adoptInstead(MeasureUnit::createLux(status)); + measureUnitValue = MeasureUnit::getLux(); + measureUnit.adoptInstead(MeasureUnit::createSolarLuminosity(status)); + measureUnitValue = MeasureUnit::getSolarLuminosity(); + measureUnit.adoptInstead(MeasureUnit::createCarat(status)); + measureUnitValue = MeasureUnit::getCarat(); + measureUnit.adoptInstead(MeasureUnit::createDalton(status)); + measureUnitValue = MeasureUnit::getDalton(); + measureUnit.adoptInstead(MeasureUnit::createEarthMass(status)); + measureUnitValue = MeasureUnit::getEarthMass(); + measureUnit.adoptInstead(MeasureUnit::createGram(status)); + measureUnitValue = MeasureUnit::getGram(); + measureUnit.adoptInstead(MeasureUnit::createKilogram(status)); + measureUnitValue = MeasureUnit::getKilogram(); + measureUnit.adoptInstead(MeasureUnit::createMetricTon(status)); + measureUnitValue = MeasureUnit::getMetricTon(); + measureUnit.adoptInstead(MeasureUnit::createMicrogram(status)); + measureUnitValue = MeasureUnit::getMicrogram(); + measureUnit.adoptInstead(MeasureUnit::createMilligram(status)); + measureUnitValue = MeasureUnit::getMilligram(); + measureUnit.adoptInstead(MeasureUnit::createOunce(status)); + measureUnitValue = MeasureUnit::getOunce(); + measureUnit.adoptInstead(MeasureUnit::createOunceTroy(status)); + measureUnitValue = MeasureUnit::getOunceTroy(); + measureUnit.adoptInstead(MeasureUnit::createPound(status)); + measureUnitValue = MeasureUnit::getPound(); + measureUnit.adoptInstead(MeasureUnit::createSolarMass(status)); + measureUnitValue = MeasureUnit::getSolarMass(); + measureUnit.adoptInstead(MeasureUnit::createStone(status)); + measureUnitValue = MeasureUnit::getStone(); + measureUnit.adoptInstead(MeasureUnit::createTon(status)); + measureUnitValue = MeasureUnit::getTon(); + measureUnit.adoptInstead(MeasureUnit::createGigawatt(status)); + measureUnitValue = MeasureUnit::getGigawatt(); + measureUnit.adoptInstead(MeasureUnit::createHorsepower(status)); + measureUnitValue = MeasureUnit::getHorsepower(); + measureUnit.adoptInstead(MeasureUnit::createKilowatt(status)); + measureUnitValue = MeasureUnit::getKilowatt(); + measureUnit.adoptInstead(MeasureUnit::createMegawatt(status)); + measureUnitValue = MeasureUnit::getMegawatt(); + measureUnit.adoptInstead(MeasureUnit::createMilliwatt(status)); + measureUnitValue = MeasureUnit::getMilliwatt(); + measureUnit.adoptInstead(MeasureUnit::createWatt(status)); + measureUnitValue = MeasureUnit::getWatt(); + measureUnit.adoptInstead(MeasureUnit::createAtmosphere(status)); + measureUnitValue = MeasureUnit::getAtmosphere(); + measureUnit.adoptInstead(MeasureUnit::createBar(status)); + measureUnitValue = MeasureUnit::getBar(); + measureUnit.adoptInstead(MeasureUnit::createHectopascal(status)); + measureUnitValue = MeasureUnit::getHectopascal(); + measureUnit.adoptInstead(MeasureUnit::createInchHg(status)); + measureUnitValue = MeasureUnit::getInchHg(); + measureUnit.adoptInstead(MeasureUnit::createKilopascal(status)); + measureUnitValue = MeasureUnit::getKilopascal(); + measureUnit.adoptInstead(MeasureUnit::createMegapascal(status)); + measureUnitValue = MeasureUnit::getMegapascal(); + measureUnit.adoptInstead(MeasureUnit::createMillibar(status)); + measureUnitValue = MeasureUnit::getMillibar(); + measureUnit.adoptInstead(MeasureUnit::createMillimeterOfMercury(status)); + measureUnitValue = MeasureUnit::getMillimeterOfMercury(); + measureUnit.adoptInstead(MeasureUnit::createPascal(status)); + measureUnitValue = MeasureUnit::getPascal(); + measureUnit.adoptInstead(MeasureUnit::createPoundPerSquareInch(status)); + measureUnitValue = MeasureUnit::getPoundPerSquareInch(); + measureUnit.adoptInstead(MeasureUnit::createKilometerPerHour(status)); + measureUnitValue = MeasureUnit::getKilometerPerHour(); + measureUnit.adoptInstead(MeasureUnit::createKnot(status)); + measureUnitValue = MeasureUnit::getKnot(); + measureUnit.adoptInstead(MeasureUnit::createMeterPerSecond(status)); + measureUnitValue = MeasureUnit::getMeterPerSecond(); + measureUnit.adoptInstead(MeasureUnit::createMilePerHour(status)); + measureUnitValue = MeasureUnit::getMilePerHour(); + measureUnit.adoptInstead(MeasureUnit::createCelsius(status)); + measureUnitValue = MeasureUnit::getCelsius(); + measureUnit.adoptInstead(MeasureUnit::createFahrenheit(status)); + measureUnitValue = MeasureUnit::getFahrenheit(); + measureUnit.adoptInstead(MeasureUnit::createGenericTemperature(status)); + measureUnitValue = MeasureUnit::getGenericTemperature(); + measureUnit.adoptInstead(MeasureUnit::createKelvin(status)); + measureUnitValue = MeasureUnit::getKelvin(); + measureUnit.adoptInstead(MeasureUnit::createNewtonMeter(status)); + measureUnitValue = MeasureUnit::getNewtonMeter(); + measureUnit.adoptInstead(MeasureUnit::createPoundFoot(status)); + measureUnitValue = MeasureUnit::getPoundFoot(); + measureUnit.adoptInstead(MeasureUnit::createAcreFoot(status)); + measureUnitValue = MeasureUnit::getAcreFoot(); + measureUnit.adoptInstead(MeasureUnit::createBarrel(status)); + measureUnitValue = MeasureUnit::getBarrel(); + measureUnit.adoptInstead(MeasureUnit::createBushel(status)); + measureUnitValue = MeasureUnit::getBushel(); + measureUnit.adoptInstead(MeasureUnit::createCentiliter(status)); + measureUnitValue = MeasureUnit::getCentiliter(); + measureUnit.adoptInstead(MeasureUnit::createCubicCentimeter(status)); + measureUnitValue = MeasureUnit::getCubicCentimeter(); + measureUnit.adoptInstead(MeasureUnit::createCubicFoot(status)); + measureUnitValue = MeasureUnit::getCubicFoot(); + measureUnit.adoptInstead(MeasureUnit::createCubicInch(status)); + measureUnitValue = MeasureUnit::getCubicInch(); + measureUnit.adoptInstead(MeasureUnit::createCubicKilometer(status)); + measureUnitValue = MeasureUnit::getCubicKilometer(); + measureUnit.adoptInstead(MeasureUnit::createCubicMeter(status)); + measureUnitValue = MeasureUnit::getCubicMeter(); + measureUnit.adoptInstead(MeasureUnit::createCubicMile(status)); + measureUnitValue = MeasureUnit::getCubicMile(); + measureUnit.adoptInstead(MeasureUnit::createCubicYard(status)); + measureUnitValue = MeasureUnit::getCubicYard(); + measureUnit.adoptInstead(MeasureUnit::createCup(status)); + measureUnitValue = MeasureUnit::getCup(); + measureUnit.adoptInstead(MeasureUnit::createCupMetric(status)); + measureUnitValue = MeasureUnit::getCupMetric(); + measureUnit.adoptInstead(MeasureUnit::createDeciliter(status)); + measureUnitValue = MeasureUnit::getDeciliter(); + measureUnit.adoptInstead(MeasureUnit::createFluidOunce(status)); + measureUnitValue = MeasureUnit::getFluidOunce(); + measureUnit.adoptInstead(MeasureUnit::createFluidOunceImperial(status)); + measureUnitValue = MeasureUnit::getFluidOunceImperial(); + measureUnit.adoptInstead(MeasureUnit::createGallon(status)); + measureUnitValue = MeasureUnit::getGallon(); + measureUnit.adoptInstead(MeasureUnit::createGallonImperial(status)); + measureUnitValue = MeasureUnit::getGallonImperial(); + measureUnit.adoptInstead(MeasureUnit::createHectoliter(status)); + measureUnitValue = MeasureUnit::getHectoliter(); + measureUnit.adoptInstead(MeasureUnit::createLiter(status)); + measureUnitValue = MeasureUnit::getLiter(); + measureUnit.adoptInstead(MeasureUnit::createMegaliter(status)); + measureUnitValue = MeasureUnit::getMegaliter(); + measureUnit.adoptInstead(MeasureUnit::createMilliliter(status)); + measureUnitValue = MeasureUnit::getMilliliter(); + measureUnit.adoptInstead(MeasureUnit::createPint(status)); + measureUnitValue = MeasureUnit::getPint(); + measureUnit.adoptInstead(MeasureUnit::createPintMetric(status)); + measureUnitValue = MeasureUnit::getPintMetric(); + measureUnit.adoptInstead(MeasureUnit::createQuart(status)); + measureUnitValue = MeasureUnit::getQuart(); + measureUnit.adoptInstead(MeasureUnit::createTablespoon(status)); + measureUnitValue = MeasureUnit::getTablespoon(); + measureUnit.adoptInstead(MeasureUnit::createTeaspoon(status)); + measureUnitValue = MeasureUnit::getTeaspoon(); + assertSuccess("", status); +} + void MeasureFormatTest::TestBasic() { UErrorCode status = U_ZERO_ERROR; MeasureUnit *ptr1 = MeasureUnit::createArcMinute(status); @@ -1539,7 +1897,7 @@ if (!(*ptr1 != *ptr3)) { errln("Expect != to work."); } - MeasureUnit *ptr4 = (MeasureUnit *) ptr1->clone(); + MeasureUnit *ptr4 = ptr1->clone(); if (*ptr1 != *ptr4) { errln("Expect clone to work."); } @@ -1695,6 +2053,10 @@ void MeasureFormatTest::TestFormatPeriodEn() { UErrorCode status = U_ZERO_ERROR; + Measure t_1y[] = {Measure((double)1, MeasureUnit::createYear(status), status)}; + Measure t_5M[] = {Measure((double)5, MeasureUnit::createMonth(status), status)}; + Measure t_4d[] = {Measure((double)4, MeasureUnit::createDay(status), status)}; + Measure t_2h[] = {Measure((double)2, MeasureUnit::createHour(status), status)}; Measure t_19m[] = {Measure((double)19, MeasureUnit::createMinute(status), status)}; Measure t_1h_23_5s[] = { Measure((double)1.0, MeasureUnit::createHour(status), status), @@ -1837,6 +2199,46 @@ {t_6h_56_92m, UPRV_LENGTHOF(t_6h_56_92m), "6:56,92"}, {t_3h_5h, UPRV_LENGTHOF(t_3h_5h), "3 Std., 5 Std."}}; + ExpectedResult numericDataBn[] = { + {t_1m_59_9996s, UPRV_LENGTHOF(t_1m_59_9996s), "\\u09E7:\\u09EB\\u09EF.\\u09EF\\u09EF\\u09EF\\u09EC"}, + {t_19m, UPRV_LENGTHOF(t_19m), "\\u09E7\\u09EF \\u09AE\\u09BF\\u0983"}, + {t_1h_23_5s, UPRV_LENGTHOF(t_1h_23_5s), "\\u09E7:\\u09E6\\u09E6:\\u09E8\\u09E9.\\u09EB"}, + {t_1h_0m_23s, UPRV_LENGTHOF(t_1h_0m_23s), "\\u09E7:\\u09E6\\u09E6:\\u09E8\\u09E9"}, + {t_1h_23_5m, UPRV_LENGTHOF(t_1h_23_5m), "\\u09E7:\\u09E8\\u09E9.\\u09EB"}, + {t_5h_17m, UPRV_LENGTHOF(t_5h_17m), "\\u09EB:\\u09E7\\u09ED"}, + {t_19m_28s, UPRV_LENGTHOF(t_19m_28s), "\\u09E7\\u09EF:\\u09E8\\u09EE"}, + {t_2y_5M_3w_4d, UPRV_LENGTHOF(t_2y_5M_3w_4d), "\\u09E8 \\u09AC\\u099B\\u09B0, \\u09EB \\u09AE\\u09BE\\u09B8, \\u09E9 \\u09B8\\u09AA\\u09CD\\u09A4\\u09BE\\u09B9, \\u09EA \\u09A6\\u09BF\\u09A8"}, + {t_0h_0m_17s, UPRV_LENGTHOF(t_0h_0m_17s), "\\u09E6:\\u09E6\\u09E6:\\u09E7\\u09ED"}, + {t_6h_56_92m, UPRV_LENGTHOF(t_6h_56_92m), "\\u09EC:\\u09EB\\u09EC.\\u09EF\\u09E8"}, + {t_3h_5h, UPRV_LENGTHOF(t_3h_5h), "\\u09E9 \\u0998\\u0983, \\u09EB \\u0998\\u0983"}}; + + ExpectedResult numericDataBnLatn[] = { + {t_1m_59_9996s, UPRV_LENGTHOF(t_1m_59_9996s), "1:59.9996"}, + {t_19m, UPRV_LENGTHOF(t_19m), "19 \\u09AE\\u09BF\\u0983"}, + {t_1h_23_5s, UPRV_LENGTHOF(t_1h_23_5s), "1:00:23.5"}, + {t_1h_0m_23s, UPRV_LENGTHOF(t_1h_0m_23s), "1:00:23"}, + {t_1h_23_5m, UPRV_LENGTHOF(t_1h_23_5m), "1:23.5"}, + {t_5h_17m, UPRV_LENGTHOF(t_5h_17m), "5:17"}, + {t_19m_28s, UPRV_LENGTHOF(t_19m_28s), "19:28"}, + {t_2y_5M_3w_4d, UPRV_LENGTHOF(t_2y_5M_3w_4d), "2 \\u09AC\\u099B\\u09B0, 5 \\u09AE\\u09BE\\u09B8, 3 \\u09B8\\u09AA\\u09CD\\u09A4\\u09BE\\u09B9, 4 \\u09A6\\u09BF\\u09A8"}, + {t_0h_0m_17s, UPRV_LENGTHOF(t_0h_0m_17s), "0:00:17"}, + {t_6h_56_92m, UPRV_LENGTHOF(t_6h_56_92m), "6:56.92"}, + {t_3h_5h, UPRV_LENGTHOF(t_3h_5h), "3 \\u0998\\u0983, 5 \\u0998\\u0983"}}; + + ExpectedResult fullDataSpellout[] = { + {t_1y, UPRV_LENGTHOF(t_1y), "one year"}, + {t_5M, UPRV_LENGTHOF(t_5M), "five months"}, + {t_4d, UPRV_LENGTHOF(t_4d), "four days"}, + {t_2h, UPRV_LENGTHOF(t_2h), "two hours"}, + {t_19m, UPRV_LENGTHOF(t_19m), "nineteen minutes"}}; + + ExpectedResult fullDataSpelloutFr[] = { + {t_1y, UPRV_LENGTHOF(t_1y), "un\\u00A0an"}, + {t_5M, UPRV_LENGTHOF(t_5M), "cinq\\u00A0mois"}, + {t_4d, UPRV_LENGTHOF(t_4d), "quatre\\u00A0jours"}, + {t_2h, UPRV_LENGTHOF(t_2h), "deux\\u00A0heures"}, + {t_19m, UPRV_LENGTHOF(t_19m), "dix-neuf minutes"}}; + Locale en(Locale::getEnglish()); LocalPointer nf(NumberFormat::createInstance(en, status)); if (U_FAILURE(status)) { @@ -1844,7 +2246,7 @@ return; } nf->setMaximumFractionDigits(4); - MeasureFormat mf(en, UMEASFMT_WIDTH_WIDE, (NumberFormat *) nf->clone(), status); + MeasureFormat mf(en, UMEASFMT_WIDTH_WIDE, nf->clone(), status); if (!assertSuccess("Error creating measure format en WIDE", status)) { return; } @@ -1857,21 +2259,21 @@ } // exercise clone { - MeasureFormat *mf3 = (MeasureFormat *) mf.clone(); + MeasureFormat *mf3 = mf.clone(); verifyFormat("en WIDE copy", *mf3, fullData, UPRV_LENGTHOF(fullData)); delete mf3; } - mf = MeasureFormat(en, UMEASFMT_WIDTH_SHORT, (NumberFormat *) nf->clone(), status); + mf = MeasureFormat(en, UMEASFMT_WIDTH_SHORT, nf->clone(), status); if (!assertSuccess("Error creating measure format en SHORT", status)) { return; } verifyFormat("en SHORT", mf, abbrevData, UPRV_LENGTHOF(abbrevData)); - mf = MeasureFormat(en, UMEASFMT_WIDTH_NARROW, (NumberFormat *) nf->clone(), status); + mf = MeasureFormat(en, UMEASFMT_WIDTH_NARROW, nf->clone(), status); if (!assertSuccess("Error creating measure format en NARROW", status)) { return; } verifyFormat("en NARROW", mf, narrowData, UPRV_LENGTHOF(narrowData)); - mf = MeasureFormat(en, UMEASFMT_WIDTH_NUMERIC, (NumberFormat *) nf->clone(), status); + mf = MeasureFormat(en, UMEASFMT_WIDTH_NUMERIC, nf->clone(), status); if (!assertSuccess("Error creating measure format en NUMERIC", status)) { return; } @@ -1883,16 +2285,64 @@ return; } nf->setMaximumFractionDigits(4); - mf = MeasureFormat(de, UMEASFMT_WIDTH_WIDE, (NumberFormat *) nf->clone(), status); + mf = MeasureFormat(de, UMEASFMT_WIDTH_WIDE, nf->clone(), status); if (!assertSuccess("Error creating measure format de WIDE", status)) { return; } verifyFormat("de WIDE", mf, fullDataDe, UPRV_LENGTHOF(fullDataDe)); - mf = MeasureFormat(de, UMEASFMT_WIDTH_NUMERIC, (NumberFormat *) nf->clone(), status); + mf = MeasureFormat(de, UMEASFMT_WIDTH_NUMERIC, nf->clone(), status); if (!assertSuccess("Error creating measure format de NUMERIC", status)) { return; } verifyFormat("de NUMERIC", mf, numericDataDe, UPRV_LENGTHOF(numericDataDe)); + + Locale bengali("bn"); + nf.adoptInstead(NumberFormat::createInstance(bengali, status)); + if (!assertSuccess("Error creating number format de object", status)) { + return; + } + nf->setMaximumFractionDigits(4); + mf = MeasureFormat(bengali, UMEASFMT_WIDTH_NUMERIC, nf->clone(), status); + if (!assertSuccess("Error creating measure format bn NUMERIC", status)) { + return; + } + verifyFormat("bn NUMERIC", mf, numericDataBn, UPRV_LENGTHOF(numericDataBn)); + + Locale bengaliLatin("bn-u-nu-latn"); + nf.adoptInstead(NumberFormat::createInstance(bengaliLatin, status)); + if (!assertSuccess("Error creating number format de object", status)) { + return; + } + nf->setMaximumFractionDigits(4); + mf = MeasureFormat(bengaliLatin, UMEASFMT_WIDTH_NUMERIC, nf->clone(), status); + if (!assertSuccess("Error creating measure format bn-u-nu-latn NUMERIC", status)) { + return; + } + verifyFormat("bn-u-nu-latn NUMERIC", mf, numericDataBnLatn, UPRV_LENGTHOF(numericDataBnLatn)); + + status = U_ZERO_ERROR; + LocalPointer rbnf(new RuleBasedNumberFormat(URBNF_SPELLOUT, en, status)); + if (U_FAILURE(status)) { + dataerrln("Error creating rbnf en object - %s", u_errorName(status)); + return; + } + mf = MeasureFormat(en, UMEASFMT_WIDTH_WIDE, rbnf->clone(), status); + if (!assertSuccess("Error creating measure format en WIDE with rbnf", status)) { + return; + } + verifyFormat("en WIDE rbnf", mf, fullDataSpellout, UPRV_LENGTHOF(fullDataSpellout)); + + Locale fr(Locale::getFrench()); + LocalPointer rbnffr(new RuleBasedNumberFormat(URBNF_SPELLOUT, fr, status)); + if (U_FAILURE(status)) { + dataerrln("Error creating rbnf fr object - %s", u_errorName(status)); + return; + } + mf = MeasureFormat(fr, UMEASFMT_WIDTH_WIDE, rbnffr->clone(), status); + if (!assertSuccess("Error creating measure format fr WIDE with rbnf", status)) { + return; + } + verifyFormat("fr WIDE rbnf", mf, fullDataSpelloutFr, UPRV_LENGTHOF(fullDataSpellout)); } void MeasureFormatTest::Test10219FractionalPlurals() { @@ -1967,7 +2417,7 @@ "1 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B1", "1 \\u03B5\\u03B2\\u03B4.", "1 \\u03BC\\u03AE\\u03BD.", - "1 \\u03AD\\u03C4.", // year (one) + "1 \\u03AD\\u03C4.", // year (one) // "el_GR" 7 wide "7 \\u03B4\\u03B5\\u03C5\\u03C4\\u03B5\\u03C1\\u03CC\\u03BB\\u03B5\\u03C0\\u03C4\\u03B1", "7 \\u03BB\\u03B5\\u03C0\\u03C4\\u03AC", @@ -1979,7 +2429,7 @@ // "el_GR" 7 short "7 \\u03B4\\u03B5\\u03C5\\u03C4.", "7 \\u03BB\\u03B5\\u03C0.", - "7 \\u03CE\\u03C1.", // hour (other) + "7 \\u03CE\\u03C1.", // hour (other) "7 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B5\\u03C2", "7 \\u03B5\\u03B2\\u03B4.", "7 \\u03BC\\u03AE\\u03BD.", @@ -2000,7 +2450,7 @@ "1 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B1", "1 \\u03B5\\u03B2\\u03B4.", "1 \\u03BC\\u03AE\\u03BD.", - "1 \\u03AD\\u03C4.", // year (one) + "1 \\u03AD\\u03C4.", // year (one) // "el" 7 wide "7 \\u03B4\\u03B5\\u03C5\\u03C4\\u03B5\\u03C1\\u03CC\\u03BB\\u03B5\\u03C0\\u03C4\\u03B1", "7 \\u03BB\\u03B5\\u03C0\\u03C4\\u03AC", @@ -2012,7 +2462,7 @@ // "el" 7 short "7 \\u03B4\\u03B5\\u03C5\\u03C4.", "7 \\u03BB\\u03B5\\u03C0.", - "7 \\u03CE\\u03C1.", // hour (other) + "7 \\u03CE\\u03C1.", // hour (other) "7 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B5\\u03C2", "7 \\u03B5\\u03B2\\u03B4.", "7 \\u03BC\\u03AE\\u03BD.", @@ -2194,7 +2644,7 @@ if (!assertSuccess("Error creating format object", status)) { return; } - Measure measure(value, (MeasureUnit *) unit.clone(), status); + Measure measure(value, unit.clone(), status); if (!assertSuccess("Error creating measure object", status)) { return; } @@ -2267,7 +2717,7 @@ if (!assertSuccess("Error creating measures", status)) { return; } - helperTestManyLocaleDurations("da", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5 t og 37 min"); + helperTestManyLocaleDurations("da", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5 t og 37 m"); helperTestManyLocaleDurations("da", UMEASFMT_WIDTH_NUMERIC, measures, UPRV_LENGTHOF(measures), "5.37"); helperTestManyLocaleDurations("de", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5 Std., 37 Min."); helperTestManyLocaleDurations("de", UMEASFMT_WIDTH_NUMERIC, measures, UPRV_LENGTHOF(measures), "5:37"); @@ -2275,7 +2725,7 @@ helperTestManyLocaleDurations("en", UMEASFMT_WIDTH_NUMERIC, measures, UPRV_LENGTHOF(measures), "5:37"); helperTestManyLocaleDurations("en_GB", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5h 37m"); helperTestManyLocaleDurations("en_GB", UMEASFMT_WIDTH_NUMERIC, measures, UPRV_LENGTHOF(measures), "5:37"); - helperTestManyLocaleDurations("es", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5h 37min"); + helperTestManyLocaleDurations("es", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5 h 37 min"); helperTestManyLocaleDurations("es", UMEASFMT_WIDTH_NUMERIC, measures, UPRV_LENGTHOF(measures), "5:37"); helperTestManyLocaleDurations("fi", UMEASFMT_WIDTH_NARROW, measures, UPRV_LENGTHOF(measures), "5t 37min"); helperTestManyLocaleDurations("fi", UMEASFMT_WIDTH_NUMERIC, measures, UPRV_LENGTHOF(measures), "5.37"); @@ -2691,6 +3141,80 @@ } } +void MeasureFormatTest::TestNumericTime() { + IcuTestErrorCode status(*this, "TestNumericTime"); + + MeasureFormat fmt("en", UMEASFMT_WIDTH_NUMERIC, status); + + Measure hours(112, MeasureUnit::createHour(status), status); + Measure minutes(113, MeasureUnit::createMinute(status), status); + Measure seconds(114, MeasureUnit::createSecond(status), status); + Measure fhours(112.8765, MeasureUnit::createHour(status), status); + Measure fminutes(113.8765, MeasureUnit::createMinute(status), status); + Measure fseconds(114.8765, MeasureUnit::createSecond(status), status); + if (status.errDataIfFailureAndReset(WHERE)) return; + + verifyFormat("hours", fmt, &hours, 1, "112h"); + verifyFormat("minutes", fmt, &minutes, 1, "113m"); + verifyFormat("seconds", fmt, &seconds, 1, "114s"); + + verifyFormat("fhours", fmt, &fhours, 1, "112.876h"); + verifyFormat("fminutes", fmt, &fminutes, 1, "113.876m"); + verifyFormat("fseconds", fmt, &fseconds, 1, "114.876s"); + + Measure hoursMinutes[2] = {hours, minutes}; + verifyFormat("hoursMinutes", fmt, hoursMinutes, 2, "112:113"); + Measure hoursSeconds[2] = {hours, seconds}; + verifyFormat("hoursSeconds", fmt, hoursSeconds, 2, "112:00:114"); + Measure minutesSeconds[2] = {minutes, seconds}; + verifyFormat("minutesSeconds", fmt, minutesSeconds, 2, "113:114"); + + Measure hoursFminutes[2] = {hours, fminutes}; + verifyFormat("hoursFminutes", fmt, hoursFminutes, 2, "112:113.876"); + Measure hoursFseconds[2] = {hours, fseconds}; + verifyFormat("hoursFseconds", fmt, hoursFseconds, 2, "112:00:114.876"); + Measure minutesFseconds[2] = {minutes, fseconds}; + verifyFormat("hoursMminutesFsecondsinutes", fmt, minutesFseconds, 2, "113:114.876"); + + Measure fhoursMinutes[2] = {fhours, minutes}; + verifyFormat("fhoursMinutes", fmt, fhoursMinutes, 2, "112:113"); + Measure fhoursSeconds[2] = {fhours, seconds}; + verifyFormat("fhoursSeconds", fmt, fhoursSeconds, 2, "112:00:114"); + Measure fminutesSeconds[2] = {fminutes, seconds}; + verifyFormat("fminutesSeconds", fmt, fminutesSeconds, 2, "113:114"); + + Measure fhoursFminutes[2] = {fhours, fminutes}; + verifyFormat("fhoursFminutes", fmt, fhoursFminutes, 2, "112:113.876"); + Measure fhoursFseconds[2] = {fhours, fseconds}; + verifyFormat("fhoursFseconds", fmt, fhoursFseconds, 2, "112:00:114.876"); + Measure fminutesFseconds[2] = {fminutes, fseconds}; + verifyFormat("fminutesFseconds", fmt, fminutesFseconds, 2, "113:114.876"); + + Measure hoursMinutesSeconds[3] = {hours, minutes, seconds}; + verifyFormat("hoursMinutesSeconds", fmt, hoursMinutesSeconds, 3, "112:113:114"); + Measure fhoursFminutesFseconds[3] = {fhours, fminutes, fseconds}; + verifyFormat("fhoursFminutesFseconds", fmt, fhoursFminutesFseconds, 3, "112:113:114.876"); +} + +void MeasureFormatTest::TestNumericTimeSomeSpecialFormats() { + IcuTestErrorCode status(*this, "TestNumericTimeSomeSpecialFormats"); + + Measure fhours(2.8765432, MeasureUnit::createHour(status), status); + Measure fminutes(3.8765432, MeasureUnit::createMinute(status), status); + if (status.errDataIfFailureAndReset(WHERE)) return; + + Measure fhoursFminutes[2] = {fhours, fminutes}; + + // Latvian is one of the very few locales 0-padding the hour + MeasureFormat fmtLt("lt", UMEASFMT_WIDTH_NUMERIC, status); + if (status.errDataIfFailureAndReset(WHERE)) return; + verifyFormat("Latvian fhoursFminutes", fmtLt, fhoursFminutes, 2, "02:03,877"); + + // Danish is one of the very few locales using '.' as separator + MeasureFormat fmtDa("da", UMEASFMT_WIDTH_NUMERIC, status); + verifyFormat("Danish fhoursFminutes", fmtDa, fhoursFminutes, 2, "2.03,877"); +} + void MeasureFormatTest::verifyFieldPosition( const char *description, diff -Nru icu-64.2/source/test/intltest/miscdtfm.cpp icu-65.1/source/test/intltest/miscdtfm.cpp --- icu-64.2/source/test/intltest/miscdtfm.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/miscdtfm.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -113,8 +113,8 @@ };*/ UErrorCode status = U_ZERO_ERROR; - SimpleDateFormat *formatter; - SimpleDateFormat *resultFormatter = new SimpleDateFormat((UnicodeString)"yyyy", status); + LocalPointer formatter; + SimpleDateFormat resultFormatter((UnicodeString)u"yyyy", status); if (U_FAILURE(status)) { dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status)); return; @@ -125,24 +125,21 @@ for (int i = 0; i < 14/*dstring.length*/; i++) { log(dformat[i] + "\t" + dstring[i] + "\t"); - formatter = new SimpleDateFormat(dformat[i], status); + formatter.adoptInstead(new SimpleDateFormat(dformat[i], status)); if(failure(status, "new SimpleDateFormat")) return; //try { UnicodeString str; FieldPosition pos(FieldPosition::DONT_CARE); - logln(resultFormatter->format(formatter->parse(dstring[i], status), str, pos)); - failure(status, "resultFormatter->format"); + logln(resultFormatter.format(formatter->parse(dstring[i], status), str, pos)); + failure(status, "resultFormatter.format"); //if ( !dresult[i] ) System.out.print(" <-- error!"); /*} catch (ParseException exception) { //if ( dresult[i] ) System.out.print(" <-- error!"); System.out.print("exception --> " + exception); }*/ - delete formatter; logln(); } - - delete resultFormatter; } /* diff -Nru icu-64.2/source/test/intltest/msfmrgts.cpp icu-65.1/source/test/intltest/msfmrgts.cpp --- icu-64.2/source/test/intltest/msfmrgts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/msfmrgts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -32,29 +32,29 @@ MessageFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { TESTCASE_AUTO_BEGIN; - TESTCASE_AUTO(Test4074764) + TESTCASE_AUTO(Test4074764); //TESTCASE_AUTO(Test4058973) -- disabled/obsolete in ICU 4.8 - TESTCASE_AUTO(Test4031438) - TESTCASE_AUTO(Test4052223) - TESTCASE_AUTO(Test4104976) - TESTCASE_AUTO(Test4106659) - TESTCASE_AUTO(Test4106660) - TESTCASE_AUTO(Test4111739) - TESTCASE_AUTO(Test4114743) - TESTCASE_AUTO(Test4116444) - TESTCASE_AUTO(Test4114739) - TESTCASE_AUTO(Test4113018) - TESTCASE_AUTO(Test4106661) - TESTCASE_AUTO(Test4094906) - TESTCASE_AUTO(Test4118592) - TESTCASE_AUTO(Test4118594) - TESTCASE_AUTO(Test4105380) - TESTCASE_AUTO(Test4120552) - TESTCASE_AUTO(Test4142938) - TESTCASE_AUTO(TestChoicePatternQuote) - TESTCASE_AUTO(Test4112104) - TESTCASE_AUTO(TestICU12584) - TESTCASE_AUTO(TestAPI) + TESTCASE_AUTO(Test4031438); + TESTCASE_AUTO(Test4052223); + TESTCASE_AUTO(Test4104976); + TESTCASE_AUTO(Test4106659); + TESTCASE_AUTO(Test4106660); + TESTCASE_AUTO(Test4111739); + TESTCASE_AUTO(Test4114743); + TESTCASE_AUTO(Test4116444); + TESTCASE_AUTO(Test4114739); + TESTCASE_AUTO(Test4113018); + TESTCASE_AUTO(Test4106661); + TESTCASE_AUTO(Test4094906); + TESTCASE_AUTO(Test4118592); + TESTCASE_AUTO(Test4118594); + TESTCASE_AUTO(Test4105380); + TESTCASE_AUTO(Test4120552); + TESTCASE_AUTO(Test4142938); + TESTCASE_AUTO(TestChoicePatternQuote); + TESTCASE_AUTO(Test4112104); + TESTCASE_AUTO(TestICU12584); + TESTCASE_AUTO(TestAPI); TESTCASE_AUTO_END; } diff -Nru icu-64.2/source/test/intltest/nmfmapts.cpp icu-65.1/source/test/intltest/nmfmapts.cpp --- icu-64.2/source/test/intltest/nmfmapts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/nmfmapts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -274,7 +274,7 @@ virtual NumberFormat* createFormat(const Locale& /* loc */, UNumberFormatStyle formatType) { if (formatType == UNUM_CURRENCY) { - return (NumberFormat*)currencyStyle->clone(); + return currencyStyle->clone(); } return NULL; } @@ -310,7 +310,7 @@ LocalPointer f3a(NumberFormat::createCurrencyInstance(SRC_LOC, status)); LocalPointer f4(NumberFormat::createInstance(SRC_LOC, status)); - StringEnumeration* locs = NumberFormat::getAvailableLocales(); + LocalPointer locs(NumberFormat::getAvailableLocales()); LocalUNumberFormatPointer uf3(unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(), NULL, &status)); LocalUNumberFormatPointer uf4(unum_open(UNUM_DEFAULT, NULL, 0, SRC_LOC.getName(), NULL, &status)); @@ -325,7 +325,7 @@ LocalUNumberFormatPointer uf5(unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(), NULL, &status)); if (U_FAILURE(status)) { - dataerrln("Error creating instnaces."); + dataerrln("Error creating instanaces."); return; } else { float n = 1234.567f; @@ -391,8 +391,6 @@ for (res = locs->snext(status); res; res = locs->snext(status)) { logln(*res); } - - delete locs; #endif } diff -Nru icu-64.2/source/test/intltest/nptrans.cpp icu-65.1/source/test/intltest/nptrans.cpp --- icu-64.2/source/test/intltest/nptrans.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/nptrans.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -47,11 +47,10 @@ //constructor NamePrepTransform::NamePrepTransform(UParseError& parseError, UErrorCode& status) -: unassigned(), prohibited(), labelSeparatorSet(){ + : mapping(nullptr), unassigned(), prohibited(), labelSeparatorSet(), bundle(nullptr) { - mapping = NULL; - bundle = NULL; - + LocalPointer lmapping; + LocalUResourceBundlePointer lbundle; const char* testDataName = IntlTest::loadTestData(status); @@ -59,31 +58,31 @@ return; } - bundle = ures_openDirect(testDataName,"idna_rules",&status); + lbundle.adoptInstead(ures_openDirect(testDataName,"idna_rules",&status)); - if(bundle != NULL && U_SUCCESS(status)){ + if(lbundle.isValid() && U_SUCCESS(status)){ // create the mapping transliterator int32_t ruleLen = 0; - const UChar* ruleUChar = ures_getStringByKey(bundle, "MapNFKC",&ruleLen, &status); + const UChar* ruleUChar = ures_getStringByKey(lbundle.getAlias(), "MapNFKC",&ruleLen, &status); int32_t mapRuleLen = 0; - const UChar *mapRuleUChar = ures_getStringByKey(bundle, "MapNoNormalization", &mapRuleLen, &status); + const UChar *mapRuleUChar = ures_getStringByKey(lbundle.getAlias(), "MapNoNormalization", &mapRuleLen, &status); UnicodeString rule(mapRuleUChar, mapRuleLen); rule.append(ruleUChar, ruleLen); - mapping = Transliterator::createFromRules(UnicodeString("NamePrepTransform", ""), rule, - UTRANS_FORWARD, parseError,status); + lmapping.adoptInstead( Transliterator::createFromRules(UnicodeString("NamePrepTransform", ""), rule, + UTRANS_FORWARD, parseError,status)); if(U_FAILURE(status)) { - return; + return; } //create the unassigned set int32_t patternLen =0; - const UChar* pattern = ures_getStringByKey(bundle,"UnassignedSet",&patternLen, &status); + const UChar* pattern = ures_getStringByKey(lbundle.getAlias(),"UnassignedSet",&patternLen, &status); unassigned.applyPattern(UnicodeString(pattern, patternLen), status); //create prohibited set patternLen=0; - pattern = ures_getStringByKey(bundle,"ProhibitedSet",&patternLen, &status); + pattern = ures_getStringByKey(lbundle.getAlias(),"ProhibitedSet",&patternLen, &status); UnicodeString test(pattern,patternLen); prohibited.applyPattern(test,status); #ifdef NPTRANS_DEBUG @@ -107,20 +106,18 @@ //create label separator set patternLen=0; - pattern = ures_getStringByKey(bundle,"LabelSeparatorSet",&patternLen, &status); + pattern = ures_getStringByKey(lbundle.getAlias(), "LabelSeparatorSet", &patternLen, &status); labelSeparatorSet.applyPattern(UnicodeString(pattern,patternLen),status); } - if(U_SUCCESS(status) && - (mapping == NULL) - ){ + if(U_SUCCESS(status) && (lmapping.isNull())) { status = U_MEMORY_ALLOCATION_ERROR; - delete mapping; - ures_close(bundle); - mapping = NULL; - bundle = NULL; } - + if (U_FAILURE(status)) { + return; + } + mapping = lmapping.orphan(); + bundle = lbundle.orphan(); } diff -Nru icu-64.2/source/test/intltest/numbertest_affixutils.cpp icu-65.1/source/test/intltest/numbertest_affixutils.cpp --- icu-64.2/source/test/intltest/numbertest_affixutils.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_affixutils.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -217,7 +217,7 @@ NumericSymbolProvider provider; UErrorCode status = U_ZERO_ERROR; - NumberStringBuilder sb; + FormattedStringBuilder sb; for (auto& cas : cases) { UnicodeString input(cas[0]); UnicodeString expected(cas[1]); @@ -239,7 +239,7 @@ UnicodeString AffixUtilsTest::unescapeWithDefaults(const SymbolProvider &defaultProvider, UnicodeString input, UErrorCode &status) { - NumberStringBuilder nsb; + FormattedStringBuilder nsb; int32_t length = AffixUtils::unescape(input, nsb, 0, defaultProvider, UNUM_FIELD_COUNT, status); assertEquals("Return value of unescape", nsb.length(), length); return nsb.toUnicodeString(); diff -Nru icu-64.2/source/test/intltest/numbertest_api.cpp icu-65.1/source/test/intltest/numbertest_api.cpp --- icu-64.2/source/test/intltest/numbertest_api.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_api.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -86,9 +86,11 @@ // TODO: Add this method if currency symbols override support is added. //TESTCASE_AUTO(symbolsOverride); TESTCASE_AUTO(sign); + TESTCASE_AUTO(signCoverage); TESTCASE_AUTO(decimal); TESTCASE_AUTO(scale); TESTCASE_AUTO(locale); + TESTCASE_AUTO(skeletonUserGuideExamples); TESTCASE_AUTO(formatTypes); TESTCASE_AUTO(fieldPositionLogic); TESTCASE_AUTO(fieldPositionCoverage); @@ -102,6 +104,7 @@ TESTCASE_AUTO(copyMove); TESTCASE_AUTO(localPointerCAPI); TESTCASE_AUTO(toObject); + TESTCASE_AUTO(toDecimalNumber); TESTCASE_AUTO_END; } @@ -215,6 +218,22 @@ Locale::getEnglish(), -1000000, u"-1E6"); + + assertFormatSingle( + u"Scientific Infinity", + u"scientific", + NumberFormatter::with().notation(Notation::scientific()), + Locale::getEnglish(), + -uprv_getInfinity(), + u"-∞"); + + assertFormatSingle( + u"Scientific NaN", + u"scientific", + NumberFormatter::with().notation(Notation::scientific()), + Locale::getEnglish(), + uprv_getNaN(), + u"NaN"); } void NumberFormatterApiTest::notationCompact() { @@ -431,6 +450,22 @@ 1e7, u"1000\u842C"); + assertFormatSingle( + u"Compact Infinity", + u"compact-short", + NumberFormatter::with().notation(Notation::compactShort()), + Locale::getEnglish(), + -uprv_getInfinity(), + u"-∞"); + + assertFormatSingle( + u"Compact NaN", + u"compact-short", + NumberFormatter::with().notation(Notation::compactShort()), + Locale::getEnglish(), + uprv_getNaN(), + u"NaN"); + // NOTE: There is no API for compact custom data in C++ // and thus no "Compact Somali No Figure" test } @@ -1345,17 +1380,18 @@ u"8.765", u"0"); - // NOTE: Hungarian is interesting because it has minimumGroupingDigits=4 in locale data + // NOTE: Polish is interesting because it has minimumGroupingDigits=2 in locale data + // (Most locales have either 1 or 2) // If this test breaks due to data changes, find another locale that has minimumGroupingDigits. assertFormatDescendingBig( - u"Hungarian Grouping", + u"Polish Grouping", u"group-auto", NumberFormatter::with().grouping(UNUM_GROUPING_AUTO), - Locale("hu"), + Locale("pl"), u"87 650 000", u"8 765 000", - u"876500", - u"87650", + u"876 500", + u"87 650", u"8765", u"876,5", u"87,65", @@ -1363,14 +1399,14 @@ u"0"); assertFormatDescendingBig( - u"Hungarian Grouping, Min 2", + u"Polish Grouping, Min 2", u"group-min2", NumberFormatter::with().grouping(UNUM_GROUPING_MIN2), - Locale("hu"), + Locale("pl"), u"87 650 000", u"8 765 000", - u"876500", - u"87650", + u"876 500", + u"87 650", u"8765", u"876,5", u"87,65", @@ -1378,10 +1414,10 @@ u"0"); assertFormatDescendingBig( - u"Hungarian Grouping, Always", + u"Polish Grouping, Always", u"group-on-aligned", NumberFormatter::with().grouping(UNUM_GROUPING_ON_ALIGNED), - Locale("hu"), + Locale("pl"), u"87 650 000", u"8 765 000", u"876 500", @@ -2068,6 +2104,39 @@ u"-444,444.00 US dollars"); } +void NumberFormatterApiTest::signCoverage() { + // https://unicode-org.atlassian.net/browse/ICU-20708 + IcuTestErrorCode status(*this, "signCoverage"); + const struct TestCase { + UNumberSignDisplay sign; + const char16_t* expectedStrings[8]; + } cases[] = { + { UNUM_SIGN_AUTO, { u"-∞", u"-1", u"-0", u"0", u"1", u"∞", u"NaN", u"-NaN" } }, + { UNUM_SIGN_ALWAYS, { u"-∞", u"-1", u"-0", u"+0", u"+1", u"+∞", u"+NaN", u"-NaN" } }, + { UNUM_SIGN_NEVER, { u"∞", u"1", u"0", u"0", u"1", u"∞", u"NaN", u"NaN" } }, + { UNUM_SIGN_EXCEPT_ZERO, { u"-∞", u"-1", u"-0", u"0", u"+1", u"+∞", u"NaN", u"-NaN" } }, + }; + double negNaN = std::copysign(uprv_getNaN(), -0.0); + const double inputs[] = { + -uprv_getInfinity(), -1, -0.0, 0, 1, uprv_getInfinity(), uprv_getNaN(), negNaN + }; + for (auto& cas : cases) { + auto sign = cas.sign; + for (int32_t i = 0; i < UPRV_LENGTHOF(inputs); i++) { + auto input = inputs[i]; + auto expected = cas.expectedStrings[i]; + auto actual = NumberFormatter::with() + .sign(sign) + .locale(Locale::getUS()) + .formatDouble(input, status) + .toString(status); + assertEquals( + DoubleToUnicodeString(input) + " " + Int64ToUnicodeString(sign), + expected, actual); + } + } +} + void NumberFormatterApiTest::decimal() { assertFormatDescending( u"Decimal Default", @@ -2232,6 +2301,47 @@ assertEquals("Locale withLocale()", u"1\u202f234", actual); } +void NumberFormatterApiTest::skeletonUserGuideExamples() { + IcuTestErrorCode status(*this, "skeletonUserGuideExamples"); + + // Test the skeleton examples in userguide/format_parse/numbers/skeletons.md + struct TestCase { + const char16_t* skeleton; + double input; + const char16_t* expected; + } cases[] = { + {u"percent", 25, u"25%"}, + {u".00", 25, u"25.00"}, + {u"percent .00", 25, u"25.00%"}, + {u"scale/100", 0.3, u"30"}, + {u"percent scale/100", 0.3, u"30%"}, + {u"measure-unit/length-meter", 5, u"5 m"}, + {u"measure-unit/length-meter unit-width-full-name", 5, u"5 meters"}, + {u"currency/CAD", 10, u"CA$10.00"}, + {u"currency/CAD unit-width-narrow", 10, u"$10.00"}, + {u"compact-short", 5000, u"5K"}, + {u"compact-long", 5000, u"5 thousand"}, + {u"compact-short currency/CAD", 5000, u"CA$5K"}, + {u"", 5000, u"5,000"}, + {u"group-min2", 5000, u"5000"}, + {u"group-min2", 15000, u"15,000"}, + {u"sign-always", 60, u"+60"}, + {u"sign-always", 0, u"+0"}, + {u"sign-except-zero", 60, u"+60"}, + {u"sign-except-zero", 0, u"0"}, + {u"sign-accounting currency/CAD", -40, u"(CA$40.00)"} + }; + + for (const auto& cas : cases) { + status.setScope(cas.skeleton); + FormattedNumber actual = NumberFormatter::forSkeleton(cas.skeleton, status) + .locale("en-US") + .formatDouble(cas.input, status); + assertEquals(cas.skeleton, cas.expected, actual.toTempString(status)); + status.errIfFailureAndReset(); + } +} + void NumberFormatterApiTest::formatTypes() { UErrorCode status = U_ZERO_ERROR; LocalizedNumberFormatter formatter = NumberFormatter::withLocale(Locale::getEnglish()); @@ -2711,7 +2821,7 @@ #define EXPECTED_MAX_INT_FRAC_SIG 999 -#define VALID_RANGE_ASSERT(status, method, lowerBound, argument) { \ +#define VALID_RANGE_ASSERT(status, method, lowerBound, argument) UPRV_BLOCK_MACRO_BEGIN { \ UErrorCode expectedStatus = ((lowerBound <= argument) && (argument <= EXPECTED_MAX_INT_FRAC_SIG)) \ ? U_ZERO_ERROR \ : U_NUMBER_ARG_OUTOFBOUNDS_ERROR; \ @@ -2720,17 +2830,17 @@ + Int64ToUnicodeString(argument), \ expectedStatus, \ status); \ -} +} UPRV_BLOCK_MACRO_END -#define VALID_RANGE_ONEARG(setting, method, lowerBound) { \ +#define VALID_RANGE_ONEARG(setting, method, lowerBound) UPRV_BLOCK_MACRO_BEGIN { \ for (int32_t argument = -2; argument <= EXPECTED_MAX_INT_FRAC_SIG + 2; argument++) { \ UErrorCode status = U_ZERO_ERROR; \ NumberFormatter::with().setting(method(argument)).copyErrorTo(status); \ VALID_RANGE_ASSERT(status, method, lowerBound, argument); \ } \ -} +} UPRV_BLOCK_MACRO_END -#define VALID_RANGE_TWOARGS(setting, method, lowerBound) { \ +#define VALID_RANGE_TWOARGS(setting, method, lowerBound) UPRV_BLOCK_MACRO_BEGIN { \ for (int32_t argument = -2; argument <= EXPECTED_MAX_INT_FRAC_SIG + 2; argument++) { \ UErrorCode status = U_ZERO_ERROR; \ /* Pass EXPECTED_MAX_INT_FRAC_SIG as the second argument so arg1 <= arg2 in expected cases */ \ @@ -2746,7 +2856,7 @@ U_NUMBER_ARG_OUTOFBOUNDS_ERROR, \ status); \ } \ -} +} UPRV_BLOCK_MACRO_END VALID_RANGE_ONEARG(precision, Precision::fixedFraction, 0); VALID_RANGE_ONEARG(precision, Precision::minFraction, 0); @@ -2925,6 +3035,18 @@ } } +void NumberFormatterApiTest::toDecimalNumber() { + IcuTestErrorCode status(*this, "toDecimalNumber"); + FormattedNumber fn = NumberFormatter::withLocale("bn-BD") + .scale(Scale::powerOfTen(2)) + .precision(Precision::maxSignificantDigits(5)) + .formatDouble(9.87654321e12, status); + assertEquals("Should have expected localized string result", + u"৯৮,৭৬,৫০,০০,০০,০০,০০০", fn.toString(status)); + assertEquals(u"Should have expected toDecimalNumber string result", + "9.8765E+14", fn.toDecimalNumber(status).c_str()); +} + void NumberFormatterApiTest::assertFormatDescending(const char16_t* umessage, const char16_t* uskeleton, const UnlocalizedNumberFormatter& f, Locale locale, diff -Nru icu-64.2/source/test/intltest/numbertest_decimalquantity.cpp icu-65.1/source/test/intltest/numbertest_decimalquantity.cpp --- icu-64.2/source/test/intltest/numbertest_decimalquantity.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_decimalquantity.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -18,7 +18,7 @@ } TESTCASE_AUTO_BEGIN; TESTCASE_AUTO(testDecimalQuantityBehaviorStandalone); - TESTCASE_AUTO(testSwitchStorage);; + TESTCASE_AUTO(testSwitchStorage); TESTCASE_AUTO(testCopyMove); TESTCASE_AUTO(testAppend); if (!quick) { diff -Nru icu-64.2/source/test/intltest/numbertest.h icu-65.1/source/test/intltest/numbertest.h --- icu-64.2/source/test/intltest/numbertest.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest.h 2019-10-03 11:16:41.000000000 +0000 @@ -6,11 +6,11 @@ #if !UCONFIG_NO_FORMATTING #pragma once -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "intltest.h" #include "itformat.h" #include "number_affixutils.h" -#include "numparse_stringsegment.h" +#include "string_segment.h" #include "numrange_impl.h" #include "unicode/locid.h" #include "unicode/numberformatter.h" @@ -68,9 +68,11 @@ // TODO: Add this method if currency symbols override support is added. //void symbolsOverride(); void sign(); + void signCoverage(); void decimal(); void scale(); void locale(); + void skeletonUserGuideExamples(); void formatTypes(); void fieldPositionLogic(); void fieldPositionCoverage(); @@ -80,6 +82,7 @@ void copyMove(); void localPointerCAPI(); void toObject(); + void toDecimalNumber(); void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0); @@ -173,7 +176,7 @@ UnicodeString expectedChars, UnicodeString expectedFields, UErrorCode &status); - void assertModifierEquals(const Modifier &mod, NumberStringBuilder &sb, int32_t expectedPrefixLength, + void assertModifierEquals(const Modifier &mod, FormattedStringBuilder &sb, int32_t expectedPrefixLength, bool expectedStrong, UnicodeString expectedChars, UnicodeString expectedFields, UErrorCode &status); }; @@ -203,33 +206,6 @@ private: }; -class NumberStringBuilderTest : public IntlTest { - public: - void testInsertAppendUnicodeString(); - void testSplice(); - void testInsertAppendCodePoint(); - void testCopy(); - void testFields(); - void testUnlimitedCapacity(); - void testCodePoints(); - - void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0); - - private: - void assertEqualsImpl(const UnicodeString &a, const NumberStringBuilder &b); -}; - -class StringSegmentTest : public IntlTest { - public: - void testOffset(); - void testLength(); - void testCharAt(); - void testGetCodePoint(); - void testCommonPrefixLength(); - - void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0); -}; - class NumberParserTest : public IntlTest { public: void testBasic(); @@ -312,6 +288,13 @@ const char16_t* expected); }; +class NumberPermutationTest : public IntlTest { + public: + void testPermutations(); + + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0); +}; + // NOTE: This macro is identical to the one in itformat.cpp #define TESTCLASS(id, TestClass) \ @@ -339,12 +322,11 @@ TESTCLASS(3, ModifiersTest); TESTCLASS(4, PatternModifierTest); TESTCLASS(5, PatternStringTest); - TESTCLASS(6, NumberStringBuilderTest); - TESTCLASS(7, DoubleConversionTest); - TESTCLASS(8, StringSegmentTest); - TESTCLASS(9, NumberParserTest); - TESTCLASS(10, NumberSkeletonTest); - TESTCLASS(11, NumberRangeFormatterTest); + TESTCLASS(6, DoubleConversionTest); + TESTCLASS(7, NumberParserTest); + TESTCLASS(8, NumberSkeletonTest); + TESTCLASS(9, NumberRangeFormatterTest); + TESTCLASS(10, NumberPermutationTest); default: name = ""; break; // needed to end loop } } diff -Nru icu-64.2/source/test/intltest/numbertest_modifiers.cpp icu-65.1/source/test/intltest/numbertest_modifiers.cpp --- icu-64.2/source/test/intltest/numbertest_modifiers.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_modifiers.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -7,7 +7,7 @@ #include "putilimp.h" #include "intltest.h" -#include "number_stringbuilder.h" +#include "formatted_string_builder.h" #include "number_modifiers.h" #include "numbertest.h" @@ -36,8 +36,8 @@ void ModifiersTest::testConstantMultiFieldModifier() { UErrorCode status = U_ZERO_ERROR; - NumberStringBuilder prefix; - NumberStringBuilder suffix; + FormattedStringBuilder prefix; + FormattedStringBuilder suffix; ConstantMultiFieldModifier mod1(prefix, suffix, false, true); assertModifierEquals(mod1, 0, true, u"|", u"n", status); assertSuccess("Spot 1", status); @@ -87,7 +87,7 @@ // Test strange insertion positions for (int32_t j = 0; j < NUM_OUTPUTS; j++) { - NumberStringBuilder output; + FormattedStringBuilder output; output.append(outputs[j].baseString, UNUM_FIELD_COUNT, status); mod.apply(output, outputs[j].leftIndex, outputs[j].rightIndex, status); UnicodeString expected = expecteds[j][i]; @@ -105,8 +105,8 @@ return; } - NumberStringBuilder prefix; - NumberStringBuilder suffix; + FormattedStringBuilder prefix; + FormattedStringBuilder suffix; CurrencySpacingEnabledModifier mod1(prefix, suffix, false, true, symbols, status); assertSuccess("Spot 2", status); assertModifierEquals(mod1, 0, true, u"|", u"n", status); @@ -120,15 +120,15 @@ assertSuccess("Spot 6", status); // Test the default currency spacing rules - NumberStringBuilder sb; + FormattedStringBuilder sb; sb.append("123", UNUM_INTEGER_FIELD, status); assertSuccess("Spot 7", status); - NumberStringBuilder sb1(sb); + FormattedStringBuilder sb1(sb); assertModifierEquals(mod2, sb1, 3, true, u"USD\u00A0123", u"$$$niii", status); assertSuccess("Spot 8", status); // Compare with the unsafe code path - NumberStringBuilder sb2(sb); + FormattedStringBuilder sb2(sb); sb2.insert(0, "USD", UNUM_CURRENCY_FIELD, status); assertSuccess("Spot 9", status); CurrencySpacingEnabledModifier::applyCurrencySpacing(sb2, 0, 3, 6, 0, symbols, status); @@ -149,14 +149,14 @@ void ModifiersTest::assertModifierEquals(const Modifier &mod, int32_t expectedPrefixLength, bool expectedStrong, UnicodeString expectedChars, UnicodeString expectedFields, UErrorCode &status) { - NumberStringBuilder sb; + FormattedStringBuilder sb; sb.appendCodePoint('|', UNUM_FIELD_COUNT, status); assertModifierEquals( mod, sb, expectedPrefixLength, expectedStrong, expectedChars, expectedFields, status); } -void ModifiersTest::assertModifierEquals(const Modifier &mod, NumberStringBuilder &sb, +void ModifiersTest::assertModifierEquals(const Modifier &mod, FormattedStringBuilder &sb, int32_t expectedPrefixLength, bool expectedStrong, UnicodeString expectedChars, UnicodeString expectedFields, UErrorCode &status) { @@ -171,7 +171,7 @@ } UnicodeString debugString; - debugString.append(u"apply(nsb1, 0, 0, status); assertSuccess("Spot 3", status); - NumberStringBuilder nsb2; + FormattedStringBuilder nsb2; MicroProps micros2; LocalPointer immutable(mod.createImmutable(status)); immutable->applyToMicros(micros2, fq, status); micros2.modMiddle->apply(nsb2, 0, 0, status); assertSuccess("Spot 4", status); - NumberStringBuilder nsb3; + FormattedStringBuilder nsb3; MicroProps micros3; mod.addToChain(µs3); mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false); @@ -168,14 +168,14 @@ } UnicodeString PatternModifierTest::getPrefix(const MutablePatternModifier &mod, UErrorCode &status) { - NumberStringBuilder nsb; + FormattedStringBuilder nsb; mod.apply(nsb, 0, 0, status); int32_t prefixLength = mod.getPrefixLength(); return UnicodeString(nsb.toUnicodeString(), 0, prefixLength); } UnicodeString PatternModifierTest::getSuffix(const MutablePatternModifier &mod, UErrorCode &status) { - NumberStringBuilder nsb; + FormattedStringBuilder nsb; mod.apply(nsb, 0, 0, status); int32_t prefixLength = mod.getPrefixLength(); return UnicodeString(nsb.toUnicodeString(), prefixLength, nsb.length() - prefixLength); diff -Nru icu-64.2/source/test/intltest/numbertest_permutation.cpp icu-65.1/source/test/intltest/numbertest_permutation.cpp --- icu-64.2/source/test/intltest/numbertest_permutation.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_permutation.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,198 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include +#include +#include + +#include "numbertest.h" +#include "ucbuf.h" +#include "unicode/numberformatter.h" + +void NumberPermutationTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char*) { + if (exec) { + logln("TestSuite NumberPermutationTest: "); + } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(testPermutations); + TESTCASE_AUTO_END; +} + +static const char16_t* kSkeletonParts[] = { + // Notation + u"compact-short", + u"scientific/+ee/sign-always", + nullptr, + // Unit + u"percent", + u"currency/EUR", + u"measure-unit/length-furlong", + nullptr, + // Unit Width + u"unit-width-narrow", + u"unit-width-full-name", + nullptr, + // Precision + u"precision-integer", + u".000", + u".##/@@@+", + u"@@", + nullptr, + // Rounding Mode + u"rounding-mode-floor", + nullptr, + // Integer Width + u"integer-width/##00", + nullptr, + // Scale + u"scale/0.5", + nullptr, + // Grouping + u"group-on-aligned", + nullptr, + // Symbols + u"latin", + nullptr, + // Sign Display + u"sign-accounting-except-zero", + nullptr, + // Decimal Separator Display + u"decimal-always", + nullptr, +}; + +static const double kNumbersToTest[]{0, 91827.3645, -0.22222}; + +/** + * Test permutations of 3 orthogonal skeleton parts from the list above. + * Compare the results against the golden data file: + * numberpermutationtest.txt + * To regenerate that file, run intltest with the -G option. + */ +void NumberPermutationTest::testPermutations() { + IcuTestErrorCode status(*this, "testPermutations"); + + const struct LocaleData { + Locale locale; + const char16_t* ustring; + } localesToTest[] = { + {"es-MX", u"es-MX"}, + {"zh-TW", u"zh-TW"}, + {"bn-BD", u"bn-BD"}, + }; + + // Convert kSkeletonParts to a more convenient data structure + auto skeletonParts = std::vector>(); + auto currentSection = std::vector(); + for (int32_t i = 0; i < UPRV_LENGTHOF(kSkeletonParts); i++) { + const char16_t* skeletonPart = kSkeletonParts[i]; + if (skeletonPart == nullptr) { + skeletonParts.push_back(currentSection); + currentSection.clear(); + } else { + currentSection.push_back(skeletonPart); + } + } + + // Build up the golden data string as we evaluate all permutations + std::vector resultLines; + resultLines.push_back(u"# © 2019 and later: Unicode, Inc. and others."); + resultLines.push_back(u"# License & terms of use: http://www.unicode.org/copyright.html"); + resultLines.push_back(UnicodeString()); + + // Take combinations of 3 orthogonal options + for (size_t i = 0; i < skeletonParts.size() - 2; i++) { + const auto& skeletons1 = skeletonParts[i]; + for (size_t j = i + 1; j < skeletonParts.size() - 1; j++) { + const auto& skeletons2 = skeletonParts[j]; + for (size_t k = j + 1; k < skeletonParts.size(); k++) { + const auto& skeletons3 = skeletonParts[k]; + + // Evaluate all combinations of skeletons for these options + for (const auto& skel1 : skeletons1) { + for (const auto& skel2 : skeletons2) { + for (const auto& skel3 : skeletons3) { + // Compute the skeleton + UnicodeString skeleton; + skeleton + .append(skel1) // + .append(u' ') // + .append(skel2) // + .append(u' ') // + .append(skel3); + resultLines.push_back(skeleton); + + // Check several locales and several numbers in each locale + for (const auto& locData : localesToTest) { + auto lnf = NumberFormatter::forSkeleton(skeleton, status) + .locale(locData.locale); + resultLines.push_back(UnicodeString(u" ").append(locData.ustring)); + for (const auto& input : kNumbersToTest) { + resultLines.push_back(UnicodeString(u" ").append( + lnf.formatDouble(input, status).toTempString(status))); + } + } + + resultLines.push_back(UnicodeString()); + } + } + } + } + + // Quick mode: test all fields at least once but stop early. + if (quick) { + infoln(u"Quick mode: stopped after " + Int64ToUnicodeString(resultLines.size()) + + u" lines"); + goto outerEnd; + } + } + } +outerEnd: + void(); + + CharString goldenFilePath(getSourceTestData(status), status); + goldenFilePath.appendPathPart("numberpermutationtest.txt", status); + + // Compare it to the golden file + const char* codePage = "UTF-8"; + LocalUCHARBUFPointer f(ucbuf_open(goldenFilePath.data(), &codePage, TRUE, FALSE, status)); + if (!assertSuccess("Can't open data file", status)) { + return; + } + + int32_t lineNumber = 1; + int32_t lineLength; + for (const auto& actualLine : resultLines) { + const UChar* lineBuf = ucbuf_readline(f.getAlias(), &lineLength, status); + if (lineBuf == nullptr) { + errln("More lines generated than are in the data file!"); + break; + } + UnicodeString expectedLine(lineBuf, lineLength - 1); + assertEquals(u"Line #" + Int64ToUnicodeString(lineNumber) + u" differs", // + expectedLine, actualLine); + lineNumber++; + } + // Quick mode: test all fields at least once but stop early. + if (!quick && ucbuf_readline(f.getAlias(), &lineLength, status) != nullptr) { + errln("Fewer lines generated than are in the data file!"); + } + + // Overwrite the golden data if requested + if (write_golden_data) { + std::ofstream outFile; + outFile.open(goldenFilePath.data()); + for (const auto& uniLine : resultLines) { + std::string byteLine; + uniLine.toUTF8String(byteLine); + outFile << byteLine << std::endl; + } + outFile.close(); + } +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/numbertest_skeletons.cpp icu-65.1/source/test/intltest/numbertest_skeletons.cpp --- icu-64.2/source/test/intltest/numbertest_skeletons.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_skeletons.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -149,6 +149,8 @@ u"integer-width/xxx", u"integer-width/0+", u"integer-width/+0#", + u"integer-width/+#", + u"integer-width/+#0", u"scientific/foo"}; expectedErrorSkeleton(cases, UPRV_LENGTHOF(cases)); diff -Nru icu-64.2/source/test/intltest/numbertest_stringbuilder.cpp icu-65.1/source/test/intltest/numbertest_stringbuilder.cpp --- icu-64.2/source/test/intltest/numbertest_stringbuilder.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_stringbuilder.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,288 +0,0 @@ -// © 2017 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "putilimp.h" -#include "numbertest.h" - -static const char16_t *EXAMPLE_STRINGS[] = { - u"", - u"xyz", - u"The quick brown fox jumps over the lazy dog", - u"😁", - u"mixed 😇 and ASCII", - u"with combining characters like 🇦🇧🇨🇩", - u"A very very very very very very very very very very long string to force heap"}; - -void NumberStringBuilderTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *) { - if (exec) { - logln("TestSuite NumberStringBuilderTest: "); - } - TESTCASE_AUTO_BEGIN; - TESTCASE_AUTO(testInsertAppendUnicodeString); - TESTCASE_AUTO(testSplice); - TESTCASE_AUTO(testInsertAppendCodePoint); - TESTCASE_AUTO(testCopy); - TESTCASE_AUTO(testFields); - TESTCASE_AUTO(testUnlimitedCapacity); - TESTCASE_AUTO(testCodePoints); - TESTCASE_AUTO_END; -} - -void NumberStringBuilderTest::testInsertAppendUnicodeString() { - UErrorCode status = U_ZERO_ERROR; - UnicodeString sb1; - NumberStringBuilder sb2; - for (const char16_t* strPtr : EXAMPLE_STRINGS) { - UnicodeString str(strPtr); - - NumberStringBuilder sb3; - sb1.append(str); - // Note: UNUM_FIELD_COUNT is like passing null in Java - sb2.append(str, UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb2", status); - sb3.append(str, UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb3", status); - assertEqualsImpl(sb1, sb2); - assertEqualsImpl(str, sb3); - - UnicodeString sb4; - NumberStringBuilder sb5; - sb4.append(u"😇"); - sb4.append(str); - sb4.append(u"xx"); - sb5.append(u"😇xx", UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb5", status); - sb5.insert(2, str, UNUM_FIELD_COUNT, status); - assertSuccess("Inserting into sb5", status); - assertEqualsImpl(sb4, sb5); - - int start = uprv_min(1, str.length()); - int end = uprv_min(10, str.length()); - sb4.insert(3, str, start, end - start); // UnicodeString uses length instead of end index - sb5.insert(3, str, start, end, UNUM_FIELD_COUNT, status); - assertSuccess("Inserting into sb5 again", status); - assertEqualsImpl(sb4, sb5); - - UnicodeString sb4cp(sb4); - NumberStringBuilder sb5cp(sb5); - sb4.append(sb4cp); - sb5.append(sb5cp, status); - assertSuccess("Appending again to sb5", status); - assertEqualsImpl(sb4, sb5); - } -} - -void NumberStringBuilderTest::testSplice() { - static const struct TestCase { - const char16_t* input; - const int32_t startThis; - const int32_t endThis; - } cases[] = { - { u"", 0, 0 }, - { u"abc", 0, 0 }, - { u"abc", 1, 1 }, - { u"abc", 1, 2 }, - { u"abc", 0, 2 }, - { u"abc", 0, 3 }, - { u"lorem ipsum dolor sit amet", 8, 8 }, - { u"lorem ipsum dolor sit amet", 8, 11 }, // 3 chars, equal to replacement "xyz" - { u"lorem ipsum dolor sit amet", 8, 18 } }; // 10 chars, larger than several replacements - - UErrorCode status = U_ZERO_ERROR; - UnicodeString sb1; - NumberStringBuilder sb2; - for (auto cas : cases) { - for (const char16_t* replacementPtr : EXAMPLE_STRINGS) { - UnicodeString replacement(replacementPtr); - - // Test replacement with full string - sb1.remove(); - sb1.append(cas.input); - sb1.replace(cas.startThis, cas.endThis - cas.startThis, replacement); - sb2.clear(); - sb2.append(cas.input, UNUM_FIELD_COUNT, status); - sb2.splice(cas.startThis, cas.endThis, replacement, 0, replacement.length(), UNUM_FIELD_COUNT, status); - assertSuccess("Splicing into sb2 first time", status); - assertEqualsImpl(sb1, sb2); - - // Test replacement with partial string - if (replacement.length() <= 2) { - continue; - } - sb1.remove(); - sb1.append(cas.input); - sb1.replace(cas.startThis, cas.endThis - cas.startThis, UnicodeString(replacement, 1, 2)); - sb2.clear(); - sb2.append(cas.input, UNUM_FIELD_COUNT, status); - sb2.splice(cas.startThis, cas.endThis, replacement, 1, 3, UNUM_FIELD_COUNT, status); - assertSuccess("Splicing into sb2 second time", status); - assertEqualsImpl(sb1, sb2); - } - } -} - -void NumberStringBuilderTest::testInsertAppendCodePoint() { - static const UChar32 cases[] = { - 0, 1, 60, 127, 128, 0x7fff, 0x8000, 0xffff, 0x10000, 0x1f000, 0x10ffff}; - UErrorCode status = U_ZERO_ERROR; - UnicodeString sb1; - NumberStringBuilder sb2; - for (UChar32 cas : cases) { - NumberStringBuilder sb3; - sb1.append(cas); - sb2.appendCodePoint(cas, UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb2", status); - sb3.appendCodePoint(cas, UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb3", status); - assertEqualsImpl(sb1, sb2); - assertEquals("Length of sb3", U16_LENGTH(cas), sb3.length()); - assertEquals("Code point count of sb3", 1, sb3.codePointCount()); - assertEquals( - "First code unit in sb3", - !U_IS_SUPPLEMENTARY(cas) ? (char16_t) cas : U16_LEAD(cas), - sb3.charAt(0)); - - UnicodeString sb4; - NumberStringBuilder sb5; - sb4.append(u"😇xx"); - sb4.insert(2, cas); - sb5.append(u"😇xx", UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb5", status); - sb5.insertCodePoint(2, cas, UNUM_FIELD_COUNT, status); - assertSuccess("Inserting into sb5", status); - assertEqualsImpl(sb4, sb5); - } -} - -void NumberStringBuilderTest::testCopy() { - UErrorCode status = U_ZERO_ERROR; - for (UnicodeString str : EXAMPLE_STRINGS) { - NumberStringBuilder sb1; - sb1.append(str, UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb1 first time", status); - NumberStringBuilder sb2(sb1); - assertTrue("Content should equal itself", sb1.contentEquals(sb2)); - - sb1.append("12345", UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb1 second time", status); - assertFalse("Content should no longer equal itself", sb1.contentEquals(sb2)); - } -} - -void NumberStringBuilderTest::testFields() { - UErrorCode status = U_ZERO_ERROR; - // Note: This is a C++11 for loop that calls the UnicodeString constructor on each iteration. - for (UnicodeString str : EXAMPLE_STRINGS) { - NumberStringBuilder sb; - sb.append(str, UNUM_FIELD_COUNT, status); - assertSuccess("Appending to sb", status); - sb.append(str, UNUM_CURRENCY_FIELD, status); - assertSuccess("Appending to sb", status); - assertEquals("Reference string copied twice", str.length() * 2, sb.length()); - for (int32_t i = 0; i < str.length(); i++) { - assertEquals("Null field first", (Field) UNUM_FIELD_COUNT, sb.fieldAt(i)); - assertEquals("Currency field second", (Field) UNUM_CURRENCY_FIELD, sb.fieldAt(i + str.length())); - } - - // Very basic FieldPosition test. More robust tests happen in NumberFormatTest. - // Let NumberFormatTest also take care of FieldPositionIterator material. - FieldPosition fp(UNUM_CURRENCY_FIELD); - sb.nextFieldPosition(fp, status); - assertSuccess("Populating the FieldPosition", status); - assertEquals("Currency start position", str.length(), fp.getBeginIndex()); - assertEquals("Currency end position", str.length() * 2, fp.getEndIndex()); - - if (str.length() > 0) { - sb.insertCodePoint(2, 100, UNUM_INTEGER_FIELD, status); - assertSuccess("Inserting code point into sb", status); - assertEquals("New length", str.length() * 2 + 1, sb.length()); - assertEquals("Integer field", (Field) UNUM_INTEGER_FIELD, sb.fieldAt(2)); - } - - NumberStringBuilder old(sb); - sb.append(old, status); - assertSuccess("Appending to myself", status); - int32_t numNull = 0; - int32_t numCurr = 0; - int32_t numInt = 0; - for (int32_t i = 0; i < sb.length(); i++) { - Field field = sb.fieldAt(i); - assertEquals("Field should equal location in old", old.fieldAt(i % old.length()), field); - if (field == UNUM_FIELD_COUNT) { - numNull++; - } else if (field == UNUM_CURRENCY_FIELD) { - numCurr++; - } else if (field == UNUM_INTEGER_FIELD) { - numInt++; - } else { - errln("Encountered unknown field"); - } - } - assertEquals("Number of null fields", str.length() * 2, numNull); - assertEquals("Number of currency fields", numNull, numCurr); - assertEquals("Number of integer fields", str.length() > 0 ? 2 : 0, numInt); - } -} - -void NumberStringBuilderTest::testUnlimitedCapacity() { - UErrorCode status = U_ZERO_ERROR; - NumberStringBuilder builder; - // The builder should never fail upon repeated appends. - for (int i = 0; i < 1000; i++) { - UnicodeString message("Iteration #"); - message += Int64ToUnicodeString(i); - assertEquals(message, builder.length(), i); - builder.appendCodePoint(u'x', UNUM_FIELD_COUNT, status); - assertSuccess(message, status); - assertEquals(message, builder.length(), i + 1); - } -} - -void NumberStringBuilderTest::testCodePoints() { - UErrorCode status = U_ZERO_ERROR; - NumberStringBuilder nsb; - assertEquals("First is -1 on empty string", -1, nsb.getFirstCodePoint()); - assertEquals("Last is -1 on empty string", -1, nsb.getLastCodePoint()); - assertEquals("Length is 0 on empty string", 0, nsb.codePointCount()); - - nsb.append(u"q", UNUM_FIELD_COUNT, status); - assertSuccess("Spot 1", status); - assertEquals("First is q", u'q', nsb.getFirstCodePoint()); - assertEquals("Last is q", u'q', nsb.getLastCodePoint()); - assertEquals("0th is q", u'q', nsb.codePointAt(0)); - assertEquals("Before 1st is q", u'q', nsb.codePointBefore(1)); - assertEquals("Code point count is 1", 1, nsb.codePointCount()); - - // 🚀 is two char16s - nsb.append(u"🚀", UNUM_FIELD_COUNT, status); - assertSuccess("Spot 2" ,status); - assertEquals("First is still q", u'q', nsb.getFirstCodePoint()); - assertEquals("Last is space ship", 128640, nsb.getLastCodePoint()); - assertEquals("1st is space ship", 128640, nsb.codePointAt(1)); - assertEquals("Before 1st is q", u'q', nsb.codePointBefore(1)); - assertEquals("Before 3rd is space ship", 128640, nsb.codePointBefore(3)); - assertEquals("Code point count is 2", 2, nsb.codePointCount()); -} - -void NumberStringBuilderTest::assertEqualsImpl(const UnicodeString &a, const NumberStringBuilder &b) { - // TODO: Why won't this compile without the IntlTest:: qualifier? - IntlTest::assertEquals("Lengths should be the same", a.length(), b.length()); - IntlTest::assertEquals("Code point counts should be the same", a.countChar32(), b.codePointCount()); - - if (a.length() != b.length()) { - return; - } - - for (int32_t i = 0; i < a.length(); i++) { - IntlTest::assertEquals( - UnicodeString(u"Char at position ") + Int64ToUnicodeString(i) + - UnicodeString(u" in \"") + a + UnicodeString("\" versus \"") + - b.toUnicodeString() + UnicodeString("\""), a.charAt(i), b.charAt(i)); - } -} - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/numbertest_stringsegment.cpp icu-65.1/source/test/intltest/numbertest_stringsegment.cpp --- icu-64.2/source/test/intltest/numbertest_stringsegment.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numbertest_stringsegment.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -// © 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "numbertest.h" -#include "numparse_stringsegment.h" - -static const char16_t* SAMPLE_STRING = u"📻 radio 📻"; - -void StringSegmentTest::runIndexedTest(int32_t index, UBool exec, const char*&name, char*) { - if (exec) { - logln("TestSuite StringSegmentTest: "); - } - TESTCASE_AUTO_BEGIN; - TESTCASE_AUTO(testOffset); - TESTCASE_AUTO(testLength); - TESTCASE_AUTO(testCharAt); - TESTCASE_AUTO(testGetCodePoint); - TESTCASE_AUTO(testCommonPrefixLength); - TESTCASE_AUTO_END; -} - -void StringSegmentTest::testOffset() { - // Note: sampleString needs function scope so it is valid while the StringSegment is valid - UnicodeString sampleString(SAMPLE_STRING); - StringSegment segment(sampleString, false); - assertEquals("Initial Offset", 0, segment.getOffset()); - segment.adjustOffset(3); - assertEquals("Adjust A", 3, segment.getOffset()); - segment.adjustOffset(2); - assertEquals("Adjust B", 5, segment.getOffset()); - segment.setOffset(4); - assertEquals("Set Offset", 4, segment.getOffset()); -} - -void StringSegmentTest::testLength() { - // Note: sampleString needs function scope so it is valid while the StringSegment is valid - UnicodeString sampleString(SAMPLE_STRING); - StringSegment segment(sampleString, false); - assertEquals("Initial length", 11, segment.length()); - segment.adjustOffset(3); - assertEquals("Adjust", 8, segment.length()); - segment.setLength(4); - assertEquals("Set Length", 4, segment.length()); - segment.setOffset(5); - assertEquals("After adjust offset", 2, segment.length()); - segment.resetLength(); - assertEquals("After reset length", 6, segment.length()); -} - -void StringSegmentTest::testCharAt() { - // Note: sampleString needs function scope so it is valid while the StringSegment is valid - UnicodeString sampleString(SAMPLE_STRING); - StringSegment segment(sampleString, false); - assertEquals("Initial", SAMPLE_STRING, segment.toUnicodeString()); - assertEquals("Initial", SAMPLE_STRING, segment.toTempUnicodeString()); - segment.adjustOffset(3); - assertEquals("After adjust-offset", UnicodeString(u"radio 📻"), segment.toUnicodeString()); - assertEquals("After adjust-offset", UnicodeString(u"radio 📻"), segment.toTempUnicodeString()); - segment.setLength(5); - assertEquals("After adjust-length", UnicodeString(u"radio"), segment.toUnicodeString()); - assertEquals("After adjust-length", UnicodeString(u"radio"), segment.toTempUnicodeString()); -} - -void StringSegmentTest::testGetCodePoint() { - // Note: sampleString needs function scope so it is valid while the StringSegment is valid - UnicodeString sampleString(SAMPLE_STRING); - StringSegment segment(sampleString, false); - assertEquals("Double-width code point", 0x1F4FB, segment.getCodePoint()); - segment.setLength(1); - assertEquals("Inalid A", -1, segment.getCodePoint()); - segment.resetLength(); - segment.adjustOffset(1); - assertEquals("Invalid B", -1, segment.getCodePoint()); - segment.adjustOffset(1); - assertEquals("Valid again", 0x20, segment.getCodePoint()); -} - -void StringSegmentTest::testCommonPrefixLength() { - // Note: sampleString needs function scope so it is valid while the StringSegment is valid - UnicodeString sampleString(SAMPLE_STRING); - StringSegment segment(sampleString, false); - assertEquals("", 11, segment.getCommonPrefixLength(SAMPLE_STRING)); - assertEquals("", 4, segment.getCommonPrefixLength(u"📻 r")); - assertEquals("", 3, segment.getCommonPrefixLength(u"📻 x")); - assertEquals("", 0, segment.getCommonPrefixLength(u"x")); - segment.adjustOffset(3); - assertEquals("", 0, segment.getCommonPrefixLength(u"RADiO")); - assertEquals("", 5, segment.getCommonPrefixLength(u"radio")); - assertEquals("", 2, segment.getCommonPrefixLength(u"rafio")); - assertEquals("", 0, segment.getCommonPrefixLength(u"fadio")); - segment.setLength(3); - assertEquals("", 3, segment.getCommonPrefixLength(u"radio")); - assertEquals("", 2, segment.getCommonPrefixLength(u"rafio")); - assertEquals("", 0, segment.getCommonPrefixLength(u"fadio")); - segment.resetLength(); - segment.setOffset(11); // end of string - assertEquals("", 0, segment.getCommonPrefixLength(u"foo")); -} - -#endif diff -Nru icu-64.2/source/test/intltest/numfmtst.cpp icu-65.1/source/test/intltest/numfmtst.cpp --- icu-64.2/source/test/intltest/numfmtst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numfmtst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -81,8 +81,18 @@ // class NumberFormatTest // ***************************************************************************** -#define CHECK(status,str) if (U_FAILURE(status)) { errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); return; } -#define CHECK_DATA(status,str) if (U_FAILURE(status)) { dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); return; } +#define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END +#define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { @@ -169,6 +179,7 @@ TESTCASE_AUTO(TestRoundingScientific10542); TESTCASE_AUTO(TestZeroScientific10547); TESTCASE_AUTO(TestAccountingCurrency); + TESTCASE_AUTO(TestCurrencyFormatForMissingLocale); TESTCASE_AUTO(TestEquality); TESTCASE_AUTO(TestCurrencyUsage); TESTCASE_AUTO(TestDoubleLimit11439); @@ -287,7 +298,7 @@ class StubNumberFormat :public NumberFormat{ public: - StubNumberFormat(){}; + StubNumberFormat(){} virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const { return appendTo; } @@ -310,7 +321,7 @@ static char classID = 0; return (UClassID)&classID; } - virtual Format* clone() const {return NULL;} + virtual StubNumberFormat* clone() const {return NULL;} }; void @@ -321,7 +332,7 @@ int64_t num = 4; if (stub.format(num, agent, pos) != UnicodeString("agent3")){ errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)"); - }; + } } void NumberFormatTest::TestLocalizedPatternSymbolCoverage() { @@ -2213,7 +2224,7 @@ errln("CurrencyUnit copy constructed object should be same"); } - CurrencyUnit * cu3 = (CurrencyUnit *)cu.clone(); + CurrencyUnit * cu3 = cu.clone(); if (!(*cu3 == cu)){ errln("CurrencyUnit cloned object should be same"); } @@ -2281,7 +2292,7 @@ errln("CurrencyAmount assigned object should be same"); } - CurrencyAmount *ca3 = (CurrencyAmount *)ca.clone(); + CurrencyAmount *ca3 = ca.clone(); if (!(*ca3 == ca)){ errln("CurrencyAmount cloned object should be same"); } @@ -3172,7 +3183,7 @@ dataerrln("FAIL: Status %s", u_errorName(status)); return; } - cloneObj = (MeasureFormat *)measureObj->clone(); + cloneObj = measureObj->clone(); if (cloneObj == NULL) { errln("Clone doesn't work"); return; @@ -3482,7 +3493,7 @@ continue; } // Clone to test ticket #10682 - NumberFormat *fmt = (NumberFormat *) origFmt->clone(); + NumberFormat *fmt = origFmt->clone(); delete origFmt; @@ -3543,9 +3554,9 @@ {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"}, {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"}, // for CHINA locale - {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\uFFE51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"}, - {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\uFFE51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"}, - {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\uFFE51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"} + {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"}, + {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"}, + {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"} }; const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0}; @@ -3760,8 +3771,8 @@ {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"}, {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"}, {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"}, - {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"}, - {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"}, + {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"}, + {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"}, {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}, {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}, {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}, @@ -3864,7 +3875,7 @@ {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"}, {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"}, {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"}, - {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"}, + {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"}, {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"}, {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"}, {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"}, @@ -6743,12 +6754,12 @@ // API test, not a comprehensive test. // See DecimalFormatTest/DataDrivenTests // -#define ASSERT_SUCCESS(status) { \ +#define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \ -} -#define ASSERT_EQUALS(expected, actual) { \ +} UPRV_BLOCK_MACRO_END +#define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \ assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \ -} +} UPRV_BLOCK_MACRO_END void NumberFormatTest::TestDecimal() { { @@ -7003,7 +7014,7 @@ void NumberFormatTest::TestAvailableNumberingSystems() { IcuTestErrorCode status(*this, "TestAvailableNumberingSystems"); StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status); - CHECK_DATA(status, "NumberingSystem::getAvailableNames()") + CHECK_DATA(status, "NumberingSystem::getAvailableNames()"); int32_t nsCount = availableNumberingSystems->count(status); if ( nsCount < 74 ) { @@ -7473,7 +7484,7 @@ Locale locale("en_US"); LocalPointer numberFormat(static_cast( NumberFormat::createInstance(locale, status))); - CHECK_DATA(status,"NumberFormat::createInstance") + CHECK_DATA(status,"NumberFormat::createInstance"); numberFormat->setSignificantDigitsUsed(TRUE); numberFormat->setMinimumSignificantDigits(3); @@ -7526,7 +7537,7 @@ Locale locale("en_US"); LocalPointer numberFormat(static_cast( NumberFormat::createInstance(locale, status))); - CHECK_DATA(status, "NumberFormat::createInstance") + CHECK_DATA(status, "NumberFormat::createInstance"); numberFormat->setSignificantDigitsUsed(TRUE); numberFormat->setMaximumSignificantDigits(3); @@ -7577,7 +7588,7 @@ void NumberFormatTest::TestParseNegativeWithFaLocale() { UErrorCode status = U_ZERO_ERROR; DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status); - CHECK_DATA(status, "NumberFormat::createInstance") + CHECK_DATA(status, "NumberFormat::createInstance"); test->setLenient(TRUE); Formattable af; ParsePosition ppos; @@ -7593,7 +7604,7 @@ void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() { UErrorCode status = U_ZERO_ERROR; DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status); - CHECK_DATA(status, "NumberFormat::createInstance") + CHECK_DATA(status, "NumberFormat::createInstance"); test->setLenient(TRUE); Formattable af; ParsePosition ppos; @@ -8014,6 +8025,52 @@ (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status); expect(NumberFormat::createInstance("de_DE", style, status), (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status); + expect(NumberFormat::createInstance("en_ID", style, status), + (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status); + expect(NumberFormat::createInstance("en_ID", style, status), + (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status); + expect(NumberFormat::createInstance("sh_ME", style, status), + (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status); + expect(NumberFormat::createInstance("sh_ME", style, status), + (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status); +} + +/** + * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression. + * + * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but + * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was + * used instead of the desired locale's currency. + */ +void NumberFormatTest::TestCurrencyFormatForMissingLocale() { + IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale"); + Locale locale = Locale::createCanonical("sh_ME"); + + LocalPointer curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status)); + // Fail here with missing data. + if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;}; + assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR"); + UnicodeString currBuf; + curFmt->format(-1234.5, currBuf); + assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf); + + LocalPointer accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status)); + assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR"); + UnicodeString accBuf; + accFmt->format(-1234.5, accBuf); + assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf); + + LocalPointer cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status)); + assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR"); + UnicodeString cashBuf; + cashFmt->format(-1234.5, cashBuf); + assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf); + + LocalPointer stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status)); + assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR"); + UnicodeString stdBuf; + stdFmt->format(-1234.5, stdBuf); + assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf); } // for #5186 @@ -8031,7 +8088,7 @@ return; } - DecimalFormat* fmtClone = (DecimalFormat*)fmtBase.clone(); + DecimalFormat* fmtClone = fmtBase.clone(); fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32); if (*fmtClone == fmtBase) { errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth"); diff -Nru icu-64.2/source/test/intltest/numfmtst.h icu-65.1/source/test/intltest/numfmtst.h --- icu-64.2/source/test/intltest/numfmtst.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numfmtst.h 2019-10-03 11:16:41.000000000 +0000 @@ -231,6 +231,7 @@ void TestRoundingScientific10542(); void TestZeroScientific10547(); void TestAccountingCurrency(); + void TestCurrencyFormatForMissingLocale(); void TestEquality(); void TestCurrencyUsage(); diff -Nru icu-64.2/source/test/intltest/numrgts.cpp icu-65.1/source/test/intltest/numrgts.cpp --- icu-64.2/source/test/intltest/numrgts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/numrgts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -78,7 +78,7 @@ { NumberFormat::parse(text, result, status); } - virtual Format* clone() const + virtual MyNumberFormatTest* clone() const { return NULL; } virtual UnicodeString& format(int32_t, @@ -850,15 +850,15 @@ void NumberFormatRegressionTest::Test4087244 (void) { UErrorCode status = U_ZERO_ERROR; char loc[256] = {0}; + uloc_canonicalize("pt_PT@currency=PTE", loc, 256, &status); - Locale *de = new Locale(loc); - NumberFormat *nf = NumberFormat::createCurrencyInstance(*de, status); + Locale de(loc); + LocalPointer nf(NumberFormat::createCurrencyInstance(de, status)); if(U_FAILURE(status)) { - dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); - delete nf; - return; + dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); + return; } - DecimalFormat *df = dynamic_cast(nf); + DecimalFormat *df = dynamic_cast(nf.getAlias()); if(df == NULL) { errln("expected DecimalFormat!"); return; @@ -887,8 +887,6 @@ monStr + "\" and not \"" + decStr + '"'); } - delete de; - delete nf; } /* @bug 4070798 * Number format data rounding errors for locale FR @@ -998,7 +996,7 @@ if (failure(status, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE)){ delete formatter; return; - }; + } tempString = formatter->format (-5789.9876, tempString); if (tempString == expectedDefault) { @@ -1132,7 +1130,7 @@ if (failure(status, "NumberFormat::createNumberInstance", TRUE)){ delete formatter; return; - }; + } tempString = formatter->format (-5789.9876, tempString); if (tempString == expectedDefault) { @@ -1942,7 +1940,7 @@ if (failure(status, "NumberFormat::createInstance", TRUE)){ delete nff; return; - }; + } DecimalFormat *nf = dynamic_cast(nff); if(nf == NULL) { errln("DecimalFormat needed to continue"); @@ -2185,7 +2183,7 @@ if (failure(status, "NumberFormat::createInstance", TRUE)){ delete fmt; return; - }; + } double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf UnicodeString s; @@ -2515,7 +2513,7 @@ if (failure(status, "createInstance", Locale::getUS(), TRUE)){ delete fmt; return; - }; + } int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 }; int DATA_length = UPRV_LENGTHOF(DATA); for (int i=0; isetMaximumFractionDigits(2); for (int i=0; isetMinimumFractionDigits(1); nf->setMaximumFractionDigits(1); double a = -0.09; @@ -2681,18 +2679,18 @@ Locale loc("fr", "CH"); // set up the input date string & expected output - UnicodeString udt("11.10.2000", ""); - UnicodeString exp("11.10.00", ""); + UnicodeString udt(u"11.10.2000"); + UnicodeString exp(u"11.10.00"); // create a Calendar for this locale - Calendar *cal = Calendar::createInstance(loc, status); + LocalPointer cal(Calendar::createInstance(loc, status)); if (U_FAILURE(status)) { dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status)); return; } // create a NumberFormat for this locale - NumberFormat *nf = NumberFormat::createInstance(loc, status); + LocalPointer nf(NumberFormat::createInstance(loc, status)); if (U_FAILURE(status)) { dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); return; @@ -2705,14 +2703,14 @@ // so they are done in DateFormat::adoptNumberFormat // create the DateFormat - DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc); + LocalPointer df(DateFormat::createDateInstance(DateFormat::kShort, loc)); if (U_FAILURE(status)) { errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); return; } - df->adoptCalendar(cal); - df->adoptNumberFormat(nf); + df->adoptCalendar(cal.orphan()); + df->adoptNumberFormat(nf.orphan()); // set parsing to lenient & parse df->setLenient(TRUE); @@ -2725,8 +2723,6 @@ if (outString != exp) { errln("FAIL: " + udt + " => " + outString); } - - delete df; } //--------------------------------------------------------------------------- @@ -2734,27 +2730,28 @@ // Error Checking / Reporting macros // //--------------------------------------------------------------------------- -#define TEST_CHECK_STATUS(status) { \ +#define TEST_CHECK_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \ if (U_FAILURE(status)) { \ if (status == U_MISSING_RESOURCE_ERROR) { \ dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \ } else { \ errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \ } return; \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define TEST_ASSERT(expr) \ +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ if ((expr)==FALSE) {\ errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\ - } -#define TEST_ASSERT_EQUALS(x,y) \ - { \ + } \ +} UPRV_BLOCK_MACRO_END +#define TEST_ASSERT_EQUALS(x,y) UPRV_BLOCK_MACRO_BEGIN { \ char _msg[1000]; \ int32_t len = sprintf (_msg,"File %s, line %d: " #x "==" #y, __FILE__, __LINE__); \ (void)len; \ U_ASSERT(len < (int32_t) sizeof(_msg)); \ assertEquals((const char*) _msg, x,y); \ - } +} UPRV_BLOCK_MACRO_END // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18 @@ -2911,7 +2908,7 @@ if (failure(status, "NumberFormat::createInstance", TRUE)){ delete nf; return; - }; + } DecimalFormat *df = dynamic_cast(nf); if(df == NULL) { errln("DecimalFormat needed to continue"); @@ -3025,7 +3022,6 @@ errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status)); status = U_ZERO_ERROR; } else { -; if(n!=-123456789) { errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n); } else { diff -Nru icu-64.2/source/test/intltest/plurfmts.cpp icu-65.1/source/test/intltest/plurfmts.cpp --- icu-64.2/source/test/intltest/plurfmts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/plurfmts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -124,7 +124,7 @@ } if ( U_SUCCESS(status[1]) ) { - plFmt[2] = (PluralFormat*) plFmt[1]->clone(); + plFmt[2] = plFmt[1]->clone(); if (plFmt[1]!=NULL) { if ( *plFmt[1] != *plFmt[2] ) { @@ -194,7 +194,7 @@ UErrorCode status = U_ZERO_ERROR; UnicodeString oddAndEvenRule = UNICODE_STRING_SIMPLE("odd: n mod 2 is 1"); - PluralRules* plRules = PluralRules::createRules(oddAndEvenRule, status); + LocalPointerplRules(PluralRules::createRules(oddAndEvenRule, status)); if (U_FAILURE(status)) { dataerrln("ERROR: create PluralRules instance failed in unit tests.- exitting"); return; @@ -223,7 +223,7 @@ status = U_ZERO_ERROR; UBool overwrite[PLURAL_PATTERN_DATA] = {FALSE, FALSE, TRUE, TRUE}; - NumberFormat *numFmt = NumberFormat::createInstance(status); + LocalPointer numFmt(NumberFormat::createInstance(status)); UnicodeString message=UnicodeString("ERROR: PluralFormat tests various pattern ..."); if (U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat instance with default locale "); @@ -240,37 +240,33 @@ errln("ERROR: PluralFormat failed to apply pattern- "+patternTestData[i]); continue; } - numberFormatTest(&plFmt, numFmt, 1, 10, (UnicodeString *)&patternOddTestResult[i], + numberFormatTest(&plFmt, numFmt.getAlias(), 1, 10, (UnicodeString *)&patternOddTestResult[i], (UnicodeString *)&patternEvenTestResult[i], overwrite[i], &message); } - delete plRules; - delete numFmt; // ======= Test set locale status = U_ZERO_ERROR; - plRules = PluralRules::createRules(UNICODE_STRING_SIMPLE("odd: n mod 2 is 1"), status); + plRules.adoptInstead(PluralRules::createRules(UNICODE_STRING_SIMPLE("odd: n mod 2 is 1"), status)); PluralFormat pluralFmt = PluralFormat(*plRules, status); if (U_FAILURE(status)) { dataerrln("ERROR: Could not create PluralFormat instance in setLocale() test - exitting. "); - delete plRules; return; } pluralFmt.applyPattern(UNICODE_STRING_SIMPLE("odd{odd} other{even}"), status); pluralFmt.setLocale(Locale::getEnglish(), status); if (U_FAILURE(status)) { dataerrln("ERROR: Could not setLocale() with English locale "); - delete plRules; return; } message = UNICODE_STRING_SIMPLE("Error set locale: pattern is not reset!"); // Check that pattern gets deleted. logln("\n Test setLocale() ..\n"); - numFmt = NumberFormat::createInstance(Locale::getEnglish(), status); + numFmt.adoptInstead(NumberFormat::createInstance(Locale::getEnglish(), status)); if (U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat instance with English locale "); } - numberFormatTest(&pluralFmt, numFmt, 5, 5, NULL, NULL, FALSE, &message); + numberFormatTest(&pluralFmt, numFmt.getAlias(), 5, 5, NULL, NULL, FALSE, &message); pluralFmt.applyPattern(UNICODE_STRING_SIMPLE("odd__{odd} other{even}"), status); if (pluralFmt.format((int32_t)1, status) != UNICODE_STRING_SIMPLE("even")) { errln("SetLocale should reset rules but did not."); @@ -302,9 +298,6 @@ if (pluralFmt != dupPFmt) { errln("Failed in PluralFormat copy constructor or == operator"); } - - delete plRules; - delete numFmt; } diff -Nru icu-64.2/source/test/intltest/plurults.cpp icu-65.1/source/test/intltest/plurults.cpp --- icu-64.2/source/test/intltest/plurults.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/plurults.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -69,9 +69,9 @@ US(const UnicodeString &us) { int32_t bufLen = us.extract((int32_t)0, us.length(), (char *)NULL, (uint32_t)0) + 1; buf = (char *)uprv_malloc(bufLen); - us.extract(0, us.length(), buf, bufLen); }; - const char *cstr() {return buf;}; - ~US() { uprv_free(buf);}; + us.extract(0, us.length(), buf, bufLen); } + const char *cstr() {return buf;} + ~US() { uprv_free(buf);} }; @@ -1037,12 +1037,34 @@ } } +void PluralRulesTest::compareLocaleResults(const char* loc1, const char* loc2, const char* loc3) { + UErrorCode status = U_ZERO_ERROR; + LocalPointer rules1(PluralRules::forLocale(loc1, status)); + LocalPointer rules2(PluralRules::forLocale(loc2, status)); + LocalPointer rules3(PluralRules::forLocale(loc3, status)); + if (U_FAILURE(status)) { + dataerrln("Failed to create PluralRules for one of %s, %s, %s: %s\n", loc1, loc2, loc3, u_errorName(status)); + return; + } + for (int32_t value = 0; value <= 12; value++) { + UnicodeString result1 = rules1->select(value); + UnicodeString result2 = rules2->select(value); + UnicodeString result3 = rules3->select(value); + if (result1 != result2 || result1 != result3) { + errln("PluralRules.select(%d) does not return the same values for %s, %s, %s\n", value, loc1, loc2, loc3); + } + } +} + void PluralRulesTest::testLocaleExtension() { IcuTestErrorCode errorCode(*this, "testLocaleExtension"); LocalPointer rules(PluralRules::forLocale("pt@calendar=gregorian", errorCode)); if (errorCode.errIfFailureAndReset("PluralRules::forLocale()")) { return; } UnicodeString key = rules->select(1); assertEquals("pt@calendar=gregorian select(1)", u"one", key); + compareLocaleResults("ar", "ar_SA", "ar_SA@calendar=gregorian"); + compareLocaleResults("ru", "ru_UA", "ru-u-cu-RUB"); + compareLocaleResults("fr", "fr_CH", "fr@ms=uksystem"); } #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/plurults.h icu-65.1/source/test/intltest/plurults.h --- icu-64.2/source/test/intltest/plurults.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/plurults.h 2019-10-03 11:16:41.000000000 +0000 @@ -45,6 +45,7 @@ double expected); void checkSelect(const LocalPointer &rules, UErrorCode &status, int32_t line, const char *keyword, ...); + void compareLocaleResults(const char* loc1, const char* loc2, const char* loc3); }; #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/pptest.cpp icu-65.1/source/test/intltest/pptest.cpp --- icu-64.2/source/test/intltest/pptest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/pptest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -182,7 +182,7 @@ if (failure(status, "NumberFormat::createInstance", TRUE)){ delete nf; return; - }; + } DecimalFormat *fmt = dynamic_cast(nf); if(fmt == NULL) { diff -Nru icu-64.2/source/test/intltest/quantityformattertest.cpp icu-65.1/source/test/intltest/quantityformattertest.cpp --- icu-64.2/source/test/intltest/quantityformattertest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/quantityformattertest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -17,6 +17,12 @@ #include "unicode/numfmt.h" #include "unicode/plurrule.h" +#define ASSERT_OK(status) UPRV_BLOCK_MACRO_BEGIN { \ + if(U_FAILURE(status)) { \ + errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END class QuantityFormatterTest : public IntlTest { public: @@ -117,6 +123,7 @@ NumberFormat::createInstance(Locale::getEnglish(), status)); LocalPointer plurrule( PluralRules::forLocale("en", status)); + ASSERT_OK(status); FieldPosition pos(FieldPosition::DONT_CARE); UnicodeString appendTo; assertEquals( diff -Nru icu-64.2/source/test/intltest/rbbiapts.cpp icu-65.1/source/test/intltest/rbbiapts.cpp --- icu-64.2/source/test/intltest/rbbiapts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/rbbiapts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -34,11 +34,17 @@ */ -#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) {\ -dataerrln("Failure at file %s, line %d, error = %s", __FILE__, __LINE__, u_errorName(status));}} - -#define TEST_ASSERT(expr) {if ((expr) == FALSE) { \ - errln("Test Failure at file %s, line %d: \"%s\" is false.\n", __FILE__, __LINE__, #expr);};} +#define TEST_ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + dataerrln("Failure at file %s, line %d, error = %s", __FILE__, __LINE__, u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr) == FALSE) { \ + errln("Test Failure at file %s, line %d: \"%s\" is false.\n", __FILE__, __LINE__, #expr); \ + } \ +} UPRV_BLOCK_MACRO_END void RBBIAPITest::TestCloneEquals() { @@ -126,8 +132,8 @@ logln((UnicodeString)"Testing clone()"); - RuleBasedBreakIterator* bi1clone = dynamic_cast(bi1->clone()); - RuleBasedBreakIterator* bi2clone = dynamic_cast(bi2->clone()); + RuleBasedBreakIterator* bi1clone = bi1->clone(); + RuleBasedBreakIterator* bi2clone = bi2->clone(); if(*bi1clone != *bi1 || *bi1clone != *biequal || *bi1clone == *bi3 || *bi1clone == *bi2) @@ -197,7 +203,7 @@ UnicodeString text(u"Hello there"); bi1->setText(text); - LocalPointer bi3((RuleBasedBreakIterator*)bi1->clone()); + LocalPointer bi3(bi1->clone()); UnicodeString temp=bi1->getRules(); UnicodeString temp2=bi2->getRules(); @@ -232,8 +238,8 @@ bi2->setText((UnicodeString)"Hash code"); bi3->setText((UnicodeString)"Hash code"); - RuleBasedBreakIterator* bi1clone= (RuleBasedBreakIterator*)bi1->clone(); - RuleBasedBreakIterator* bi2clone= (RuleBasedBreakIterator*)bi2->clone(); + RuleBasedBreakIterator* bi1clone= bi1->clone(); + RuleBasedBreakIterator* bi2clone= bi2->clone(); if(bi1->hashCode() != bi1clone->hashCode() || bi1->hashCode() != bi3->hashCode() || bi1clone->hashCode() != bi3->hashCode() || bi2->hashCode() != bi2clone->hashCode()) @@ -294,7 +300,7 @@ TEST_ASSERT(tstr == str1); - LocalPointer rb((RuleBasedBreakIterator*)wordIter1->clone()); + LocalPointer rb(wordIter1->clone()); rb->adoptText(text1); if(rb->getText() != *text1) errln((UnicodeString)"ERROR:1 error in adoptText "); @@ -1041,7 +1047,7 @@ __FILE__, __LINE__, u_errorName(status), parseError.line, parseError.offset); errln(UnicodeString(builtSource)); return; - }; + } rbbiRules = brkItr->getBinaryRules(length); logln("Comparing \"%s\" len=%d", dataFile, length); if (memcmp(builtRules, rbbiRules, (int32_t)length) != 0) { diff -Nru icu-64.2/source/test/intltest/rbbimonkeytest.cpp icu-65.1/source/test/intltest/rbbimonkeytest.cpp --- icu-64.2/source/test/intltest/rbbimonkeytest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/rbbimonkeytest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -135,13 +135,13 @@ printf("epandedDef: %s\n", CStr(expandedDef)()); } - UnicodeSet *s = new UnicodeSet(expandedDef, USET_IGNORE_SPACE, NULL, status); + LocalPointer s(new UnicodeSet(expandedDef, USET_IGNORE_SPACE, NULL, status), status); if (U_FAILURE(status)) { - IntlTest::gTest->errln("%s:%d: error %s creating UnicodeSet %s", __FILE__, __LINE__, - u_errorName(status), CStr(name)()); - return NULL; + IntlTest::gTest->errln("%s:%d: error %s creating UnicodeSet %s\n Expanded set definition: %s", + __FILE__, __LINE__, u_errorName(status), CStr(name)(), CStr(expandedDef)()); + return nullptr; } - CharClass *cclass = new CharClass(name, definition, expandedDef, s); + CharClass *cclass = new CharClass(name, definition, expandedDef, s.orphan()); CharClass *previousClass = static_cast(uhash_put(fCharClasses.getAlias(), new UnicodeString(name), // Key, owned by hash table. cclass, // Value, owned by hash table. @@ -660,12 +660,12 @@ } -#define MONKEY_ERROR(msg, index) { \ +#define MONKEY_ERROR(msg, index) UPRV_BLOCK_MACRO_BEGIN { \ IntlTest::gTest->errln("%s:%d %s at index %d. Parameters to reproduce: @rules=%s,seed=%u,loop=1,verbose ", \ __FILE__, __LINE__, msg, index, fRuleFileName, fTestData->fRandomSeed); \ if (fVerbose) { fTestData->dump(index); } \ status = U_INVALID_STATE_ERROR; \ -} +} UPRV_BLOCK_MACRO_END void RBBIMonkeyImpl::runTest() { UErrorCode status = U_ZERO_ERROR; diff -Nru icu-64.2/source/test/intltest/rbbimonkeytest.h icu-65.1/source/test/intltest/rbbimonkeytest.h --- icu-64.2/source/test/intltest/rbbimonkeytest.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/rbbimonkeytest.h 2019-10-03 11:16:41.000000000 +0000 @@ -148,8 +148,8 @@ class MonkeyTestData: public UObject { public: - MonkeyTestData() {}; - ~MonkeyTestData() {}; + MonkeyTestData() {} + ~MonkeyTestData() {} void set(BreakRules *rules, IntlTest::icu_rand &rand, UErrorCode &status); void clearActualBreaks(); void dump(int32_t around = -1) const; @@ -216,8 +216,8 @@ private: RBBIMonkeyImpl *fMonkeyImpl; public: - RBBIMonkeyThread(RBBIMonkeyImpl *impl) : fMonkeyImpl(impl) {}; - void run() U_OVERRIDE { fMonkeyImpl->runTest(); }; + RBBIMonkeyThread(RBBIMonkeyImpl *impl) : fMonkeyImpl(impl) {} + void run() U_OVERRIDE { fMonkeyImpl->runTest(); } }; private: void openBreakRules(const char *fileName, UErrorCode &status); diff -Nru icu-64.2/source/test/intltest/rbbitst.cpp icu-65.1/source/test/intltest/rbbitst.cpp --- icu-64.2/source/test/intltest/rbbitst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/rbbitst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -51,11 +51,17 @@ #include "unicode/filteredbrk.h" #endif // !UCONFIG_NO_FILTERED_BREAK_ITERATION -#define TEST_ASSERT(x) {if (!(x)) { \ - errln("Failure in file %s, line %d", __FILE__, __LINE__);}} - -#define TEST_ASSERT_SUCCESS(errcode) { if (U_FAILURE(errcode)) { \ - errcheckln(errcode, "Failure in file %s, line %d, status = \"%s\"", __FILE__, __LINE__, u_errorName(errcode));}} +#define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(x)) { \ + errln("Failure in file %s, line %d", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_SUCCESS(errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(errcode)) { \ + errcheckln(errcode, "Failure in file %s, line %d, status = \"%s\"", __FILE__, __LINE__, u_errorName(errcode)); \ + } \ +} UPRV_BLOCK_MACRO_END //--------------------------------------------- // runIndexedTest @@ -736,7 +742,7 @@ int32_t tagValue = 0; // The numeric value of a tag. UnicodeString rules; // Holds rules from a ... block - int32_t rulesFirstLine; // Line number of the start of current block + int32_t rulesFirstLine = 0; // Line number of the start of current block for (charIdx = 0; charIdx < len; ) { status = U_ZERO_ERROR; @@ -1237,7 +1243,7 @@ delete []retPtr; retPtr = 0; ulen = 0; - }; + } return retPtr; } @@ -1611,6 +1617,9 @@ UnicodeSet *fLVTSet; UnicodeSet *fHangulSet; UnicodeSet *fExtendedPictSet; + UnicodeSet *fViramaSet; + UnicodeSet *fLinkingConsonantSet; + UnicodeSet *fExtCccZwjSet; UnicodeSet *fAnySet; const UnicodeString *fText; @@ -1643,6 +1652,11 @@ fHangulSet->addAll(*fLVTSet); fExtendedPictSet = new UnicodeSet(u"[:Extended_Pictographic:]", status); + fViramaSet = new UnicodeSet(u"[\\p{Gujr}\\p{sc=Telu}\\p{sc=Mlym}\\p{sc=Orya}\\p{sc=Beng}\\p{sc=Deva}&" + "\\p{Indic_Syllabic_Category=Virama}]", status); + fLinkingConsonantSet = new UnicodeSet(u"[\\p{Gujr}\\p{sc=Telu}\\p{sc=Mlym}\\p{sc=Orya}\\p{sc=Beng}\\p{sc=Deva}&" + "\\p{Indic_Syllabic_Category=Consonant}]", status); + fExtCccZwjSet = new UnicodeSet(u"[[\\p{gcb=Extend}-\\p{ccc=0}] \\p{gcb=ZWJ}]", status); fAnySet = new UnicodeSet(0, 0x10ffff); fSets = new UVector(status); @@ -1658,6 +1672,9 @@ fSets->addElement(fAnySet, status); fSets->addElement(fZWJSet, status); fSets->addElement(fExtendedPictSet, status); + fSets->addElement(fViramaSet, status); + fSets->addElement(fLinkingConsonantSet, status); + fSets->addElement(fExtCccZwjSet, status); if (U_FAILURE(status)) { deferredStatus = status; } @@ -1777,6 +1794,22 @@ continue; } + // Rule (GB9.3) LinkingConsonant ExtCccZwj* Virama ExtCccZwj* × LinkingConsonant + // Note: Viramas are also included in the ExtCccZwj class. + if (fLinkingConsonantSet->contains(c2)) { + int pi = p1; + bool sawVirama = false; + while (pi > 0 && fExtCccZwjSet->contains(fText->char32At(pi))) { + if (fViramaSet->contains(fText->char32At(pi))) { + sawVirama = true; + } + pi = fText->moveIndex32(pi, -1); + } + if (sawVirama && fLinkingConsonantSet->contains(fText->char32At(pi))) { + continue; + } + } + // Rule (GB11) Extended_Pictographic Extend * ZWJ x Extended_Pictographic if (fExtendedPictSet->contains(cBase) && fZWJSet->contains(c1) && fExtendedPictSet->contains(c2)) { continue; @@ -1827,7 +1860,9 @@ delete fAnySet; delete fZWJSet; delete fExtendedPictSet; -} + delete fViramaSet; + delete fLinkingConsonantSet; + delete fExtCccZwjSet;} //------------------------------------------------------------------------------------------ // @@ -2004,7 +2039,7 @@ c3 = fText->char32At(p3); if (fCRSet->contains(c2) || fLFSet->contains(c2) || fNewlineSet->contains(c2)) { break; - }; + } } while (fFormatSet->contains(c3) || fExtendSet->contains(c3) || fZWJSet->contains(c3)); @@ -2030,10 +2065,10 @@ // if (fCRSet->contains(c1) || fLFSet->contains(c1) || fNewlineSet->contains(c1)) { break; - }; + } if (fCRSet->contains(c2) || fLFSet->contains(c2) || fNewlineSet->contains(c2)) { break; - }; + } // Rule (3c) ZWJ x Extended_Pictographic // Not ignoring extend chars, so peek into input text to @@ -4397,11 +4432,11 @@ assertTrue(WHERE, Locale::getFrench() == biFr->getLocale(ULOC_VALID_LOCALE, status)); assertTrue(WHERE "Locales do not participate in BreakIterator equality.", *biEn == *biFr); - LocalPointercloneEn((RuleBasedBreakIterator *)biEn->clone()); + LocalPointercloneEn(biEn->clone()); assertTrue(WHERE, *biEn == *cloneEn); assertTrue(WHERE, Locale::getEnglish() == cloneEn->getLocale(ULOC_VALID_LOCALE, status)); - LocalPointercloneFr((RuleBasedBreakIterator *)biFr->clone()); + LocalPointercloneFr(biFr->clone()); assertTrue(WHERE, *biFr == *cloneFr); assertTrue(WHERE, Locale::getFrench() == cloneFr->getLocale(ULOC_VALID_LOCALE, status)); diff -Nru icu-64.2/source/test/intltest/regcoll.cpp icu-65.1/source/test/intltest/regcoll.cpp --- icu-64.2/source/test/intltest/regcoll.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/regcoll.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -142,7 +142,7 @@ { const UChar chars3[] = {0x61, 0x00FC, 0x62, 0x65, 0x63, 0x6b, 0x20, 0x47, 0x72, 0x00F6, 0x00DF, 0x65, 0x20, 0x4c, 0x00FC, 0x62, 0x63, 0x6b, 0}; const UnicodeString test3(chars3); - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); // NOTE: The Java code uses en_us to create the CollationElementIterators // but I'm pretty sure that's wrong, so I've changed this to use c. @@ -184,7 +184,7 @@ UErrorCode status = U_ZERO_ERROR; - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::IDENTICAL); @@ -201,7 +201,7 @@ void CollationRegressionTest::Test4054736(/* char* par */) { UErrorCode status = U_ZERO_ERROR; - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::SECONDARY); c->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status); @@ -425,11 +425,11 @@ // NOTE: The java code used en_us to create the // CollationElementIterator's. I'm pretty sure that // was wrong, so I've change the code to use c1 and c2 - RuleBasedCollator *c1 = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c1 = en_us->clone(); c1->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status); CollationElementIterator *i1 = c1->createCollationElementIterator(test1); - RuleBasedCollator *c2 = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c2 = en_us->clone(); c2->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_OFF, status); CollationElementIterator *i2 = c2->createCollationElementIterator(test2); @@ -495,7 +495,7 @@ static const UChar s1[] = {0x41, 0x0301, 0x0302, 0x0300, 0}; static const UChar s2[] = {0x41, 0x0302, 0x0300, 0x0301, 0}; - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::TERTIARY); if (c->compare(s1,s2) == 0) @@ -573,7 +573,7 @@ static const UChar s2[] = {0x41, 0x0327, 0x0316, 0x0315, 0x0300, 0}; UErrorCode status = U_ZERO_ERROR; - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::TERTIARY); // Now that the default collators are set to NO_DECOMPOSITION @@ -628,7 +628,7 @@ // void CollationRegressionTest::Test4087243(/* char* par */) { - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::TERTIARY); static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] = @@ -738,7 +738,7 @@ // void CollationRegressionTest::Test4103436(/* char* par */) { - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::TERTIARY); static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] = @@ -759,7 +759,7 @@ void CollationRegressionTest::Test4114076(/* char* par */) { UErrorCode status = U_ZERO_ERROR; - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::TERTIARY); // @@ -884,7 +884,7 @@ // as we do with it on.... UErrorCode status = U_ZERO_ERROR; - RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *c = en_us->clone(); c->setStrength(Collator::TERTIARY); static const UChar test1[][CollationRegressionTest::MAX_TOKEN_LEN] = @@ -1253,7 +1253,7 @@ } void CollationRegressionTest::TestCaseFirstCompression() { - RuleBasedCollator *col = (RuleBasedCollator *) en_us->clone(); + RuleBasedCollator *col = en_us->clone(); UErrorCode status = U_ZERO_ERROR; // default diff -Nru icu-64.2/source/test/intltest/regextst.cpp icu-65.1/source/test/intltest/regextst.cpp --- icu-64.2/source/test/intltest/regextst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/regextst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -177,29 +177,56 @@ return ASSERT_BUF; } -#define REGEX_VERBOSE_TEXT(text) {char buf[200];utextToPrintable(buf,UPRV_LENGTHOF(buf),text);logln("%s:%d: UText %s=\"%s\"", __FILE__, __LINE__, #text, buf);} - -#define REGEX_CHECK_STATUS {if (U_FAILURE(status)) {dataerrln("%s:%d: RegexTest failure. status=%s", \ - __FILE__, __LINE__, u_errorName(status)); return;}} - -#define REGEX_ASSERT(expr) {if ((expr)==FALSE) {errln("%s:%d: RegexTest failure: REGEX_ASSERT(%s) failed \n", __FILE__, __LINE__, #expr);};} - -#define REGEX_ASSERT_FAIL(expr, errcode) {UErrorCode status=U_ZERO_ERROR; (expr);\ -if (status!=errcode) {dataerrln("RegexTest failure at line %d. Expected status=%s, got %s", \ - __LINE__, u_errorName(errcode), u_errorName(status));};} - -#define REGEX_CHECK_STATUS_L(line) {if (U_FAILURE(status)) {errln( \ - "RegexTest failure at line %d, from %d. status=%d\n",__LINE__, (line), status); }} - -#define REGEX_ASSERT_L(expr, line) {if ((expr)==FALSE) { \ - errln("RegexTest failure at line %d, from %d.", __LINE__, (line)); return;}} +#define REGEX_VERBOSE_TEXT(text) UPRV_BLOCK_MACRO_BEGIN { \ + char buf[200]; \ + utextToPrintable(buf,UPRV_LENGTHOF(buf),text); \ + logln("%s:%d: UText %s=\"%s\"", __FILE__, __LINE__, #text, buf); \ +} UPRV_BLOCK_MACRO_END + +#define REGEX_CHECK_STATUS UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + dataerrln("%s:%d: RegexTest failure. status=%s", \ + __FILE__, __LINE__, u_errorName(status)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define REGEX_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("%s:%d: RegexTest failure: REGEX_ASSERT(%s) failed \n", __FILE__, __LINE__, #expr); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define REGEX_ASSERT_FAIL(expr, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + UErrorCode status=U_ZERO_ERROR; \ + (expr); \ + if (status!=errcode) { \ + dataerrln("RegexTest failure at line %d. Expected status=%s, got %s", \ + __LINE__, u_errorName(errcode), u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define REGEX_CHECK_STATUS_L(line) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + errln("RegexTest failure at line %d, from %d. status=%d\n",__LINE__, (line), status); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define REGEX_ASSERT_L(expr, line) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expr)==FALSE) { \ + errln("RegexTest failure at line %d, from %d.", __LINE__, (line)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END // expected: const char * , restricted to invariant characters. // actual: const UnicodeString & -#define REGEX_ASSERT_UNISTR(expected, actual) { \ +#define REGEX_ASSERT_UNISTR(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \ if (UnicodeString(expected, -1, US_INV) != (actual)) { \ errln("%s:%d: RegexTest failure: REGEX_ASSERT_UNISTR(%s, %s) failed \n", \ - __FILE__, __LINE__, expected, extractToAssertBuf(actual));};} + __FILE__, __LINE__, expected, extractToAssertBuf(actual)); \ + } \ +} UPRV_BLOCK_MACRO_END static UBool testUTextEqual(UText *uta, UText *utb) { @@ -329,7 +356,10 @@ // //--------------------------------------------------------------------------- -#define REGEX_TESTLM(pat, text, looking, match) {doRegexLMTest(pat, text, looking, match, __LINE__);doRegexLMTestUTF8(pat, text, looking, match, __LINE__);} +#define REGEX_TESTLM(pat, text, looking, match) UPRV_BLOCK_MACRO_BEGIN { \ + doRegexLMTest(pat, text, looking, match, __LINE__); \ + doRegexLMTestUTF8(pat, text, looking, match, __LINE__); \ +} UPRV_BLOCK_MACRO_END UBool RegexTest::doRegexLMTest(const char *pat, const char *text, UBool looking, UBool match, int32_t line) { const UnicodeString pattern(pat, -1, US_INV); @@ -481,7 +511,7 @@ // REGEX_ERR("pattern", expected error line, column, expected status); // //--------------------------------------------------------------------------- -#define REGEX_ERR(pat, line, col, status) regex_err(pat, line, col, status, __LINE__); +#define REGEX_ERR(pat, line, col, status) regex_err(pat, line, col, status, __LINE__) void RegexTest::regex_err(const char *pat, int32_t errLine, int32_t errCol, UErrorCode expectedStatus, int32_t line) { @@ -3495,11 +3525,16 @@ } } parseMatcher->appendTail(deTaggedInput); - REGEX_ASSERT_L(groupStarts.size() == groupEnds.size(), line); + + if (groupStarts.size() != groupEnds.size()) { + errln("Error at line %d: mismatched group tags in expected results.", line); + failed = true; + goto cleanupAndReturn; + } if ((regionStart>=0 || regionEnd>=0) && (regionStart<0 || regionStart>regionEnd)) { - errln("mismatched tags"); - failed = TRUE; - goto cleanupAndReturn; + errln("mismatched tags"); + failed = TRUE; + goto cleanupAndReturn; } // @@ -3928,7 +3963,7 @@ delete []retPtr; retPtr = 0; ulen = 0; - }; + } return retPtr; } @@ -4755,7 +4790,7 @@ int32_t maxCalls; int32_t numCalls; int32_t lastSteps; - void reset(int32_t max) {maxCalls=max; numCalls=0; lastSteps=0;}; + void reset(int32_t max) {maxCalls=max; numCalls=0; lastSteps=0;} }; U_CDECL_BEGIN @@ -4858,7 +4893,7 @@ int64_t lastIndex; int32_t maxCalls; int32_t numCalls; - void reset(int32_t max) {maxCalls=max; numCalls=0;lastIndex=0;}; + void reset(int32_t max) {maxCalls=max; numCalls=0;lastIndex=0;} }; // call-back function for find(). diff -Nru icu-64.2/source/test/intltest/reldatefmttest.cpp icu-65.1/source/test/intltest/reldatefmttest.cpp --- icu-64.2/source/test/intltest/reldatefmttest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/reldatefmttest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -286,6 +286,8 @@ {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_FRIDAY, "this Friday"}, {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SATURDAY, "this Saturday"}, {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, "this Sunday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_HOUR, "this hour"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MINUTE, "this minute"}, {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_DAY, "day"}, {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEEK, "week"}, @@ -299,6 +301,8 @@ {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_FRIDAY, "Friday"}, {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SATURDAY, "Saturday"}, {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, "Sunday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_HOUR, "hour"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MINUTE, "minute"}, {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, "now"} }; @@ -623,11 +627,11 @@ {0.5, UDAT_REL_UNIT_SECOND, "in 0.5 seconds"}, {1.0, UDAT_REL_UNIT_SECOND, "in 1 second"}, {2.0, UDAT_REL_UNIT_SECOND, "in 2 seconds"}, - {0.0, UDAT_REL_UNIT_MINUTE, "in 0 minutes"}, + {0.0, UDAT_REL_UNIT_MINUTE, "this minute"}, {0.5, UDAT_REL_UNIT_MINUTE, "in 0.5 minutes"}, {1.0, UDAT_REL_UNIT_MINUTE, "in 1 minute"}, {2.0, UDAT_REL_UNIT_MINUTE, "in 2 minutes"}, - {0.0, UDAT_REL_UNIT_HOUR, "in 0 hours"}, + {0.0, UDAT_REL_UNIT_HOUR, "this hour"}, {0.5, UDAT_REL_UNIT_HOUR, "in 0.5 hours"}, {1.0, UDAT_REL_UNIT_HOUR, "in 1 hour"}, {2.0, UDAT_REL_UNIT_HOUR, "in 2 hours"}, @@ -684,11 +688,11 @@ {-0.5, UDAT_REL_UNIT_SECOND, "0.5 seconds ago"}, {-1.0, UDAT_REL_UNIT_SECOND, "1 second ago"}, {-2.0, UDAT_REL_UNIT_SECOND, "2 seconds ago"}, - {-0.0, UDAT_REL_UNIT_MINUTE, "0 minutes ago"}, + {-0.0, UDAT_REL_UNIT_MINUTE, "this minute"}, {-0.5, UDAT_REL_UNIT_MINUTE, "0.5 minutes ago"}, {-1.0, UDAT_REL_UNIT_MINUTE, "1 minute ago"}, {-2.0, UDAT_REL_UNIT_MINUTE, "2 minutes ago"}, - {-0.0, UDAT_REL_UNIT_HOUR, "0 hours ago"}, + {-0.0, UDAT_REL_UNIT_HOUR, "this hour"}, {-0.5, UDAT_REL_UNIT_HOUR, "0.5 hours ago"}, {-1.0, UDAT_REL_UNIT_HOUR, "1 hour ago"}, {-2.0, UDAT_REL_UNIT_HOUR, "2 hours ago"}, @@ -742,6 +746,26 @@ {-2.0, UDAT_REL_UNIT_SATURDAY, "2 Saturdays ago"} }; +static WithQuantityExpected kAfrikaans[] = { + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "oor 1 maand"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "oor 2 maande"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "1 maand gelede"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "2 maande gelede"}, +}; + +static WithoutQuantityExpected kAfrikaansNoQuantity[] = { + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONTH, "volgende maand"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONTH, "verlede maand"}, +}; + +static WithQuantityExpectedRelativeDateTimeUnit kAfrikaansFormatNumeric[] = { + {0.0, UDAT_REL_UNIT_MONTH, "oor 0 maande"}, + {1.0, UDAT_REL_UNIT_MONTH, "oor 1 maand"}, + {2.0, UDAT_REL_UNIT_MONTH, "oor 2 maande"}, + {-0.0, UDAT_REL_UNIT_MONTH, "0 maande gelede"}, + {-1.0, UDAT_REL_UNIT_MONTH, "1 maand gelede"}, + {-2.0, UDAT_REL_UNIT_MONTH, "2 maande gelede"}, +}; class RelativeDateTimeFormatterTest : public IntlTestWithFieldPosition { public: @@ -761,6 +785,7 @@ void TestEnglishNoQuantityShort(); void TestEnglishNoQuantityNarrow(); void TestSpanishNoQuantity(); + void TestAfrikaans(); void TestFormatWithQuantityIllegalArgument(); void TestFormatWithoutQuantityIllegalArgument(); void TestCustomNumberFormat(); @@ -853,6 +878,7 @@ TESTCASE_AUTO(TestEnglishNoQuantityShort); TESTCASE_AUTO(TestEnglishNoQuantityNarrow); TESTCASE_AUTO(TestSpanishNoQuantity); + TESTCASE_AUTO(TestAfrikaans); TESTCASE_AUTO(TestFormatWithQuantityIllegalArgument); TESTCASE_AUTO(TestFormatWithoutQuantityIllegalArgument); TESTCASE_AUTO(TestCustomNumberFormat); @@ -951,6 +977,12 @@ RunTest("es", kSpanishNoQuantity, UPRV_LENGTHOF(kSpanishNoQuantity)); } +void RelativeDateTimeFormatterTest::TestAfrikaans() { + RunTest("af", kAfrikaans, UPRV_LENGTHOF(kAfrikaans)); + RunTest("af", kAfrikaansNoQuantity, UPRV_LENGTHOF(kAfrikaansNoQuantity)); + RunTest("af", kAfrikaansFormatNumeric, UPRV_LENGTHOF(kAfrikaansFormatNumeric), true); +} + void RelativeDateTimeFormatterTest::TestFormatWithQuantityIllegalArgument() { UErrorCode status = U_ZERO_ERROR; RelativeDateTimeFormatter fmt("en", status); @@ -984,7 +1016,7 @@ "Failure creating format object - %s", u_errorName(status)); return; } - nf = (NumberFormat *) fmt.getNumberFormat().clone(); + nf = fmt.getNumberFormat().clone(); } nf->setMinimumFractionDigits(1); nf->setMaximumFractionDigits(1); @@ -1284,7 +1316,7 @@ fmt.format(-3.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, actual.remove(), status); assertEquals("3 days ago (negative 3.0): ", expected, actual); - expected = "next yr."; + expected = "next yr"; fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_YEAR, actual.remove(), status); assertEquals("next year: ", expected, actual); @@ -1294,7 +1326,7 @@ expected = "now"; fmtshort.format(0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, actual.remove(), status); - expected = "next yr."; + expected = "next yr"; fmt.format(UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_YEAR, actual.remove(), status); assertEquals("next year: ", expected, actual); } diff -Nru icu-64.2/source/test/intltest/reptest.cpp icu-65.1/source/test/intltest/reptest.cpp --- icu-64.2/source/test/intltest/reptest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/reptest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -71,7 +71,7 @@ this->styles = s; } - virtual Replaceable *clone() const { + virtual TestReplaceable *clone() const { return new TestReplaceable(chars, styles); } @@ -289,7 +289,7 @@ pe, status); // test clone() - TestReplaceable *tr2 = (TestReplaceable *)tr->clone(); + TestReplaceable *tr2 = tr->clone(); if(tr2 != NULL) { delete tr; tr = tr2; diff -Nru icu-64.2/source/test/intltest/restest.cpp icu-65.1/source/test/intltest/restest.cpp --- icu-64.2/source/test/intltest/restest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/restest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -37,11 +37,35 @@ //*************************************************************************************** -#define CONFIRM_EQ(actual, expected, myAction) if ((expected)==(actual)) { record_pass(myAction); } else { record_fail(myAction + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of " + (expected) + "\n");} -#define CONFIRM_GE(actual, expected, myAction) if ((actual)>=(expected)) { record_pass(myAction); } else { record_fail(myAction + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x >= " + (expected) + "\n");} -#define CONFIRM_NE(actual, expected, myAction) if ((expected)!=(actual)) { record_pass(myAction); } else { record_fail(myAction + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x != " + (expected) + "\n");} +#define CONFIRM_EQ(actual, expected, myAction) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)==(actual)) { \ + record_pass(myAction); \ + } else { \ + record_fail(myAction + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of " + (expected) + "\n"); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_GE(actual, expected, myAction) UPRV_BLOCK_MACRO_BEGIN { \ + if ((actual)>=(expected)) { \ + record_pass(myAction); \ + } else { \ + record_fail(myAction + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x >= " + (expected) + "\n"); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_NE(actual, expected, myAction) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)!=(actual)) { \ + record_pass(myAction); \ + } else { \ + record_fail(myAction + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x != " + (expected) + "\n"); \ + } \ +} UPRV_BLOCK_MACRO_END -#define CONFIRM_UErrorCode(actual, expected, myAction) if ((expected)==(actual)) { record_pass(myAction); } else { record_fail(myAction + (UnicodeString)" returned " + u_errorName(actual) + " instead of " + u_errorName(expected) + "\n"); } +#define CONFIRM_UErrorCode(actual, expected, myAction) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)==(actual)) { \ + record_pass(myAction); \ + } else { \ + record_fail(myAction + (UnicodeString)" returned " + u_errorName(actual) + " instead of " + u_errorName(expected) + "\n"); \ + } \ +} UPRV_BLOCK_MACRO_END //*************************************************************************************** diff -Nru icu-64.2/source/test/intltest/restsnew.cpp icu-65.1/source/test/intltest/restsnew.cpp --- icu-64.2/source/test/intltest/restsnew.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/restsnew.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -11,12 +11,42 @@ #include "cstring.h" #include "unicode/unistr.h" #include "unicode/resbund.h" +#include "unicode/brkiter.h" +#include "unicode/utrace.h" +#include "unicode/ucurr.h" #include "restsnew.h" #include #include #include #include +#include +#include + +//*************************************************************************************** + +void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) +{ + if (exec) logln("TestSuite ResourceBundleTest: "); + TESTCASE_AUTO_BEGIN; + +#if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION + TESTCASE_AUTO(TestResourceBundles); + TESTCASE_AUTO(TestConstruction); + TESTCASE_AUTO(TestIteration); + TESTCASE_AUTO(TestOtherAPI); + TESTCASE_AUTO(TestNewTypes); +#endif + + TESTCASE_AUTO(TestGetByFallback); + TESTCASE_AUTO(TestFilter); + +#if U_ENABLE_TRACING + TESTCASE_AUTO(TestTrace); +#endif + + TESTCASE_AUTO_END; +} //*************************************************************************************** @@ -36,11 +66,39 @@ //*************************************************************************************** -#define CONFIRM_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of " + (expected)); } -#define CONFIRM_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x >= " + (expected)); } -#define CONFIRM_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x != " + (expected)); } +#define CONFIRM_EQ(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)==(actual)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of " + (expected)); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_GE(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((actual)>=(expected)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x >= " + (expected)); \ + } \ +} UPRV_BLOCK_MACRO_END +#define CONFIRM_NE(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)!=(actual)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x != " + (expected)); \ + } \ +} UPRV_BLOCK_MACRO_END -#define CONFIRM_UErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (UnicodeString)u_errorName(actual) + (UnicodeString)" instead of " + (UnicodeString)u_errorName(expected)); } +#define CONFIRM_UErrorCode(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \ + if ((expected)==(actual)) { \ + record_pass(); \ + } else { \ + record_fail(); \ + errln(action + (UnicodeString)" returned " + (UnicodeString)u_errorName(actual) + (UnicodeString)" instead of " + (UnicodeString)u_errorName(expected)); \ + } \ +} UPRV_BLOCK_MACRO_END //*************************************************************************************** @@ -180,27 +238,6 @@ } } -void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) -{ - if (exec) logln("TestSuite ResourceBundleTest: "); - switch (index) { -#if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION - case 0: name = "TestResourceBundles"; if (exec) TestResourceBundles(); break; - case 1: name = "TestConstruction"; if (exec) TestConstruction(); break; - case 2: name = "TestIteration"; if (exec) TestIteration(); break; - case 3: name = "TestOtherAPI"; if(exec) TestOtherAPI(); break; - case 4: name = "TestNewTypes"; if(exec) TestNewTypes(); break; -#else - case 0: case 1: case 2: case 3: case 4: name = "skip"; break; -#endif - - case 5: name = "TestGetByFallback"; if(exec) TestGetByFallback(); break; - case 6: name = "TestFilter"; if(exec) TestFilter(); break; - - default: name = ""; break; //needed to end loop - } -} - //*************************************************************************************** void @@ -1202,17 +1239,17 @@ } -#define REQUIRE_SUCCESS(status) { \ +#define REQUIRE_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ if (status.errIfFailureAndReset("line %d", __LINE__)) { \ return; \ } \ -} +} UPRV_BLOCK_MACRO_END -#define REQUIRE_ERROR(expected, status) { \ +#define REQUIRE_ERROR(expected, status) UPRV_BLOCK_MACRO_BEGIN { \ if (!status.expectErrorAndReset(expected, "line %d", __LINE__)) { \ return; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Tests the --filterDir option in genrb. @@ -1261,13 +1298,11 @@ assertEquals("fornia", fornia.getType(), URES_TABLE); { + // Filter: hawaii should not be included based on parent inheritance ResourceBundle hawaii = fornia.get("hawaii", status); - REQUIRE_SUCCESS(status); - assertEquals("hawaii", hawaii.getType(), URES_STRING); - assertEquals("hawaii", u"idaho", hawaii.getString(status)); - REQUIRE_SUCCESS(status); + REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status); - // Filter: illinois should not be included + // Filter: illinois should not be included based on direct rule ResourceBundle illinois = fornia.get("illinois", status); REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status); } @@ -1341,7 +1376,101 @@ REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status); } } + + // Filter: northCarolina should be included based on direct rule, + // and so should its child, northDakota + ResourceBundle northCarolina = rb.get("northCarolina", status); + REQUIRE_SUCCESS(status); + assertEquals("northCarolina", northCarolina.getType(), URES_TABLE); + + { + ResourceBundle northDakota = northCarolina.get("northDakota", status); + REQUIRE_SUCCESS(status); + assertEquals("northDakota", northDakota.getType(), URES_STRING); + assertEquals("northDakota", u"west-virginia", northDakota.getString(status)); + REQUIRE_SUCCESS(status); + } +} + +#if U_ENABLE_TRACING + +static std::vector gResourcePathsTraced; +static std::vector gDataFilesTraced; +static std::vector gBundlesTraced; + +static void U_CALLCONV traceData( + const void*, + int32_t fnNumber, + int32_t, + const char *, + va_list args) { + + // NOTE: Whether this test is run in isolation affects whether or not + // *.res files are opened. For stability, ignore *.res file opens. + + if (fnNumber == UTRACE_UDATA_RESOURCE) { + va_arg(args, const char*); // type + va_arg(args, const char*); // file + const char* resourcePath = va_arg(args, const char*); + gResourcePathsTraced.push_back(resourcePath); + } else if (fnNumber == UTRACE_UDATA_BUNDLE) { + const char* filePath = va_arg(args, const char*); + gBundlesTraced.push_back(filePath); + } else if (fnNumber == UTRACE_UDATA_DATA_FILE) { + const char* filePath = va_arg(args, const char*); + gDataFilesTraced.push_back(filePath); + } else if (fnNumber == UTRACE_UDATA_RES_FILE) { + // ignore + } +} + +void NewResourceBundleTest::TestTrace() { + IcuTestErrorCode status(*this, "TestTrace"); + + assertEquals("Start position stability coverage", 0x3000, UTRACE_UDATA_START); + + const void* context; + utrace_setFunctions(context, nullptr, nullptr, traceData); + utrace_setLevel(UTRACE_VERBOSE); + + { + LocalPointer brkitr(BreakIterator::createWordInstance("zh-CN", status)); + + assertEquals("Should touch expected resource paths", + { "/boundaries", "/boundaries/word", "/boundaries/word" }, + gResourcePathsTraced); + assertEquals("Should touch expected resource bundles", + { U_ICUDATA_NAME "-brkitr/zh.res" }, + gBundlesTraced); + assertEquals("Should touch expected data files", + { U_ICUDATA_NAME "-brkitr/word.brk" }, + gDataFilesTraced); + gResourcePathsTraced.clear(); + gDataFilesTraced.clear(); + gBundlesTraced.clear(); + } + + { + ucurr_getDefaultFractionDigits(u"USD", status); + + assertEquals("Should touch expected resource paths", + { "/CurrencyMeta", "/CurrencyMeta/DEFAULT", "/CurrencyMeta/DEFAULT" }, + gResourcePathsTraced); + assertEquals("Should touch expected resource bundles", + { U_ICUDATA_NAME "-curr/supplementalData.res" }, + gBundlesTraced); + assertEquals("Should touch expected data files", + { }, + gDataFilesTraced); + gResourcePathsTraced.clear(); + gDataFilesTraced.clear(); + gBundlesTraced.clear(); + } + + utrace_setFunctions(context, nullptr, nullptr, nullptr); } +#endif + //eof diff -Nru icu-64.2/source/test/intltest/restsnew.h icu-65.1/source/test/intltest/restsnew.h --- icu-64.2/source/test/intltest/restsnew.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/restsnew.h 2019-10-03 11:16:41.000000000 +0000 @@ -40,6 +40,10 @@ void TestFilter(void); +#if U_ENABLE_TRACING + void TestTrace(void); +#endif + private: /** * The assignment operator has no real implementation. diff -Nru icu-64.2/source/test/intltest/selfmts.cpp icu-65.1/source/test/intltest/selfmts.cpp --- icu-64.2/source/test/intltest/selfmts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/selfmts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -23,8 +23,13 @@ #define EXP_FORMAT_RESULT_DATA 12 #define NUM_OF_FORMAT_ARGS 3 -#define VERBOSE_INT(x) {logln("%s:%d: int %s=%d\n", __FILE__, __LINE__, #x, (x));} -#define VERBOSE_USTRING(text) {logln("%s:%d: UnicodeString %s(%d) = ", __FILE__, __LINE__, #text, text.length()); logln(UnicodeString(" \"")+text+UnicodeString("\";"));} +#define VERBOSE_INT(x) UPRV_BLOCK_MACRO_BEGIN { \ + logln("%s:%d: int %s=%d\n", __FILE__, __LINE__, #x, (x)); \ +} UPRV_BLOCK_MACRO_END +#define VERBOSE_USTRING(text) UPRV_BLOCK_MACRO_BEGIN { \ + logln("%s:%d: UnicodeString %s(%d) = ", __FILE__, __LINE__, #text, text.length()); \ + logln(UnicodeString(" \"")+text+UnicodeString("\";")); \ +} UPRV_BLOCK_MACRO_END void SelectFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) @@ -230,7 +235,7 @@ // ======= Test clone && == operator. logln("SelectFormat API test: Testing clone and == operator ..."); if ( U_SUCCESS(status[0]) ) { - selFmt[1] = (SelectFormat*)selFmt[0]->clone(); + selFmt[1] = selFmt[0]->clone(); if (selFmt[1]!=NULL) { if ( *selFmt[1] != *selFmt[0] ) { errln("ERROR: SelectFormat API test clone test failed!"); diff -Nru icu-64.2/source/test/intltest/simplethread.cpp icu-65.1/source/test/intltest/simplethread.cpp --- icu-64.2/source/test/intltest/simplethread.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/simplethread.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -36,7 +36,7 @@ class ThreadPoolThread: public SimpleThread { public: - ThreadPoolThread(ThreadPoolBase *pool, int32_t threadNum) : fPool(pool), fNum(threadNum) {}; + ThreadPoolThread(ThreadPoolBase *pool, int32_t threadNum) : fPool(pool), fNum(threadNum) {} virtual void run() {fPool->callFn(fNum); } ThreadPoolBase *fPool; int32_t fNum; diff -Nru icu-64.2/source/test/intltest/simplethread.h icu-65.1/source/test/intltest/simplethread.h --- icu-64.2/source/test/intltest/simplethread.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/simplethread.h 2019-10-03 11:16:41.000000000 +0000 @@ -76,8 +76,8 @@ void (TestClass::*fRunFnPtr)(int32_t); public: ThreadPool(TestClass *test, int howMany, void (TestClass::*runFnPtr)(int32_t threadNumber)) : - ThreadPoolBase(test, howMany), fRunFnPtr(runFnPtr) {}; - virtual ~ThreadPool() {}; + ThreadPoolBase(test, howMany), fRunFnPtr(runFnPtr) {} + virtual ~ThreadPool() {} private: virtual void callFn(int32_t param) { TestClass *test = dynamic_cast(fIntlTest); diff -Nru icu-64.2/source/test/intltest/srchtest.cpp icu-65.1/source/test/intltest/srchtest.cpp --- icu-64.2/source/test/intltest/srchtest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/srchtest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -769,7 +769,7 @@ } delete copy; - copy = (StringSearch *)result->safeClone(); + copy = result->safeClone(); if (*(copy->getCollator()) != *(result->getCollator()) || copy->getBreakIterator() != result->getBreakIterator() || copy->getMatchedLength() != result->getMatchedLength() || @@ -2452,11 +2452,11 @@ class StubSearchIterator:public SearchIterator{ public: StubSearchIterator(){} - virtual void setOffset(int32_t , UErrorCode &) {}; - virtual int32_t getOffset(void) const {return 0;}; - virtual SearchIterator* safeClone(void) const {return NULL;}; - virtual int32_t handleNext(int32_t , UErrorCode &){return 0;}; - virtual int32_t handlePrev(int32_t , UErrorCode &) {return 0;}; + virtual void setOffset(int32_t , UErrorCode &) {} + virtual int32_t getOffset(void) const {return 0;} + virtual SearchIterator* safeClone(void) const {return NULL;} + virtual int32_t handleNext(int32_t , UErrorCode &){return 0;} + virtual int32_t handlePrev(int32_t , UErrorCode &) {return 0;} virtual UClassID getDynamicClassID() const { static char classID = 0; return (UClassID)&classID; diff -Nru icu-64.2/source/test/intltest/ssearch.cpp icu-65.1/source/test/intltest/ssearch.cpp --- icu-64.2/source/test/intltest/ssearch.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/ssearch.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -32,15 +32,25 @@ char testId[100]; -#define TEST_ASSERT(x) {if (!(x)) { \ - errln("Failure in file %s, line %d, test ID = \"%s\"", __FILE__, __LINE__, testId);}} - -#define TEST_ASSERT_M(x, m) {if (!(x)) { \ - dataerrln("Failure in file %s, line %d. \"%s\"", __FILE__, __LINE__, m);return;}} - -#define TEST_ASSERT_SUCCESS(errcode) {if (U_FAILURE(errcode)) { \ - dataerrln("Failure in file %s, line %d, test ID \"%s\", status = \"%s\"", \ - __FILE__, __LINE__, testId, u_errorName(errcode));}} +#define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(x)) { \ + errln("Failure in file %s, line %d, test ID = \"%s\"", __FILE__, __LINE__, testId); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_M(x, m) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(x)) { \ + dataerrln("Failure in file %s, line %d. \"%s\"", __FILE__, __LINE__, m); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT_SUCCESS(errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(errcode)) { \ + dataerrln("Failure in file %s, line %d, test ID \"%s\", status = \"%s\"", \ + __FILE__, __LINE__, testId, u_errorName(errcode)); \ + } \ +} UPRV_BLOCK_MACRO_END #define NEW_ARRAY(type, count) (type *) uprv_malloc((count) * sizeof(type)) #define DELETE_ARRAY(array) uprv_free((void *) (array)) @@ -173,7 +183,7 @@ // This assert is a little deceiving in that strength can be // any of the allowed values, not just TERTIARY, but it will // do the job of getting the error output. - TEST_ASSERT(*strength=="TERTIARY") + TEST_ASSERT(*strength=="TERTIARY"); } // @@ -201,7 +211,7 @@ const UnicodeString *locale = testCase->getAttribute("locale"); if (locale == NULL || locale->length()==0) { locale = &defLocale; - }; + } locale->extract(0, locale->length(), clocale, sizeof(clocale), NULL); diff -Nru icu-64.2/source/test/intltest/string_segment_test.cpp icu-65.1/source/test/intltest/string_segment_test.cpp --- icu-64.2/source/test/intltest/string_segment_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/intltest/string_segment_test.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,120 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "string_segment.h" +#include "intltest.h" + +class StringSegmentTest : public IntlTest { + public: + void testOffset(); + void testLength(); + void testCharAt(); + void testGetCodePoint(); + void testCommonPrefixLength(); + + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0); +}; + +static const char16_t* SAMPLE_STRING = u"📻 radio 📻"; + +void StringSegmentTest::runIndexedTest(int32_t index, UBool exec, const char*&name, char*) { + if (exec) { + logln("TestSuite StringSegmentTest: "); + } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(testOffset); + TESTCASE_AUTO(testLength); + TESTCASE_AUTO(testCharAt); + TESTCASE_AUTO(testGetCodePoint); + TESTCASE_AUTO(testCommonPrefixLength); + TESTCASE_AUTO_END; +} + +void StringSegmentTest::testOffset() { + // Note: sampleString needs function scope so it is valid while the StringSegment is valid + UnicodeString sampleString(SAMPLE_STRING); + StringSegment segment(sampleString, false); + assertEquals("Initial Offset", 0, segment.getOffset()); + segment.adjustOffset(3); + assertEquals("Adjust A", 3, segment.getOffset()); + segment.adjustOffset(2); + assertEquals("Adjust B", 5, segment.getOffset()); + segment.setOffset(4); + assertEquals("Set Offset", 4, segment.getOffset()); +} + +void StringSegmentTest::testLength() { + // Note: sampleString needs function scope so it is valid while the StringSegment is valid + UnicodeString sampleString(SAMPLE_STRING); + StringSegment segment(sampleString, false); + assertEquals("Initial length", 11, segment.length()); + segment.adjustOffset(3); + assertEquals("Adjust", 8, segment.length()); + segment.setLength(4); + assertEquals("Set Length", 4, segment.length()); + segment.setOffset(5); + assertEquals("After adjust offset", 2, segment.length()); + segment.resetLength(); + assertEquals("After reset length", 6, segment.length()); +} + +void StringSegmentTest::testCharAt() { + // Note: sampleString needs function scope so it is valid while the StringSegment is valid + UnicodeString sampleString(SAMPLE_STRING); + StringSegment segment(sampleString, false); + assertEquals("Initial", SAMPLE_STRING, segment.toUnicodeString()); + assertEquals("Initial", SAMPLE_STRING, segment.toTempUnicodeString()); + segment.adjustOffset(3); + assertEquals("After adjust-offset", UnicodeString(u"radio 📻"), segment.toUnicodeString()); + assertEquals("After adjust-offset", UnicodeString(u"radio 📻"), segment.toTempUnicodeString()); + segment.setLength(5); + assertEquals("After adjust-length", UnicodeString(u"radio"), segment.toUnicodeString()); + assertEquals("After adjust-length", UnicodeString(u"radio"), segment.toTempUnicodeString()); +} + +void StringSegmentTest::testGetCodePoint() { + // Note: sampleString needs function scope so it is valid while the StringSegment is valid + UnicodeString sampleString(SAMPLE_STRING); + StringSegment segment(sampleString, false); + assertEquals("Double-width code point", 0x1F4FB, segment.getCodePoint()); + segment.setLength(1); + assertEquals("Inalid A", -1, segment.getCodePoint()); + segment.resetLength(); + segment.adjustOffset(1); + assertEquals("Invalid B", -1, segment.getCodePoint()); + segment.adjustOffset(1); + assertEquals("Valid again", 0x20, segment.getCodePoint()); +} + +void StringSegmentTest::testCommonPrefixLength() { + // Note: sampleString needs function scope so it is valid while the StringSegment is valid + UnicodeString sampleString(SAMPLE_STRING); + StringSegment segment(sampleString, false); + assertEquals("", 11, segment.getCommonPrefixLength(SAMPLE_STRING)); + assertEquals("", 4, segment.getCommonPrefixLength(u"📻 r")); + assertEquals("", 3, segment.getCommonPrefixLength(u"📻 x")); + assertEquals("", 0, segment.getCommonPrefixLength(u"x")); + segment.adjustOffset(3); + assertEquals("", 0, segment.getCommonPrefixLength(u"RADiO")); + assertEquals("", 5, segment.getCommonPrefixLength(u"radio")); + assertEquals("", 2, segment.getCommonPrefixLength(u"rafio")); + assertEquals("", 0, segment.getCommonPrefixLength(u"fadio")); + segment.setLength(3); + assertEquals("", 3, segment.getCommonPrefixLength(u"radio")); + assertEquals("", 2, segment.getCommonPrefixLength(u"rafio")); + assertEquals("", 0, segment.getCommonPrefixLength(u"fadio")); + segment.resetLength(); + segment.setOffset(11); // end of string + assertEquals("", 0, segment.getCommonPrefixLength(u"foo")); +} + + +extern IntlTest *createStringSegmentTest() { + return new StringSegmentTest(); +} + +#endif diff -Nru icu-64.2/source/test/intltest/strtest.cpp icu-65.1/source/test/intltest/strtest.cpp --- icu-64.2/source/test/intltest/strtest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/strtest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -14,6 +14,11 @@ * created by: Markus W. Scherer */ +#ifdef U_HAVE_STRING_VIEW +#include +#endif + +#include #include #include "unicode/utypes.h" @@ -28,6 +33,7 @@ #include "cstr.h" #include "intltest.h" #include "strtest.h" +#include "uinvchar.h" StringTest::~StringTest() {} @@ -142,6 +148,64 @@ } } +namespace { + +// See U_CHARSET_FAMILY in unicode/platform.h. +const char *nativeInvChars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789 \"%&'()*+,-./:;<=>?_"; +const char16_t *asciiInvChars = + u"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + u"abcdefghijklmnopqrstuvwxyz" + u"0123456789 \"%&'()*+,-./:;<=>?_"; + +} // namespace + +void +StringTest::TestUpperOrdinal() { + for (int32_t i = 0;; ++i) { + char ic = nativeInvChars[i]; + uint8_t ac = asciiInvChars[i]; + int32_t expected = ac - 'A'; + int32_t actual = uprv_upperOrdinal(ic); + if (0 <= expected && expected <= 25) { + if (actual != expected) { + errln("uprv_upperOrdinal('%c')=%d != expected %d", + ic, (int)actual, (int)expected); + } + } else { + if (0 <= actual && actual <= 25) { + errln("uprv_upperOrdinal('%c')=%d should have been outside 0..25", + ic, (int)actual); + } + } + if (ic == 0) { break; } + } +} + +void +StringTest::TestLowerOrdinal() { + for (int32_t i = 0;; ++i) { + char ic = nativeInvChars[i]; + uint8_t ac = asciiInvChars[i]; + int32_t expected = ac - 'a'; + int32_t actual = uprv_lowerOrdinal(ic); + if (0 <= expected && expected <= 25) { + if (actual != expected) { + errln("uprv_lowerOrdinal('%c')=%d != expected %d", + ic, (int)actual, (int)expected); + } + } else { + if (0 <= actual && actual <= 25) { + errln("uprv_lowerOrdinal('%c')=%d should have been outside 0..25", + ic, (int)actual); + } + } + if (ic == 0) { break; } + } +} + void StringTest::Test_UTF8_COUNT_TRAIL_BYTES() { #if !U_HIDE_OBSOLETE_UTF_OLD_H @@ -173,10 +237,16 @@ TESTCASE_AUTO(Test_U_STRING); TESTCASE_AUTO(Test_UNICODE_STRING); TESTCASE_AUTO(Test_UNICODE_STRING_SIMPLE); + TESTCASE_AUTO(TestUpperOrdinal); + TESTCASE_AUTO(TestLowerOrdinal); TESTCASE_AUTO(Test_UTF8_COUNT_TRAIL_BYTES); TESTCASE_AUTO(TestSTLCompatibility); TESTCASE_AUTO(TestStringPiece); TESTCASE_AUTO(TestStringPieceComparisons); + TESTCASE_AUTO(TestStringPieceOther); +#ifdef U_HAVE_STRING_VIEW + TESTCASE_AUTO(TestStringPieceStringView); +#endif TESTCASE_AUTO(TestByteSink); TESTCASE_AUTO(TestCheckedArrayByteSink); TESTCASE_AUTO(TestStringByteSink); @@ -346,6 +416,36 @@ } } +void +StringTest::TestStringPieceOther() { + static constexpr char msg[] = "Kapow!"; + + // Another string piece implementation. + struct Other { + const char* data() { return msg; } + size_t size() { return sizeof msg - 1; } + }; + + Other other; + StringPiece piece(other); + + assertEquals("size()", piece.size(), other.size()); + assertEquals("data()", piece.data(), other.data()); +} + +#ifdef U_HAVE_STRING_VIEW +void +StringTest::TestStringPieceStringView() { + static constexpr char msg[] = "Kapow!"; + + std::string_view view(msg); // C++17 + StringPiece piece(view); + + assertEquals("size()", piece.size(), view.size()); + assertEquals("data()", piece.data(), view.data()); +} +#endif + // Verify that ByteSink is subclassable and Flush() overridable. class SimpleByteSink : public ByteSink { public: diff -Nru icu-64.2/source/test/intltest/strtest.h icu-65.1/source/test/intltest/strtest.h --- icu-64.2/source/test/intltest/strtest.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/strtest.h 2019-10-03 11:16:41.000000000 +0000 @@ -39,9 +39,15 @@ void Test_U_STRING(); void Test_UNICODE_STRING(); void Test_UNICODE_STRING_SIMPLE(); + void TestUpperOrdinal(); + void TestLowerOrdinal(); void Test_UTF8_COUNT_TRAIL_BYTES(); void TestStringPiece(); void TestStringPieceComparisons(); + void TestStringPieceOther(); +#ifdef U_HAVE_STRING_VIEW + void TestStringPieceStringView(); +#endif void TestByteSink(); void TestCheckedArrayByteSink(); void TestStringByteSink(); diff -Nru icu-64.2/source/test/intltest/tchcfmt.cpp icu-65.1/source/test/intltest/tchcfmt.cpp --- icu-64.2/source/test/intltest/tchcfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tchcfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -311,7 +311,7 @@ it_errln("*** operator!="); } - ChoiceFormat* form_A3 = (ChoiceFormat*) form_A->clone(); + ChoiceFormat* form_A3 = form_A->clone(); if (!form_A3) { it_errln("*** ChoiceFormat->clone is nil."); }else{ diff -Nru icu-64.2/source/test/intltest/testidna.cpp icu-65.1/source/test/intltest/testidna.cpp --- icu-64.2/source/test/intltest/testidna.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/testidna.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1597,25 +1597,22 @@ void TestIDNA::TestDataFile(){ testData(*this); } + TestIDNA::~TestIDNA(){ - if(gPrep!=NULL){ - delete gPrep; - gPrep = NULL; - } + delete gPrep; + gPrep = NULL; } -NamePrepTransform* TestIDNA::gPrep = NULL; - NamePrepTransform* TestIDNA::getInstance(UErrorCode& status){ - if(TestIDNA::gPrep == NULL){ + if(gPrep == NULL){ UParseError parseError; - TestIDNA::gPrep = NamePrepTransform::createInstance(parseError, status); - if(TestIDNA::gPrep ==NULL){ + gPrep = NamePrepTransform::createInstance(parseError, status); + if(gPrep == NULL){ //status = U_MEMORY_ALLOCATION_ERROR; return NULL; } } - return TestIDNA::gPrep; + return gPrep; } #endif /* #if !UCONFIG_NO_IDNA */ diff -Nru icu-64.2/source/test/intltest/testidna.h icu-65.1/source/test/intltest/testidna.h --- icu-64.2/source/test/intltest/testidna.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/testidna.h 2019-10-03 11:16:41.000000000 +0000 @@ -66,8 +66,9 @@ void TestRefIDNA(); void TestIDNAMonkeyTest(); void TestConformance(); - static NamePrepTransform* getInstance(UErrorCode& status); - static NamePrepTransform* gPrep; + NamePrepTransform* getInstance(UErrorCode& status); + NamePrepTransform* gPrep; + TestIDNA() : gPrep(nullptr) {} virtual ~TestIDNA(); private: diff -Nru icu-64.2/source/test/intltest/tmsgfmt.cpp icu-65.1/source/test/intltest/tmsgfmt.cpp --- icu-64.2/source/test/intltest/tmsgfmt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tmsgfmt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -185,7 +185,7 @@ // {sfb} use double format in pattern, so result will match (not strictly necessary) const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1 fmt(new MessageFormat(pattern, status)); if (U_FAILURE(status)) { dataerrln("MessageFormat pattern creation failed. - %s", u_errorName(status)); return; @@ -194,7 +194,6 @@ if (pattern != result) { errln("MessageFormat::toPattern() failed."); } - delete fmt; } #if 0 @@ -300,10 +299,10 @@ for (int32_t i = 0; i < 9; ++i) { //it_out << "\nPat in: " << testCases[i]); - MessageFormat *form = 0; + LocalPointer form; UErrorCode success = U_ZERO_ERROR; UnicodeString buffer; - form = new MessageFormat(testCases[i], Locale::getUS(), success); + form.adoptInstead(new MessageFormat(testCases[i], Locale::getUS(), success)); if (U_FAILURE(success)) { dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success)); logln(((UnicodeString)"MessageFormat for ") + testCases[i] + " creation failed.\n"); @@ -368,7 +367,6 @@ if (failed) errln("MessageFormat failed test #6"); #endif - delete form; } } @@ -676,13 +674,13 @@ UnicodeString pattern ,Locale locale ,UErrorCode &status , char* errMsg) { //Create the MessageFormat with simple SelectFormat - MessageFormat* msgFmt = new MessageFormat(pattern, locale, status); + LocalPointer msgFmt(new MessageFormat(pattern, locale, status)); if (U_FAILURE(status)) { dataerrln( "%s error while constructing with ErrorCode as %s" ,errMsg, u_errorName(status) ); logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status); - return NULL; + return nullptr; } - return msgFmt; + return msgFmt.orphan(); } void TestMessageFormat::testMsgFormatSelect(/* char* par */) @@ -809,7 +807,8 @@ //Select, plural, and number formats heavily nested UnicodeString t6("{0} und {1, select, female {{2, plural, one {{3, select, female {ihre Freundin} other {ihr Freund}} } other {ihre {2, number, integer} {3, select, female {Freundinnen} other {Freunde}} } }} other{{2, plural, one {{3, select, female {seine Freundin} other {sein Freund}}} other {seine {2, number, integer} {3, select, female {Freundinnen} other {Freunde}}}}} } gingen nach Paris."); //Create the MessageFormat with Select, plural, and number formats heavily nested - MessageFormat* msgFmt6 = internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::TestSelectFormat create t6"); + LocalPointer msgFmt6( + internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::TestSelectFormat create t6")); if (!U_FAILURE(err)) { //Arguments Formattable testArgs10[] = {"Kirti","other",(int32_t)1,"other"}; @@ -848,10 +847,9 @@ }; //Format for( int i=0; i< 14; i++){ - internalFormat( msgFmt6 , testArgs[i], 4, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t6"); + internalFormat( msgFmt6.getAlias(), testArgs[i], 4, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t6"); } } - delete msgFmt6; } //--------------------------------- @@ -923,7 +921,7 @@ MessageFormat *x = new MessageFormat("There are {0} files on {1}", success); MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success); MessageFormat *y = 0; - y = (MessageFormat*)x->clone(); + y = x->clone(); if ( (*x == *y) && (*x != *z) && (*y != *z) ) @@ -1435,8 +1433,8 @@ goto cleanup; } - fmt3 = (MessageFormat*) fmt1->clone(); - fmt4 = (MessageFormat*) fmt2->clone(); + fmt3 = fmt1->clone(); + fmt4 = fmt2->clone(); if (fmt3 == NULL) { it_err("testCopyConstructor2: (fmt3 != NULL)"); diff -Nru icu-64.2/source/test/intltest/transapi.cpp icu-65.1/source/test/intltest/transapi.cpp --- icu-64.2/source/test/intltest/transapi.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/transapi.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -712,7 +712,7 @@ */ class TestFilter1 : public UnicodeFilter { UClassID getDynamicClassID()const { return &gTestFilter1ClassID; } - virtual UnicodeFunctor* clone() const { + virtual TestFilter1* clone() const { return new TestFilter1(*this); } virtual UBool contains(UChar32 c) const { @@ -733,7 +733,7 @@ }; class TestFilter2 : public UnicodeFilter { UClassID getDynamicClassID()const { return &gTestFilter2ClassID; } - virtual UnicodeFunctor* clone() const { + virtual TestFilter2* clone() const { return new TestFilter2(*this); } virtual UBool contains(UChar32 c) const { @@ -754,7 +754,7 @@ }; class TestFilter3 : public UnicodeFilter { UClassID getDynamicClassID()const { return &gTestFilter3ClassID; } - virtual UnicodeFunctor* clone() const { + virtual TestFilter3* clone() const { return new TestFilter3(*this); } virtual UBool contains(UChar32 c) const { @@ -915,8 +915,12 @@ // transliterator, just to verify that they don't fail in some // destructive way. // -#define CEASSERT(a) {if (!(a)) { \ -errln("FAIL at line %d from line %d: %s", __LINE__, line, #a); return; }} +#define CEASSERT(a) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(a)) { \ + errln("FAIL at line %d from line %d: %s", __LINE__, line, #a); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END void TransliteratorAPITest::callEverything(const Transliterator *tr, int line) { Transliterator *clonedTR = tr->clone(); @@ -970,7 +974,7 @@ public: virtual UnicodeFunctor* clone() const {return NULL;} static UClassID getStaticClassID(void) {return (UClassID)&MyUnicodeFunctorTestClassID;} - virtual UClassID getDynamicClassID(void) const {return getStaticClassID();}; + virtual UClassID getDynamicClassID(void) const {return getStaticClassID();} virtual void setData(const TransliterationRuleData*) {} }; diff -Nru icu-64.2/source/test/intltest/transrt.cpp icu-65.1/source/test/intltest/transrt.cpp --- icu-64.2/source/test/intltest/transrt.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/transrt.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1034,11 +1034,14 @@ } -#define ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ - errcheckln(status, "error at file %s, line %d, status = %s", __FILE__, __LINE__, \ - u_errorName(status)); \ - return;}} - +#define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + errcheckln(status, "error at file %s, line %d, status = %s", __FILE__, __LINE__, \ + u_errorName(status)); \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END + static void writeStringInU8(FILE *out, const UnicodeString &s) { int i; @@ -1049,6 +1052,7 @@ int32_t destIdx = 0; U8_APPEND(bufForOneChar, destIdx, (int32_t)sizeof(bufForOneChar), c, isError); U_ASSERT(!isError); + (void)isError; fwrite(bufForOneChar, 1, destIdx, out); } } @@ -1059,7 +1063,10 @@ void TransliteratorRoundTripTest::TestHan() { UErrorCode status = U_ZERO_ERROR; LocalULocaleDataPointer uld(ulocdata_open("zh",&status)); - LocalUSetPointer USetExemplars(ulocdata_getExemplarSet(uld.getAlias(), uset_openEmpty(), 0, ULOCDATA_ES_STANDARD, &status)); + LocalUSetPointer USetExemplars(uset_openEmpty()); + assertTrue("", USetExemplars.isValid(), false, false, __FILE__, __LINE__); + if (! USetExemplars.isValid()) return; + ulocdata_getExemplarSet(uld.getAlias(), USetExemplars.getAlias(), 0, ULOCDATA_ES_STANDARD, &status); ASSERT_SUCCESS(status); UnicodeString source; @@ -1281,7 +1288,7 @@ public: LegalIndic(); virtual UBool is(const UnicodeString& sourceString) const; - virtual ~LegalIndic() {}; + virtual ~LegalIndic() {} }; UBool LegalIndic::is(const UnicodeString& sourceString) const{ int cp=sourceString.charAt(0); diff -Nru icu-64.2/source/test/intltest/transtst.cpp icu-65.1/source/test/intltest/transtst.cpp --- icu-64.2/source/test/intltest/transtst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/transtst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -657,7 +657,7 @@ * Used by TestFiltering(). */ class TestFilter : public UnicodeFilter { - virtual UnicodeFunctor* clone() const { + virtual TestFilter* clone() const { return new TestFilter(*this); } virtual UBool contains(UChar32 c) const { @@ -1947,7 +1947,7 @@ public: TestTrans(const UnicodeString& id) : Transliterator(id, 0) { } - virtual Transliterator* clone(void) const { + virtual TestTrans* clone(void) const { return new TestTrans(getID()); } virtual void handleTransliterate(Replaceable& /*text*/, UTransPosition& offsets, @@ -2340,17 +2340,17 @@ exp = CharsToUnicodeString(DATA[i+3]); } UBool expOk = (DATA[i+1] != NULL); - Transliterator* t = NULL; + LocalPointer t; UParseError pe; UErrorCode ec = U_ZERO_ERROR; if (id.charAt(0) == 0x23/*#*/) { - t = Transliterator::createFromRules("ID", id, direction, pe, ec); + t.adoptInstead(Transliterator::createFromRules("ID", id, direction, pe, ec)); } else { - t = Transliterator::createInstance(id, direction, pe, ec); + t.adoptInstead(Transliterator::createInstance(id, direction, pe, ec)); } - UBool ok = (t != NULL && U_SUCCESS(ec)); + UBool ok = (t.isValid() && U_SUCCESS(ec)); UnicodeString transID; - if (t!=0) { + if (t.isValid()) { transID = t->getID(); } else { @@ -2362,7 +2362,6 @@ if (source.length() != 0) { expect(*t, source, exp); } - delete t; } else { dataerrln((UnicodeString)"FAIL: " + id + " => " + transID + ", " + u_errorName(ec)); @@ -3176,12 +3175,12 @@ UParseError pe; UErrorCode ec = U_ZERO_ERROR; - Transliterator *t2 = Transliterator::createFromRules("source-target", UnicodeString(testRules, -1, US_INV), UTRANS_FORWARD, pe, ec); - Transliterator *t3 = Transliterator::createFromRules("target-source", UnicodeString(testRules, -1, US_INV), UTRANS_REVERSE, pe, ec); + LocalPointer t2( + Transliterator::createFromRules("source-target", UnicodeString(testRules, -1, US_INV), UTRANS_FORWARD, pe, ec)); + LocalPointer t3( + Transliterator::createFromRules("target-source", UnicodeString(testRules, -1, US_INV), UTRANS_REVERSE, pe, ec)); if (U_FAILURE(ec)) { - delete t2; - delete t3; dataerrln((UnicodeString)"FAIL: createFromRules => " + u_errorName(ec)); return; } @@ -3191,9 +3190,6 @@ checkRules("Failed toRules FORWARD", *t2, UnicodeString(testRulesForward, -1, US_INV)); checkRules("Failed toRules BACKWARD", *t3, UnicodeString(testRulesBackward, -1, US_INV)); - - delete t2; - delete t3; } /** @@ -4066,7 +4062,7 @@ } -#define TEST_TRANSLIT_ID(id, cls) { \ +#define TEST_TRANSLIT_ID(id, cls) UPRV_BLOCK_MACRO_BEGIN { \ UErrorCode ec = U_ZERO_ERROR; \ Transliterator* t = Transliterator::createInstance(id, UTRANS_FORWARD, ec); \ if (U_FAILURE(ec)) { \ @@ -4078,9 +4074,9 @@ /* *t = *t; */ /*can't do this: coverage test for assignment op*/ \ } \ delete t; \ -} +} UPRV_BLOCK_MACRO_END -#define TEST_TRANSLIT_RULE(rule, cls) { \ +#define TEST_TRANSLIT_RULE(rule, cls) UPRV_BLOCK_MACRO_BEGIN { \ UErrorCode ec = U_ZERO_ERROR; \ UParseError pe; \ Transliterator* t = Transliterator::createFromRules("_", rule, UTRANS_FORWARD, pe, ec); \ @@ -4093,7 +4089,7 @@ /* *t = *t; */ /*can't do this: coverage test for assignment op*/ \ } \ delete t; \ -} +} UPRV_BLOCK_MACRO_END void TransliteratorTest::TestBoilerplate() { TEST_TRANSLIT_ID("Any-Latin", AnyTransliterator); diff -Nru icu-64.2/source/test/intltest/tsdate.cpp icu-65.1/source/test/intltest/tsdate.cpp --- icu-64.2/source/test/intltest/tsdate.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tsdate.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -164,14 +164,22 @@ date[0] = theDate; fFormat->format(theDate, string[0]); + UErrorCode status = U_ZERO_ERROR; + const char* locID = "??"; + Locale loc = fFormat->getCalendar()->getLocale(ULOC_VALID_LOCALE, status); + if (U_SUCCESS(status)) { + locID = loc.getName(); + } + for (i=1; iparse(string[i-1], status); if (U_FAILURE(status)) { describeTest(); - errln("**** FAIL: Parse of " + prettify(string[i-1], FALSE) + " failed."); + errln("**** FAIL, locale " + UnicodeString(locID,-1,US_INV) + + ": Parse of " + prettify(string[i-1], FALSE) + " failed."); dump = TRUE; break; } @@ -181,7 +189,8 @@ else if (dateMatch > 0 && date[i] != date[i-1]) { describeTest(); - errln("**** FAIL: Date mismatch after match for " + string[i]); + errln("**** FAIL, locale " + UnicodeString(locID,-1,US_INV) + + ": Date mismatch after match for " + string[i]); dump = TRUE; break; } @@ -190,7 +199,8 @@ else if (stringMatch > 0 && string[i] != string[i-1]) { describeTest(); - errln("**** FAIL: String mismatch after match for " + string[i]); + errln("**** FAIL, locale " + UnicodeString(locID,-1,US_INV) + + ": String mismatch after match for " + string[i]); dump = TRUE; break; } diff -Nru icu-64.2/source/test/intltest/tsmthred.cpp icu-65.1/source/test/intltest/tsmthred.cpp --- icu-64.2/source/test/intltest/tsmthred.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tsmthred.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -62,7 +62,6 @@ TESTCASE_AUTO_BEGIN; TESTCASE_AUTO(TestThreads); - TESTCASE_AUTO(TestMutex); #if !UCONFIG_NO_FORMATTING TESTCASE_AUTO(TestThreadedIntl); #endif @@ -72,7 +71,6 @@ TESTCASE_AUTO(TestString); TESTCASE_AUTO(TestArabicShapingThreads); TESTCASE_AUTO(TestAnyTranslit); - TESTCASE_AUTO(TestConditionVariables); TESTCASE_AUTO(TestUnifiedCache); #if !UCONFIG_NO_TRANSLITERATION TESTCASE_AUTO(TestBreakTranslit); @@ -81,7 +79,7 @@ TESTCASE_AUTO(Test20104); #endif /* #if !UCONFIG_NO_FORMATTING */ #endif /* #if !UCONFIG_NO_TRANSLITERATION */ - TESTCASE_AUTO_END + TESTCASE_AUTO_END; } @@ -160,8 +158,8 @@ class TestArabicShapeThreads : public SimpleThread { public: - TestArabicShapeThreads() {}; - virtual void run() { doTailTest(); }; + TestArabicShapeThreads() {} + virtual void run() { doTailTest(); } private: void doTailTest(); }; @@ -232,109 +230,6 @@ } -//----------------------------------------------------------------------- -// -// TestMutex - a simple (non-stress) test to verify that ICU mutexes -// and condition variables are functioning. Does not test the use of -// mutexes within ICU services, but rather that the -// platform's mutex support is at least superficially there. -// -//---------------------------------------------------------------------- -static UMutex *gTestMutexA() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} -static UConditionVar *gThreadsCountChanged() { - static UConditionVar cv = U_CONDITION_INITIALIZER; - return &cv; -} - -static int gThreadsStarted = 0; -static int gThreadsInMiddle = 0; -static int gThreadsDone = 0; - -static const int TESTMUTEX_THREAD_COUNT = 40; - -class TestMutexThread : public SimpleThread -{ -public: - virtual void run() { - // This is the code that each of the spawned threads runs. - // All threads move together throught the started - middle - done sequence together, - // waiting for all other threads to reach each point before advancing. - umtx_lock(gTestMutexA()); - gThreadsStarted += 1; - umtx_condBroadcast(gThreadsCountChanged()); - while (gThreadsStarted < TESTMUTEX_THREAD_COUNT) { - if (gThreadsInMiddle != 0) { - IntlTest::gTest->errln( - "%s:%d gThreadsInMiddle = %d. Expected 0.", __FILE__, __LINE__, gThreadsInMiddle); - return; - } - umtx_condWait(gThreadsCountChanged(), gTestMutexA()); - } - - gThreadsInMiddle += 1; - umtx_condBroadcast(gThreadsCountChanged()); - while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) { - if (gThreadsDone != 0) { - IntlTest::gTest->errln( - "%s:%d gThreadsDone = %d. Expected 0.", __FILE__, __LINE__, gThreadsDone); - return; - } - umtx_condWait(gThreadsCountChanged(), gTestMutexA()); - } - - gThreadsDone += 1; - umtx_condBroadcast(gThreadsCountChanged()); - while (gThreadsDone < TESTMUTEX_THREAD_COUNT) { - umtx_condWait(gThreadsCountChanged(), gTestMutexA()); - } - umtx_unlock(gTestMutexA()); - } -}; - -void MultithreadTest::TestMutex() -{ - gThreadsStarted = 0; - gThreadsInMiddle = 0; - gThreadsDone = 0; - int32_t i = 0; - TestMutexThread threads[TESTMUTEX_THREAD_COUNT]; - umtx_lock(gTestMutexA()); - for (i=0; ierrln("File %s, Line %d: Error, gStartedThreads = %d, gFinishedThreads = %d", - __FILE__, __LINE__, gStartedThreads, gFinishedThreads); - } - umtx_condWait(gCTConditionVar(), gCTMutex()); - } - - gFinishedThreads += gConditionTestOne; - fFinished = true; - umtx_condBroadcast(gCTConditionVar()); - - while (gFinishedThreads < NUMTHREADS) { - umtx_condWait(gCTConditionVar(), gCTMutex()); - } - umtx_unlock(gCTMutex()); -} - -void MultithreadTest::TestConditionVariables() { - gStartedThreads = 0; - gFinishedThreads = 0; - int i; - - umtx_lock(gCTMutex()); - CondThread *threads[NUMTHREADS]; - for (i=0; istart(); - } - - while (gStartedThreads < NUMTHREADS) { - umtx_condWait(gCTConditionVar(), gCTMutex()); - } - - while (gFinishedThreads < NUMTHREADS) { - umtx_condWait(gCTConditionVar(), gCTMutex()); - } - - umtx_unlock(gCTMutex()); - - for (i=0; ifFinished); - } - - for (i=0; ijoin(); - delete threads[i]; - } -} - // // Unified Cache Test @@ -1277,6 +1081,9 @@ U_NAMESPACE_BEGIN +static std::mutex *gCTMutex = nullptr; +static std::condition_variable *gCTConditionVar = nullptr; + template<> U_EXPORT const UCTMultiThreadItem *LocaleCacheKey::createObject( const void *context, UErrorCode &status) const { @@ -1292,21 +1099,23 @@ return result; } - umtx_lock(gCTMutex()); - bool firstObject = (gObjectsCreated == 0); - if (firstObject) { - // Force the first object creation that comes through to wait - // until other have completed. Verifies that cache doesn't - // deadlock when a creation is slow. - - // Note that gObjectsCreated needs to be incremeneted from 0 to 1 - // early, to keep subsequent threads from entering this path. - gObjectsCreated = 1; - while (gObjectsCreated < 3) { - umtx_condWait(gCTConditionVar(), gCTMutex()); + bool firstObject = false; + { + std::unique_lock lock(*gCTMutex); + firstObject = (gObjectsCreated == 0); + if (firstObject) { + // Force the first object creation that comes through to wait + // until other have completed. Verifies that cache doesn't + // deadlock when a creation is slow. + + // Note that gObjectsCreated needs to be incremeneted from 0 to 1 + // early, to keep subsequent threads from entering this path. + gObjectsCreated = 1; + while (gObjectsCreated < 3) { + gCTConditionVar->wait(lock); + } } } - umtx_unlock(gCTMutex()); const UCTMultiThreadItem *result = new UCTMultiThreadItem(fLoc.getLanguage()); @@ -1318,12 +1127,13 @@ // Log that we created an object. The first object was already counted, // don't do it again. - umtx_lock(gCTMutex()); - if (!firstObject) { - gObjectsCreated += 1; + { + std::unique_lock lock(*gCTMutex); + if (!firstObject) { + gObjectsCreated += 1; + } + gCTConditionVar->notify_all(); } - umtx_condBroadcast(gCTConditionVar()); - umtx_unlock(gCTMutex()); return result; } @@ -1335,8 +1145,8 @@ UnifiedCacheThread( const UnifiedCache *cache, const char *loc, - const char *loc2) : fCache(cache), fLoc(loc), fLoc2(loc2) {}; - ~UnifiedCacheThread() {}; + const char *loc2) : fCache(cache), fLoc(loc), fLoc2(loc2) {} + ~UnifiedCacheThread() {} void run(); void exerciseByLocale(const Locale &); const UnifiedCache *fCache; @@ -1385,7 +1195,9 @@ cache.setEvictionPolicy(2, 0, status); U_ASSERT(U_SUCCESS(status)); - gFinishedThreads = 0; + gCTMutex = new std::mutex(); + gCTConditionVar = new std::condition_variable(); + gObjectsCreated = 0; UnifiedCacheThread *threads[CACHE_LOAD][UPRV_LENGTHOF(gCacheLocales)]; @@ -1427,6 +1239,8 @@ delete threads[i][j]; } } + delete gCTMutex; + delete gCTConditionVar; } #if !UCONFIG_NO_TRANSLITERATION @@ -1441,8 +1255,8 @@ class BreakTranslitThread: public SimpleThread { public: - BreakTranslitThread() {}; - ~BreakTranslitThread() {}; + BreakTranslitThread() {} + ~BreakTranslitThread() {} void run(); }; @@ -1491,7 +1305,7 @@ class TestIncDecThread : public SimpleThread { public: - TestIncDecThread() { }; + TestIncDecThread() {} virtual void run(); }; @@ -1524,7 +1338,7 @@ class Test20104Thread : public SimpleThread { public: - Test20104Thread() { }; + Test20104Thread() {} virtual void run(); }; diff -Nru icu-64.2/source/test/intltest/tsmthred.h icu-65.1/source/test/intltest/tsmthred.h --- icu-64.2/source/test/intltest/tsmthred.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tsmthred.h 2019-10-03 11:16:41.000000000 +0000 @@ -36,10 +36,6 @@ **/ void TestArabicShapingThreads(void); - /** - * test that mutexes work - **/ - void TestMutex(void); #if !UCONFIG_NO_FORMATTING /** * test that intl functions work in a multithreaded context @@ -49,7 +45,6 @@ void TestCollators(void); void TestString(); void TestAnyTranslit(); - void TestConditionVariables(); void TestUnifiedCache(); void TestBreakTranslit(); void TestIncDec(); diff -Nru icu-64.2/source/test/intltest/tstnorm.cpp icu-65.1/source/test/intltest/tstnorm.cpp --- icu-64.2/source/test/intltest/tstnorm.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tstnorm.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1369,7 +1369,7 @@ // We need not look at control codes, Han characters nor Hangul LVT syllables because they // do not combine forward. LV syllables are already removed. UnicodeSet notInteresting("[[:C:][:Unified_Ideograph:][:HST=LVT:]]", errorCode); - LocalPointer unsure(&((UnicodeSet *)(skipSets[UNORM_NFC].clone()))->removeAll(notInteresting)); + LocalPointer unsure(&(skipSets[UNORM_NFC].clone())->removeAll(notInteresting)); // System.out.format("unsure.size()=%d\n", unsure.size()); // For each character about which we are unsure, see if it changes when we add diff -Nru icu-64.2/source/test/intltest/tufmtts.cpp icu-65.1/source/test/intltest/tufmtts.cpp --- icu-64.2/source/test/intltest/tufmtts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tufmtts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -171,7 +171,7 @@ TimeUnit* tmunit = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status); if (!assertSuccess("TimeUnit::createInstance", status)) return; - TimeUnit* another = (TimeUnit*)tmunit->clone(); + TimeUnit* another = tmunit->clone(); TimeUnit third(*tmunit); TimeUnit fourth = third; @@ -239,7 +239,7 @@ TimeUnitAmount second(tma); TimeUnitAmount third_tma = tma; - TimeUnitAmount* fourth_tma = (TimeUnitAmount*)tma.clone(); + TimeUnitAmount* fourth_tma = tma.clone(); assertTrue("orig and copy are equal", (second == tma)); assertTrue("clone and assigned are equal", (third_tma == *fourth_tma)); @@ -266,7 +266,7 @@ TimeUnitFormat tmf_copy(tmf_fr); assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr == tmf_copy)); - TimeUnitFormat* tmf_clone = (TimeUnitFormat*)tmf_en->clone(); + TimeUnitFormat* tmf_clone = tmf_en->clone(); assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en == *tmf_clone)); delete tmf_clone; @@ -386,7 +386,7 @@ unitIndex < UPRV_LENGTHOF(tunits); ++unitIndex ) { - TimeUnitAmount *tamt = new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status); + LocalPointertamt(new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status)); if (U_FAILURE(status)) { dataerrln("generating TimeUnitAmount Object failed."); #ifdef TUFMTTS_DEBUG @@ -395,7 +395,7 @@ return; } - TimeUnitFormat *tfmt = new TimeUnitFormat(l, styles[styleIndex], status); + LocalPointer tfmt(new TimeUnitFormat(l, styles[styleIndex], status)); if (U_FAILURE(status)) { dataerrln("generating TimeUnitAmount Object failed."); #ifdef TUFMTTS_DEBUG @@ -407,10 +407,9 @@ Formattable fmt; UnicodeString str; - fmt.adoptObject(tamt); - str = ((Format *)tfmt)->format(fmt, str, status); + fmt.adoptObject(tamt.orphan()); + str = ((Format *)tfmt.getAlias())->format(fmt, str, status); if (!assertSuccess("formatting relative time failed", status)) { - delete tfmt; #ifdef TUFMTTS_DEBUG std::cout << "Failed to format" << "\n"; #endif @@ -426,11 +425,9 @@ std::cout << "Formatted string : " << tmp << " expected : " << tmp1 << "\n"; #endif if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales[locIndex]) + " style: " + (int)styles[styleIndex] + " units: " + (int)tunits[unitIndex], expected[counter], str)) { - delete tfmt; str.remove(); return; } - delete tfmt; str.remove(); ++counter; } diff -Nru icu-64.2/source/test/intltest/tzfmttst.cpp icu-65.1/source/test/intltest/tzfmttst.cpp --- icu-64.2/source/test/intltest/tzfmttst.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tzfmttst.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -85,6 +85,7 @@ TESTCASE(5, TestFormatTZDBNames); TESTCASE(6, TestFormatCustomZone); TESTCASE(7, TestFormatTZDBNamesAllZoneCoverage); + TESTCASE(8, TestAdoptDefaultThreadSafe); default: name = ""; break; } } @@ -409,7 +410,7 @@ for (int i=0; i threads(this, threadCount, &TimeZoneFormatTest::RunAdoptDefaultThreadSafeTests); + threads.start(); // Start all threads. + threads.join(); // Wait for all threads to finish. +} + +static const int32_t kAdoptDefaultIteration = 10; +static const int32_t kCreateDefaultIteration = 5000; +static const int64_t kStartTime = 1557288964845; + +void TimeZoneFormatTest::RunAdoptDefaultThreadSafeTests(int32_t threadNumber) { + UErrorCode status = U_ZERO_ERROR; + if (threadNumber % 2 == 0) { + for (int32_t i = 0; i < kAdoptDefaultIteration; i++) { + std::unique_ptr timezones( + icu::TimeZone::createEnumeration()); + // Fails with missing data. + if (!assertTrue(WHERE, (bool)timezones, false, true)) {return;} + while (const icu::UnicodeString* timezone = timezones->snext(status)) { + status = U_ZERO_ERROR; + icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(*timezone)); + } + } + } else { + int32_t rawOffset; + int32_t dstOffset; + int64_t date = kStartTime; + for (int32_t i = 0; i < kCreateDefaultIteration; i++) { + date += 6000 * i; + std::unique_ptr tz(icu::TimeZone::createDefault()); + status = U_ZERO_ERROR; + tz->getOffset(date, TRUE, rawOffset, dstOffset, status); + status = U_ZERO_ERROR; + tz->getOffset(date, FALSE, rawOffset, dstOffset, status); + } + } +} typedef struct { const char* text; @@ -1301,5 +1340,4 @@ } } } - #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/tzfmttst.h icu-65.1/source/test/intltest/tzfmttst.h --- icu-64.2/source/test/intltest/tzfmttst.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tzfmttst.h 2019-10-03 11:16:41.000000000 +0000 @@ -29,8 +29,10 @@ void TestFormatTZDBNames(void); void TestFormatCustomZone(void); void TestFormatTZDBNamesAllZoneCoverage(void); + void TestAdoptDefaultThreadSafe(void); void RunTimeRoundTripTests(int32_t threadNumber); + void RunAdoptDefaultThreadSafeTests(int32_t threadNumber); }; #endif /* #if !UCONFIG_NO_FORMATTING */ diff -Nru icu-64.2/source/test/intltest/tzregts.cpp icu-65.1/source/test/intltest/tzregts.cpp --- icu-64.2/source/test/intltest/tzregts.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tzregts.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -352,7 +352,7 @@ TimeZoneRegressionTest::checkCalendar314(GregorianCalendar *testCal, TimeZone *testTZ) { UErrorCode status = U_ZERO_ERROR; - // GregorianCalendar testCal = (GregorianCalendar)aCal.clone(); + // GregorianCalendar testCal = aCal.clone(); int32_t tzOffset, tzRawOffset; float tzOffsetFloat,tzRawOffsetFloat; @@ -922,26 +922,26 @@ // that does have a DST savings (which should be ignored). UErrorCode status = U_ZERO_ERROR; int32_t offset = 90 * 60000; // 1:30 - SimpleTimeZone* z1 = new SimpleTimeZone(offset, "_std_zone_"); - z1->setDSTSavings(45 * 60000, status); // 0:45 + SimpleTimeZone z1(offset, "_std_zone_"); + z1.setDSTSavings(45 * 60000, status); // 0:45 // Construct a zone that observes DST for the first 6 months. - SimpleTimeZone* z2 = new SimpleTimeZone(offset, "_dst_zone_"); - z2->setDSTSavings(45 * 60000, status); // 0:45 - z2->setStartRule(UCAL_JANUARY, 1, 0, status); - z2->setEndRule(UCAL_JULY, 1, 0, status); + SimpleTimeZone z2(offset, "_dst_zone_"); + z2.setDSTSavings(45 * 60000, status); // 0:45 + z2.setStartRule(UCAL_JANUARY, 1, 0, status); + z2.setEndRule(UCAL_JULY, 1, 0, status); // Also check DateFormat - DateFormat* fmt1 = new SimpleDateFormat(UnicodeString("z"), status); + SimpleDateFormat fmt1(UnicodeString(u"z"), status); if (U_FAILURE(status)) { dataerrln("Failure trying to construct: %s", u_errorName(status)); return; } - fmt1->setTimeZone(*z1); // Format uses standard zone - DateFormat* fmt2 = new SimpleDateFormat(UnicodeString("z"), status); + fmt1.setTimeZone(z1); // Format uses standard zone + SimpleDateFormat fmt2(UnicodeString(u"z"), status); if(!assertSuccess("trying to construct", status))return; - fmt2->setTimeZone(*z2); // Format uses DST zone - Calendar* tempcal = Calendar::createInstance(status); + fmt2.setTimeZone(z2); // Format uses DST zone + LocalPointer tempcal(Calendar::createInstance(status)); tempcal->clear(); tempcal->set(1970, UCAL_FEBRUARY, 1); UDate dst = tempcal->getTime(status); // Time in DST @@ -951,26 +951,26 @@ // Description, Result, Expected Result UnicodeString a,b,c,d,e,f,g,h,i,j,k,l; UnicodeString DATA[] = { - "z1->getDisplayName(false, SHORT)/std zone", - z1->getDisplayName(FALSE, TimeZone::SHORT, a), "GMT+1:30", - "z1->getDisplayName(false, LONG)/std zone", - z1->getDisplayName(FALSE, TimeZone::LONG, b), "GMT+01:30", - "z1->getDisplayName(true, SHORT)/std zone", - z1->getDisplayName(TRUE, TimeZone::SHORT, c), "GMT+1:30", - "z1->getDisplayName(true, LONG)/std zone", - z1->getDisplayName(TRUE, TimeZone::LONG, d ), "GMT+01:30", - "z2->getDisplayName(false, SHORT)/dst zone", - z2->getDisplayName(FALSE, TimeZone::SHORT, e), "GMT+1:30", - "z2->getDisplayName(false, LONG)/dst zone", - z2->getDisplayName(FALSE, TimeZone::LONG, f ), "GMT+01:30", - "z2->getDisplayName(true, SHORT)/dst zone", - z2->getDisplayName(TRUE, TimeZone::SHORT, g), "GMT+2:15", - "z2->getDisplayName(true, LONG)/dst zone", - z2->getDisplayName(TRUE, TimeZone::LONG, h ), "GMT+02:15", - "DateFormat.format(std)/std zone", fmt1->format(std, i), "GMT+1:30", - "DateFormat.format(dst)/std zone", fmt1->format(dst, j), "GMT+1:30", - "DateFormat.format(std)/dst zone", fmt2->format(std, k), "GMT+1:30", - "DateFormat.format(dst)/dst zone", fmt2->format(dst, l), "GMT+2:15", + "z1.getDisplayName(false, SHORT)/std zone", + z1.getDisplayName(FALSE, TimeZone::SHORT, a), "GMT+1:30", + "z1.getDisplayName(false, LONG)/std zone", + z1.getDisplayName(FALSE, TimeZone::LONG, b), "GMT+01:30", + "z1.getDisplayName(true, SHORT)/std zone", + z1.getDisplayName(TRUE, TimeZone::SHORT, c), "GMT+1:30", + "z1.getDisplayName(true, LONG)/std zone", + z1.getDisplayName(TRUE, TimeZone::LONG, d ), "GMT+01:30", + "z2.getDisplayName(false, SHORT)/dst zone", + z2.getDisplayName(FALSE, TimeZone::SHORT, e), "GMT+1:30", + "z2.getDisplayName(false, LONG)/dst zone", + z2.getDisplayName(FALSE, TimeZone::LONG, f ), "GMT+01:30", + "z2.getDisplayName(true, SHORT)/dst zone", + z2.getDisplayName(TRUE, TimeZone::SHORT, g), "GMT+2:15", + "z2.getDisplayName(true, LONG)/dst zone", + z2.getDisplayName(TRUE, TimeZone::LONG, h ), "GMT+02:15", + "DateFormat.format(std)/std zone", fmt1.format(std, i), "GMT+1:30", + "DateFormat.format(dst)/std zone", fmt1.format(dst, j), "GMT+1:30", + "DateFormat.format(std)/dst zone", fmt2.format(std, k), "GMT+1:30", + "DateFormat.format(dst)/dst zone", fmt2.format(dst, l), "GMT+2:15", }; for (int32_t idx=0; idx " + DATA[idx+1] + ", exp " + DATA[idx+2]); } } - delete z1; - delete z2; - delete fmt1; - delete fmt2; - delete tempcal; } /** diff -Nru icu-64.2/source/test/intltest/tzrulets.cpp icu-65.1/source/test/intltest/tzrulets.cpp --- icu-64.2/source/test/intltest/tzrulets.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tzrulets.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -266,7 +266,7 @@ if (rbtz1->hasSameRules(*rbtz3)) { errln("FAIL: rbtz1 and rbtz3 have different rules, but returned true."); } - RuleBasedTimeZone *rbtz1c = (RuleBasedTimeZone*)rbtz1->clone(); + RuleBasedTimeZone *rbtz1c = rbtz1->clone(); if (!rbtz1->hasSameRules(*rbtz1c)) { errln("FAIL: Cloned RuleBasedTimeZone must have the same rules with the original."); } @@ -548,7 +548,7 @@ if (ny->hasSameRules(*rbtz) || rbtz->hasSameRules(*ny)) { errln("FAIL: hasSameRules must return false"); } - RuleBasedTimeZone *rbtzc = (RuleBasedTimeZone*)rbtz->clone(); + RuleBasedTimeZone *rbtzc = rbtz->clone(); if (!rbtz->hasSameRules(*rbtzc) || !rbtz->hasEquivalentTransitions(*rbtzc, jan1_1950, jan1_2010, TRUE, status)) { errln("FAIL: hasSameRules/hasEquivalentTransitions must return true for cloned RBTZs"); } @@ -742,7 +742,7 @@ } // Cloned TimeZone - BasicTimeZone *newyork2 = (BasicTimeZone*)newyork->clone(); + BasicTimeZone *newyork2 = newyork->clone(); if (!newyork->hasEquivalentTransitions(*newyork2, jan1_1971, jan1_2011, FALSE, status)) { errln("FAIL: Cloned TimeZone must have the same transitions"); } @@ -1695,7 +1695,7 @@ // setRawOffset const int32_t RAW = -10*HOUR; - VTimeZone *tmpvtz = (VTimeZone*)vtz->clone(); + VTimeZone *tmpvtz = vtz->clone(); tmpvtz->setRawOffset(RAW); if (tmpvtz->getRawOffset() != RAW) { logln("setRawOffset is implemented in VTimeZone"); diff -Nru icu-64.2/source/test/intltest/tztest.cpp icu-65.1/source/test/intltest/tztest.cpp --- icu-64.2/source/test/intltest/tztest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/tztest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -423,7 +423,7 @@ #endif UnicodeString str; - UnicodeString *buf = new UnicodeString("TimeZone::createEnumeration() = { "); + UnicodeString buf(u"TimeZone::createEnumeration() = { "); int32_t s_length; StringEnumeration* s = TimeZone::createEnumeration(); if (s == NULL) { @@ -432,11 +432,11 @@ } s_length = s->count(ec); for (i = 0; i < s_length;++i) { - if (i > 0) *buf += ", "; + if (i > 0) buf += ", "; if ((i & 1) == 0) { - *buf += *s->snext(ec); + buf += *s->snext(ec); } else { - *buf += UnicodeString(s->next(NULL, ec), ""); + buf += UnicodeString(s->next(NULL, ec), ""); } if((i % 5) == 4) { @@ -450,8 +450,8 @@ } } } - *buf += " };"; - logln(*buf); + buf += " };"; + logln(buf); /* Confirm that the following zones can be retrieved: The first * zone, the last zone, and one in-between. This tests the binary @@ -478,31 +478,31 @@ } delete s; - buf->truncate(0); - *buf += "TimeZone::createEnumeration(GMT+01:00) = { "; + buf.truncate(0); + buf += "TimeZone::createEnumeration(GMT+01:00) = { "; s = TimeZone::createEnumeration(1 * U_MILLIS_PER_HOUR); s_length = s->count(ec); for (i = 0; i < s_length;++i) { - if (i > 0) *buf += ", "; - *buf += *s->snext(ec); + if (i > 0) buf += ", "; + buf += *s->snext(ec); } delete s; - *buf += " };"; - logln(*buf); + buf += " };"; + logln(buf); - buf->truncate(0); - *buf += "TimeZone::createEnumeration(US) = { "; + buf.truncate(0); + buf += "TimeZone::createEnumeration(US) = { "; s = TimeZone::createEnumeration("US"); s_length = s->count(ec); for (i = 0; i < s_length;++i) { - if (i > 0) *buf += ", "; - *buf += *s->snext(ec); + if (i > 0) buf += ", "; + buf += *s->snext(ec); } - *buf += " };"; - logln(*buf); + buf += " };"; + logln(buf); TimeZone *tz = TimeZone::createTimeZone("PST"); if (tz != 0) logln("getTimeZone(PST) = " + tz->getID(str)); @@ -522,7 +522,6 @@ errln("FAIL: getTimeZone(NON_EXISTENT) = " + temp); delete tz; - delete buf; delete s; } diff -Nru icu-64.2/source/test/intltest/ucharstrietest.cpp icu-65.1/source/test/intltest/ucharstrietest.cpp --- icu-64.2/source/test/intltest/ucharstrietest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/ucharstrietest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -71,6 +71,7 @@ void checkFirst(UCharsTrie &trie, const StringAndValue data[], int32_t dataLength); void checkNext(UCharsTrie &trie, const StringAndValue data[], int32_t dataLength); void checkNextWithState(UCharsTrie &trie, const StringAndValue data[], int32_t dataLength); + void checkNextWithState64(UCharsTrie &trie, const StringAndValue data[], int32_t dataLength); void checkNextString(UCharsTrie &trie, const StringAndValue data[], int32_t dataLength); void checkIterator(UCharsTrie &trie, const StringAndValue data[], int32_t dataLength); void checkIterator(UCharsTrie::Iterator &iter, const StringAndValue data[], int32_t dataLength); @@ -762,6 +763,7 @@ checkFirst(*trie, data, dataLength); checkNext(*trie, data, dataLength); checkNextWithState(*trie, data, dataLength); + checkNextWithState64(*trie, data, dataLength); checkNextString(*trie, data, dataLength); checkIterator(*trie, data, dataLength); } @@ -979,6 +981,61 @@ data[i].s); } else if(trie.getValue()!=data[i].value) { errln("trie value for %s is %ld=0x%lx instead of expected %ld=0x%lx", + data[i].s, + (long)trie.getValue(), (long)trie.getValue(), + (long)data[i].value, (long)data[i].value); + } + trie.reset(); + } +} + +void UCharsTrieTest::checkNextWithState64(UCharsTrie &trie, + const StringAndValue data[], int32_t dataLength) { + assertTrue("trie(initial state).getState64()!=0", trie.getState64() != 0); + for(int32_t i=0; igetDynamicClassID(): NULL); \ if(U_FAILURE(status)) { \ dataerrln(UnicodeString(#c " - " #f " - got err status ") + UnicodeString(u_errorName(status))); \ status = U_ZERO_ERROR; \ } \ -} +} UPRV_BLOCK_MACRO_END #define MAX_CLASS_ID 200 @@ -509,19 +509,15 @@ void UObjectTest::testUMemory() { // additional tests for code coverage #if U_OVERRIDE_CXX_ALLOCATION && U_HAVE_PLACEMENT_NEW - union { - UAlignedMemory align_; - char bytes_[sizeof(UnicodeString)]; - } stackMemory; - char *bytes = stackMemory.bytes_; + alignas(UnicodeString) char bytes[sizeof(UnicodeString)]; UnicodeString *p; enum { len=20 }; - p=new(bytes) UnicodeString(len, (UChar32)0x20ac, len); + p=new(bytes) UnicodeString(len, (UChar32)U'€', len); if((void *)p!=(void *)bytes) { errln("placement new did not place the object at the expected address"); } - if(p->length()!=len || p->charAt(0)!=0x20ac || p->charAt(len-1)!=0x20ac) { + if(p->length()!=len || p->charAt(0)!=u'€' || p->charAt(len-1)!=u'€') { errln("constructor used with placement new did not work right"); } diff -Nru icu-64.2/source/test/intltest/usettest.cpp icu-65.1/source/test/intltest/usettest.cpp --- icu-64.2/source/test/intltest/usettest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/usettest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -29,12 +29,18 @@ #include "cmemory.h" #include "hash.h" -#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ - dataerrln("fail in file \"%s\", line %d: \"%s\"", __FILE__, __LINE__, \ - u_errorName(status));}} - -#define TEST_ASSERT(expr) {if (!(expr)) { \ - dataerrln("fail in file \"%s\", line %d", __FILE__, __LINE__); }} +#define TEST_ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + dataerrln("fail in file \"%s\", line %d: \"%s\"", __FILE__, __LINE__, \ + u_errorName(status)); \ + } \ +} UPRV_BLOCK_MACRO_END + +#define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \ + if (!(expr)) { \ + dataerrln("fail in file \"%s\", line %d", __FILE__, __LINE__); \ + } \ +} UPRV_BLOCK_MACRO_END UnicodeString operator+(const UnicodeString& left, const UnicodeSet& set) { UnicodeString pat; @@ -358,8 +364,8 @@ } logln("Testing clone()"); - UnicodeSet *set1clone=(UnicodeSet*)set1->clone(); - UnicodeSet *set2clone=(UnicodeSet*)set2->clone(); + UnicodeSet *set1clone=set1->clone(); + UnicodeSet *set2clone=set2->clone(); if(*set1clone != *set1 || *set1clone != *set1copy || *set1clone != set1equal || *set2clone != *set2 || *set2clone == *set1copy || *set2clone != set2equal || *set2clone == *set1 || *set2clone == set1equal || *set2clone == *set1clone){ @@ -2249,7 +2255,7 @@ errln("FAIL: copying a frozen set results in a thawed one"); } - UnicodeSet *cloned=(UnicodeSet *)frozen.clone(); + UnicodeSet *cloned=frozen.clone(); if(!cloned->isFrozen() || *cloned!=frozen || cloned->containsSome(0xd802, 0xd805)) { errln("FAIL: clone() failed"); } @@ -2259,7 +2265,7 @@ } delete cloned; - UnicodeSet *thawed=(UnicodeSet *)frozen.cloneAsThawed(); + UnicodeSet *thawed=frozen.cloneAsThawed(); if(thawed->isFrozen() || *thawed!=frozen || thawed->containsSome(0xd802, 0xd805)) { errln("FAIL: cloneAsThawed() failed"); } @@ -3686,11 +3692,11 @@ // Intermediate set: Test cloning of a frozen set. UnicodeSet *fast=new UnicodeSet(*sets[SLOW]); fast->freeze(); - sets[FAST]=(UnicodeSet *)fast->clone(); + sets[FAST]=fast->clone(); delete fast; UnicodeSet *fastNot=new UnicodeSet(*sets[SLOW_NOT]); fastNot->freeze(); - sets[FAST_NOT]=(UnicodeSet *)fastNot->clone(); + sets[FAST_NOT]=fastNot->clone(); delete fastNot; for(j=0; jclone(); + UnicodeString *c=test->clone(); workingBuffer[1] = 0x109; if(test->charAt(1) != 0x109) { diff -Nru icu-64.2/source/test/intltest/utxttest.cpp icu-65.1/source/test/intltest/utxttest.cpp --- icu-64.2/source/test/intltest/utxttest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/intltest/utxttest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -29,17 +29,21 @@ // Forward decl UText *openFragmentedUnicodeString(UText *ut, UnicodeString *s, UErrorCode *status); -#define TEST_ASSERT(x) \ -{ if ((x)==FALSE) {errln("Test #%d failure in file %s at line %d\n", gTestNum, __FILE__, __LINE__);\ - gFailed = TRUE;\ - }} +#define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \ + if ((x)==FALSE) { \ + errln("Test #%d failure in file %s at line %d\n", gTestNum, __FILE__, __LINE__); \ + gFailed = TRUE; \ + } \ +} UPRV_BLOCK_MACRO_END -#define TEST_SUCCESS(status) \ -{ if (U_FAILURE(status)) {errln("Test #%d failure in file %s at line %d. Error = \"%s\"\n", \ - gTestNum, __FILE__, __LINE__, u_errorName(status)); \ - gFailed = TRUE;\ - }} +#define TEST_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if (U_FAILURE(status)) { \ + errln("Test #%d failure in file %s at line %d. Error = \"%s\"\n", \ + gTestNum, __FILE__, __LINE__, u_errorName(status)); \ + gFailed = TRUE; \ + } \ +} UPRV_BLOCK_MACRO_END UTextTest::UTextTest() { } @@ -266,7 +270,7 @@ i = 0; // native utf-8 index for (j=0; j <_ProjectFileVersion>10.0.30319.1 - .\x86\Debug\ - .\x86\Debug\ - - .\x86\Release\ - .\x86\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - - .\x64\Release\ - .\x64\Release\ - false + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + + + $(OutDir)\iotest.tlb + ..\..\..\include;..\..\tools\ctestfw;..\..\common;%(AdditionalIncludeDirectories) U_ATTRIBUTE_DEPRECATED=;%(PreprocessorDefinitions) true Level3 - - - - - .\x86\Debug/iotest.tlb - - - - - MultiThreadedDebugDLL - true - .\x86\Debug/iotest.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true - EditAndContinue - Default - - - .\x86\Debug/iotest.exe - icuucd.lib;icuind.lib;icuiod.lib;icutestd.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/iotest.pdb - Console - false - - - - - - - .\x86\Release/iotest.tlb - - - MultiThreadedDLL - .\x86\Release/iotest.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Default + $(OutDir)\iotest.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\iotest.pdb - .\x86\Release/iotest.exe - icuuc.lib;icuin.lib;icuio.lib;icutest.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/iotest.pdb Console - false - - + $(OutDir)\iotest.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - .\x64\Debug/iotest.tlb - - - + + - MultiThreadedDebugDLL - .\x64\Debug/iotest.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ true - ProgramDatabase - Default + MultiThreadedDebugDLL - .\x64\Debug/iotest.exe icuucd.lib;icuind.lib;icuiod.lib;icutestd.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/iotest.pdb - Console - - - .\x64\Release/iotest.tlb - + + MultiThreadedDLL - .\x64\Release/iotest.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default + true - .\x64\Release/iotest.exe icuuc.lib;icuin.lib;icuio.lib;icutest.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/iotest.pdb - Console diff -Nru icu-64.2/source/test/iotest/strtst.c icu-65.1/source/test/iotest/strtst.c --- icu-64.2/source/test/iotest/strtst.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/iotest/strtst.c 2019-10-03 11:16:41.000000000 +0000 @@ -313,7 +313,7 @@ } #if !UCONFIG_NO_FORMATTING -#define Test_u_snprintf(limit, format, value, expectedSize, expectedStr) \ +#define Test_u_snprintf(limit, format, value, expectedSize, expectedStr) UPRV_BLOCK_MACRO_BEGIN { \ u_uastrncpy(testStr, "xxxxxxxxxxxxxx", UPRV_LENGTHOF(testStr));\ size = u_snprintf(testStr, limit, format, value);\ u_austrncpy(cTestResult, testStr, UPRV_LENGTHOF(cTestResult));\ @@ -324,6 +324,7 @@ else {\ log_verbose("Got: %s\n", cTestResult);\ }\ +} UPRV_BLOCK_MACRO_END #endif @@ -358,7 +359,7 @@ #endif } -#define TestSPrintFormat(uFormat, uValue, cFormat, cValue) \ +#define TestSPrintFormat(uFormat, uValue, cFormat, cValue) UPRV_BLOCK_MACRO_BEGIN { \ /* Reinitialize the buffer to verify null termination works. */\ u_memset(uBuffer, 0x2a, UPRV_LENGTHOF(uBuffer));\ memset(buffer, '*', UPRV_LENGTHOF(buffer));\ @@ -375,6 +376,7 @@ if (buffer[uNumPrinted+1] != '*') {\ log_err("%" uFormat " too much stored\n");\ }\ +} UPRV_BLOCK_MACRO_END static void TestSprintfFormat(void) { #if !UCONFIG_NO_FORMATTING @@ -687,6 +689,7 @@ static void TestBadSScanfFormat(const char *format, const UChar *uValue, const char *cValue) { #if !UCONFIG_NO_FORMATTING + (void)cValue; // suppress compiler warnings about unused variable UChar uBuffer[256]; int32_t uNumScanned; diff -Nru icu-64.2/source/test/letest/gendata.vcxproj icu-65.1/source/test/letest/gendata.vcxproj --- icu-64.2/source/test/letest/gendata.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/letest/gendata.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -114,7 +114,6 @@ true .\x86\Debug/gendata.pdb Console - false @@ -153,7 +152,6 @@ true .\x64\Debug/gendata.pdb Console - false MachineX64 @@ -191,7 +189,6 @@ true .\x86\Release/gendata.pdb Console - false @@ -229,7 +226,6 @@ true .\x64\Release/gendata.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/letest/letest.cpp icu-65.1/source/test/letest/letest.cpp --- icu-64.2/source/test/letest/letest.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/letest/letest.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -244,7 +244,7 @@ SimpleFontInstance *font = new SimpleFontInstance(12, status); LayoutEngine *engine = LayoutEngine::layoutEngineFactory(font, arabScriptCode, -1, status); le_int32 glyphCount; - LEGlyphID glyphs[6], extraBitGlyphs[6];; + LEGlyphID glyphs[6], extraBitGlyphs[6]; le_int32 biasedIndices[6], indices[6], glyph; float positions[6 * 2 + 2]; LEUnicode chars[] = { diff -Nru icu-64.2/source/test/letest/letest.vcxproj icu-65.1/source/test/letest/letest.vcxproj --- icu-64.2/source/test/letest/letest.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/letest/letest.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -114,7 +114,6 @@ .\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/letest.pdb Console - false @@ -154,7 +153,6 @@ true .\x86\Debug/letest.pdb Console - false diff -Nru icu-64.2/source/test/Makefile.in icu-65.1/source/test/Makefile.in --- icu-64.2/source/test/Makefile.in 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/Makefile.in 2019-10-03 11:16:41.000000000 +0000 @@ -15,6 +15,8 @@ ## Build directory information subdir = test +@FUZZER_TRUE@FUZZER=fuzzer + @ICUIO_TRUE@IOTEST = iotest # the letest directory depends on layoutex. @@ -32,7 +34,7 @@ ## Files to remove for 'make clean' CLEANFILES = *~ $(STATUS_TMP) -SUBDIRS = $(TESTDATA) intltest $(IOTEST) cintltst $(LETEST) +SUBDIRS = $(TESTDATA) intltest $(IOTEST) cintltst $(LETEST) $(FUZZER) ## List of phony targets .PHONY : everything all all-local all-recursive install install-local \ @@ -140,6 +142,8 @@ @goods=; \ bads=; \ echo "----------------------------------------"; \ + echo $SUBDIRS \ + echo "----------------------------------------"; \ for subdir in $(SUBDIRS); do \ if [ -s "$(MYSTATUS_R).$$subdir" ]; then \ echo "-------------" ; \ diff -Nru icu-64.2/source/test/perf/charperf/charperf.vcxproj icu-65.1/source/test/perf/charperf/charperf.vcxproj --- icu-64.2/source/test/perf/charperf/charperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/charperf/charperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -115,7 +115,6 @@ true .\x86\Debug/charperf.pdb Console - false @@ -157,7 +156,6 @@ true .\x64\Debug/charperf.pdb Console - false MachineX64 @@ -198,7 +196,6 @@ ..\..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/charperf.pdb Console - false MachineX86 @@ -240,7 +237,6 @@ ..\..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/charperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/collperf/collperf.vcxproj icu-65.1/source/test/perf/collperf/collperf.vcxproj --- icu-64.2/source/test/perf/collperf/collperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/collperf/collperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -113,7 +113,6 @@ true .\x86\Debug/collperf.pdb Console - false @@ -153,7 +152,6 @@ true .\x64\Debug/collperf.pdb Console - false MachineX64 @@ -192,7 +190,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/collperf.pdb Console - false MachineX86 @@ -232,7 +229,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/collperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/collperf2/collperf2.vcxproj icu-65.1/source/test/perf/collperf2/collperf2.vcxproj --- icu-64.2/source/test/perf/collperf2/collperf2.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/collperf2/collperf2.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -113,7 +113,6 @@ true .\x86\Debug/collperf2.pdb Console - false @@ -153,7 +152,6 @@ true .\x64\Debug/collperf2.pdb Console - false MachineX64 @@ -192,7 +190,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/collperf2.pdb Console - false MachineX86 @@ -232,7 +229,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/collperf2.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/convperf/convperf.vcxproj icu-65.1/source/test/perf/convperf/convperf.vcxproj --- icu-64.2/source/test/perf/convperf/convperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/convperf/convperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -114,7 +114,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/convperf.pdb Console - false MachineX86 @@ -156,7 +155,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/convperf.pdb Console - false MachineX64 @@ -198,7 +196,6 @@ true .\x86\Debug/convperf.pdb Console - false @@ -240,7 +237,6 @@ true .\x64\Debug/convperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/DateFmtPerf/DateFmtPerf.vcxproj icu-65.1/source/test/perf/DateFmtPerf/DateFmtPerf.vcxproj --- icu-64.2/source/test/perf/DateFmtPerf/DateFmtPerf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/DateFmtPerf/DateFmtPerf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -95,7 +95,6 @@ - false MachineX86 diff -Nru icu-64.2/source/test/perf/normperf/dtfmtrtperf.vcxproj icu-65.1/source/test/perf/normperf/dtfmtrtperf.vcxproj --- icu-64.2/source/test/perf/normperf/dtfmtrtperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/normperf/dtfmtrtperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -118,7 +118,6 @@ true .\x86\Debug/dtfmtrtperf.pdb Console - false @@ -158,7 +157,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/normperf.pdb Console - false MachineX86 @@ -201,7 +199,6 @@ true .\x64\Debug/normperf.pdb Console - false MachineX64 @@ -243,7 +240,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/normperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/normperf/normperf.vcxproj icu-65.1/source/test/perf/normperf/normperf.vcxproj --- icu-64.2/source/test/perf/normperf/normperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/normperf/normperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -115,7 +115,6 @@ true .\x86\Debug/normperf.pdb Console - false @@ -157,7 +156,6 @@ true .\x64\Debug/normperf.pdb Console - false MachineX64 @@ -198,7 +196,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/normperf.pdb Console - false MachineX86 @@ -240,7 +237,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/normperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/strsrchperf/strsrchperf.vcxproj icu-65.1/source/test/perf/strsrchperf/strsrchperf.vcxproj --- icu-64.2/source/test/perf/strsrchperf/strsrchperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/strsrchperf/strsrchperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -115,7 +115,6 @@ true .\x86\Debug/strsrchperf.pdb Console - false @@ -157,7 +156,6 @@ true .\x64\Debug/strsrchperf.pdb Console - false MachineX64 @@ -198,7 +196,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/strsrchperf.pdb Console - false MachineX86 @@ -240,7 +237,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/strsrchperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/ubrkperf/ubrkperf.vcxproj icu-65.1/source/test/perf/ubrkperf/ubrkperf.vcxproj --- icu-64.2/source/test/perf/ubrkperf/ubrkperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/ubrkperf/ubrkperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -113,7 +113,6 @@ true .\x86\Debug/ubrkperf.pdb Console - false @@ -151,7 +150,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/ubrkperf24.pdb Console - false MachineX86 @@ -192,7 +190,6 @@ true .\x64\Debug/ubrkperf.pdb Console - false MachineX64 @@ -232,7 +229,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/ubrkperf24.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/unisetperf/unisetperf.vcxproj icu-65.1/source/test/perf/unisetperf/unisetperf.vcxproj --- icu-64.2/source/test/perf/unisetperf/unisetperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/unisetperf/unisetperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -112,7 +112,6 @@ true .\x86\Debug/unisetperf.pdb Console - false MachineX86 @@ -152,7 +151,6 @@ true .\x64\Debug/unisetperf.pdb Console - false MachineX64 @@ -191,7 +189,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/unisetperf.pdb Console - false MachineX86 @@ -231,7 +228,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/unisetperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/usetperf/usetperf.vcxproj icu-65.1/source/test/perf/usetperf/usetperf.vcxproj --- icu-64.2/source/test/perf/usetperf/usetperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/usetperf/usetperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -112,7 +112,6 @@ ..\..\..\..\lib;%(AdditionalLibraryDirectories) .\x86\Release/usetperf.pdb Console - false MachineX86 @@ -152,7 +151,6 @@ ..\..\..\..\lib64;%(AdditionalLibraryDirectories) .\x64\Release/usetperf.pdb Console - false MachineX64 @@ -191,7 +189,6 @@ true .\x86\Debug/usetperf.pdb Console - false @@ -230,7 +227,6 @@ true .\x64\Debug/usetperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/ustrperf/stringperf.vcxproj icu-65.1/source/test/perf/ustrperf/stringperf.vcxproj --- icu-64.2/source/test/perf/ustrperf/stringperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/ustrperf/stringperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -114,7 +114,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/stringperf.pdb Console - false MachineX86 @@ -156,7 +155,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/stringperf.pdb Console - false MachineX64 @@ -198,7 +196,6 @@ true .\x86\Debug/stringperf.pdb Console - false @@ -240,7 +237,6 @@ true .\x64\Debug/stringperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/utfperf/utfperf.vcxproj icu-65.1/source/test/perf/utfperf/utfperf.vcxproj --- icu-64.2/source/test/perf/utfperf/utfperf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/utfperf/utfperf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -112,7 +112,6 @@ true .\x86\Debug/utfperf.pdb Console - false @@ -151,7 +150,6 @@ true .\x64\Debug/utfperf.pdb Console - false MachineX64 @@ -190,7 +188,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/utfperf.pdb Console - false MachineX86 @@ -230,7 +227,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/utfperf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/perf/utrie2perf/utrie2perf.vcxproj icu-65.1/source/test/perf/utrie2perf/utrie2perf.vcxproj --- icu-64.2/source/test/perf/utrie2perf/utrie2perf.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/perf/utrie2perf/utrie2perf.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -112,7 +112,6 @@ true .\x86\Debug/utrie2perf.pdb Console - false @@ -151,7 +150,6 @@ true .\x64\Debug/utrie2perf.pdb Console - false MachineX64 @@ -190,7 +188,6 @@ ..\..\..\..\lib\;%(AdditionalLibraryDirectories) .\x86\Release/utrie2perf.pdb Console - false MachineX86 @@ -230,7 +227,6 @@ ..\..\..\..\lib64\;%(AdditionalLibraryDirectories) .\x64\Release/utrie2perf.pdb Console - false MachineX64 diff -Nru icu-64.2/source/test/testdata/break_rules/grapheme.txt icu-65.1/source/test/testdata/break_rules/grapheme.txt --- icu-64.2/source/test/testdata/break_rules/grapheme.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/break_rules/grapheme.txt 2019-10-03 11:16:41.000000000 +0000 @@ -37,6 +37,13 @@ Extended_Pict = [:ExtPict:]; +# Indic Sequences +Virama_ = [[\p{Gujr}\p{sc=Telu}\p{sc=Mlym}\p{sc=Orya}\p{sc=Beng}\p{sc=Deva}] & [\p{Indic_Syllabic_Category=Virama}]]; + +LinkingConsonant = [[\p{Gujr}\p{sc=Telu}\p{sc=Mlym}\p{sc=Orya}\p{sc=Beng}\p{sc=Deva}] & [\p{Indic_Syllabic_Category=Consonant}]]; + +ExtCccZwj = [[Extend-[\p{ccc=0}]] ZWJ]; + GB3: CR LF; GB4: (Control | CR | LF) ÷; GB5: . ÷ (Control | CR | LF); @@ -46,6 +53,7 @@ GB8: (LVT | T) T; GB11: Extended_Pict Extend* ZWJ Extended_Pict; +GB9c: LinkingConsonant ExtCccZwj* Virama_ ExtCccZwj* LinkingConsonant; GB9: . (Extend | ZWJ); GB9a: . SpacingMark; diff -Nru icu-64.2/source/test/testdata/break_rules/README.md icu-65.1/source/test/testdata/break_rules/README.md --- icu-64.2/source/test/testdata/break_rules/README.md 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/testdata/break_rules/README.md 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,100 @@ + + +This directory contains the break iterator reference rule files used by intltest rbbi/RBBIMonkeyTest/testMonkey. +=========================================== + +The rules in this directory track the boundary rules from Unicode UAX 14 and 29. They are interpreted +to provide an expected set of boundary positions to compare with the results from ICU break iteration. + +ICU4J also includes copies of the test reference rules, located in the directory +main/tests/core/src/com/ibm/icu/dev/test/rbbi/break_rules/ +The copies should be kept synchronized; there should be no differences. + +Each set of reference break rules lives in a separate file. +The list of rule files to run by default is hard coded into the test code, in rbbimonkeytest.cpp. + +Each test file includes + - The type of ICU break iterator to create (word, line, sentence, etc.) + - The locale to use + - Character Class definitions + - Rule definitions + +To Do + - Extend the syntax to support rule tailoring. + + +**character class definition** + + name = set_regular_expression; + +*caution* When referenced, these definitions are textually substituted into the overall rule. +To avoid unexpected behavior, include [brackets] around the full definition + + letter_number = [:Letter:][:Number:]; + +Will compile, but will produce unexpected results. + + letter_number = [[:Letter:][:Number:]]; + +is safe. The issue is similar to the problems that can occur with the C preprocessor +and the use of parentheses around macro paramteters. + +**rule definition** + + rule_regular_expression; + +**name** + + [A-Za-z_][A-Za-z0-9_]* + +**set_regular_expression** + +The intersection of an ICU regular expression [set] expression and a UnicodeSet pattern +(They are mostly the same). May include previously defined set names, which are logically +expanded in-place. + +**rule_regular_expression** + + An ICU Regular Expression. + May include set names, which are logically expanded in-place. + May include a '÷', which defines a boundary position. + +Application of the rules: + +Matching begins at the start of text, or after a previously identified boundary. +The pseudo-code below finds the next boundary. + + while position < end of text + for each rule + if the text at position matches this rule + if the rule has a '÷' + Boundary is found. + return the position of the '÷' within the match. + else + position = last character of the rule match. + break from the inner rule loop, continue the outer loop. + +This differs from the Unicode UAX algorithm in that each position in the text is +not tested separately. Instead, when a rule match is found, rule application restarts with the last +character of the preceding rule match. ICU's break rules also operate this way. + +Expressing rules this way simplifies UAX rules that have leading or trailing context; it +is no longer necessary to write expressions that match the context starting from +any position within it. + +This rule form differs from ICU rules in that the rules are applied sequentially, as they +are with the Unicode UAX rules. With the main ICU break rules, all are applied in parallel. + +**Word Dictionaries** + + +The monkey test does not test dictionary based breaking. The set named 'dictionary' is special, +as it is in the main ICU rules. For the monkey test, no characters from the dictionary set are +included in the randomly-generated test data. + + diff -Nru icu-64.2/source/test/testdata/break_rules/readme.txt icu-65.1/source/test/testdata/break_rules/readme.txt --- icu-64.2/source/test/testdata/break_rules/readme.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/break_rules/readme.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -file: testdata/break_rules/readme.txt -Copyright (C) 2016 and later: Unicode, Inc. and others. -License & terms of use: http://www.unicode.org/copyright.html#License - -Copyright (c) 2015-2016, International Business Machines Corporation and others. All Rights Reserved. - -This directory contains the break iterator reference rule files used by intltest rbbi/RBBIMonkeyTest/testMonkey. -The rules in this directory track the boundary rules from Unicode UAX 14 and 29. They are interpreted -to provide an expected set of boundary positions to compare with the results from ICU break iteration. - -ICU4J also includes copies of the test reference rules, located in the directory -main/tests/core/src/com/ibm/icu/dev/test/rbbi/break_rules/ -The copies should be kept synchronized; there should be no differences. - -Each set of reference break rules lives in a separate file. -The list of rule files to run by default is hard coded into the test code, in rbbimonkeytest.cpp. - -Each test file includes - - The type of ICU break iterator to create (word, line, sentence, etc.) - - The locale to use - - Character Class definitions - - Rule definitions - -To Do - - Extend the syntax to support rule tailoring. - - -Character Class Definition: - name = set_regular_expression; - -Rule Definition: - rule_regular_expression; - -name: - [A-Za-z_][A-Za-z0-9_]* - -set_regular_expression: - The intersection of an ICU regular expression [set] expression and a UnicodeSet pattern. - (They are mostly the same) - May include previously defined set names, which are logically expanded in-place. - -rule_regular_expression: - An ICU Regular Expression. - May include set names, which are logically expanded in-place. - May include a '÷', which defines a boundary position. - -Application of the rules: - Matching begins at the start of text, or after a previously identified boundary. - The pseudo-code below finds the next boundary. - - while position < end of text - for each rule - if the text at position matches this rule - if the rule has a '÷' - Boundary is found. - return the position of the '÷' within the match. - else - position = last character of the rule match. - break from the inner rule loop, continue the outer loop. - - This differs from the Unicode UAX algorithm in that each position in the text is - not tested separately. Instead, when a rule match is found, rule application restarts with the last - character of the preceding rule match. ICU's break rules also operate this way. - - Expressing rules this way simplifies UAX rules that have leading or trailing context; it - is no longer necessary to write expressions that match the context starting from - any position within it. - - This rule form differs from ICU rules in that the rules are applied sequentially, as they - are with the Unicode UAX rules. With the main ICU break rules, all are applied in parallel. - -Word Dictionaries - The monkey test does not test dictionary based breaking. The set named 'dictionary' is special, - as it is in the main ICU rules. For the monkey test, no characters from the dictionary set are - included in the randomly-generated test data. - diff -Nru icu-64.2/source/test/testdata/BUILDRULES.py icu-65.1/source/test/testdata/BUILDRULES.py --- icu-64.2/source/test/testdata/BUILDRULES.py 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/BUILDRULES.py 2019-10-03 11:16:41.000000000 +0000 @@ -1,10 +1,8 @@ # Copyright (C) 2018 and later: Unicode, Inc. and others. # License & terms of use: http://www.unicode.org/copyright.html -from distutils.sysconfig import parse_makefile - -from buildtool import * -from buildtool.request_types import * +from icutools.databuilder import * +from icutools.databuilder.request_types import * def generate(config, glob, common_vars): @@ -28,24 +26,24 @@ def generate_rb(config, glob, common_vars): - mk_vars = parse_makefile("{GLOB_DIR}/tstfiles.mk".format(**common_vars)) - basenames = [v[:-4] for v in mk_vars["TEST_RES_SOURCE"].split()] - basenames += [ + basenames = [ + "calendar", "casing", + "conversion", + "format", + "icuio", + "idna_rules", "mc", "root", - "sh", "sh_YU", - "te", - "te_IN", + "sh", + "structLocale", "te_IN_REVISED", - "testtypes", + "te_IN", + "te", "testaliases", "testempty", - "structLocale", - "idna_rules", - "conversion", - "icuio", + "testtypes", # "metaZones", # "timezoneTypes", # "windowsZones", diff -Nru icu-64.2/source/test/testdata/filters/filtertest.txt icu-65.1/source/test/testdata/filters/filtertest.txt --- icu-64.2/source/test/testdata/filters/filtertest.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/filters/filtertest.txt 2019-10-03 11:16:41.000000000 +0000 @@ -1,6 +1,7 @@ # Copyright (C) 2018 and later: Unicode, Inc. and others. # License & terms of use: http://www.unicode.org/copyright.html +-/ -/alabama +/alabama/alaska/arizona -/fornia/illinois @@ -9,3 +10,4 @@ +/mississippi/*/maine -/mississippi/*/iowa +/mississippi/louisiana/iowa ++/northCarolina diff -Nru icu-64.2/source/test/testdata/filtertest.txt icu-65.1/source/test/testdata/filtertest.txt --- icu-64.2/source/test/testdata/filtertest.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/filtertest.txt 2019-10-03 11:16:41.000000000 +0000 @@ -34,4 +34,7 @@ missouri {"new-york"} } } + northCarolina { + northDakota {"west-virginia"} + } } diff -Nru icu-64.2/source/test/testdata/GraphemeBreakTest.txt icu-65.1/source/test/testdata/GraphemeBreakTest.txt --- icu-64.2/source/test/testdata/GraphemeBreakTest.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/GraphemeBreakTest.txt 2019-10-03 11:16:41.000000000 +0000 @@ -1,5 +1,5 @@ -# GraphemeBreakTest-12.1.0.txt -# Date: 2019-03-10, 10:53:12 GMT +# GraphemeBreakTest-12.0.0.txt +# Date: 2019-02-21, 07:57:26 GMT # © 2019 Unicode®, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html @@ -48,10 +48,14 @@ ÷ 0020 × 0308 ÷ AC00 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 0020 ÷ AC01 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 0020 × 0308 ÷ AC01 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0020 ÷ 0915 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0020 × 0308 ÷ 0915 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 0020 ÷ 231A ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0020 × 0308 ÷ 231A ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0020 × 0300 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 0020 × 0308 × 0300 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0020 × 094D ÷ # ÷ [0.2] SPACE (Other) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0020 × 0308 × 094D ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 0020 × 200D ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0020 × 0308 × 200D ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0020 ÷ 0378 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] (Other) ÷ [0.3] @@ -82,10 +86,14 @@ ÷ 000D ÷ 0308 ÷ AC00 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 000D ÷ AC01 ÷ # ÷ [0.2] (CR) ÷ [4.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 000D ÷ 0308 ÷ AC01 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 000D ÷ 0915 ÷ # ÷ [0.2] (CR) ÷ [4.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 000D ÷ 0308 ÷ 0915 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 000D ÷ 231A ÷ # ÷ [0.2] (CR) ÷ [4.0] WATCH (ExtPict) ÷ [0.3] ÷ 000D ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 000D ÷ 0300 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 000D ÷ 0308 × 0300 ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 000D ÷ 094D ÷ # ÷ [0.2] (CR) ÷ [4.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 000D ÷ 0308 × 094D ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 000D ÷ 200D ÷ # ÷ [0.2] (CR) ÷ [4.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 000D ÷ 0308 × 200D ÷ # ÷ [0.2] (CR) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 000D ÷ 0378 ÷ # ÷ [0.2] (CR) ÷ [4.0] (Other) ÷ [0.3] @@ -116,10 +124,14 @@ ÷ 000A ÷ 0308 ÷ AC00 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 000A ÷ AC01 ÷ # ÷ [0.2] (LF) ÷ [4.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 000A ÷ 0308 ÷ AC01 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 000A ÷ 0915 ÷ # ÷ [0.2] (LF) ÷ [4.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 000A ÷ 0308 ÷ 0915 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 000A ÷ 231A ÷ # ÷ [0.2] (LF) ÷ [4.0] WATCH (ExtPict) ÷ [0.3] ÷ 000A ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 000A ÷ 0300 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 000A ÷ 0308 × 0300 ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 000A ÷ 094D ÷ # ÷ [0.2] (LF) ÷ [4.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 000A ÷ 0308 × 094D ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 000A ÷ 200D ÷ # ÷ [0.2] (LF) ÷ [4.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 000A ÷ 0308 × 200D ÷ # ÷ [0.2] (LF) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 000A ÷ 0378 ÷ # ÷ [0.2] (LF) ÷ [4.0] (Other) ÷ [0.3] @@ -150,10 +162,14 @@ ÷ 0001 ÷ 0308 ÷ AC00 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 0001 ÷ AC01 ÷ # ÷ [0.2] (Control) ÷ [4.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 0001 ÷ 0308 ÷ AC01 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0001 ÷ 0915 ÷ # ÷ [0.2] (Control) ÷ [4.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0001 ÷ 0308 ÷ 0915 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 0001 ÷ 231A ÷ # ÷ [0.2] (Control) ÷ [4.0] WATCH (ExtPict) ÷ [0.3] ÷ 0001 ÷ 0308 ÷ 231A ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0001 ÷ 0300 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 0001 ÷ 0308 × 0300 ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0001 ÷ 094D ÷ # ÷ [0.2] (Control) ÷ [4.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0001 ÷ 0308 × 094D ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 0001 ÷ 200D ÷ # ÷ [0.2] (Control) ÷ [4.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0001 ÷ 0308 × 200D ÷ # ÷ [0.2] (Control) ÷ [4.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0001 ÷ 0378 ÷ # ÷ [0.2] (Control) ÷ [4.0] (Other) ÷ [0.3] @@ -184,10 +200,14 @@ ÷ 034F × 0308 ÷ AC00 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 034F ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 034F × 0308 ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 034F ÷ 0915 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 034F × 0308 ÷ 0915 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 034F ÷ 231A ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 034F × 0308 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 034F × 0300 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 034F × 0308 × 0300 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 034F × 094D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 034F × 0308 × 094D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 034F × 200D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 034F × 0308 × 200D ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 034F ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAPHEME JOINER (Extend) ÷ [999.0] (Other) ÷ [0.3] @@ -218,10 +238,14 @@ ÷ 1F1E6 × 0308 ÷ AC00 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 1F1E6 ÷ AC01 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 1F1E6 × 0308 ÷ AC01 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1F1E6 ÷ 0915 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 1F1E6 × 0308 ÷ 0915 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 1F1E6 ÷ 231A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 1F1E6 × 0308 ÷ 231A ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 1F1E6 × 0300 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 1F1E6 × 0308 × 0300 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1F1E6 × 094D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 1F1E6 × 0308 × 094D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 1F1E6 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 1F1E6 × 0308 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 1F1E6 ÷ 0378 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] (Other) ÷ [0.3] @@ -252,10 +276,14 @@ ÷ 0600 × 0308 ÷ AC00 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 0600 × AC01 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 0600 × 0308 ÷ AC01 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0600 × 0915 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0600 × 0308 ÷ 0915 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 0600 × 231A ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] WATCH (ExtPict) ÷ [0.3] ÷ 0600 × 0308 ÷ 231A ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0600 × 0300 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 0600 × 0308 × 0300 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0600 × 094D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0600 × 0308 × 094D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 0600 × 200D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0600 × 0308 × 200D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0600 × 0378 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] (Other) ÷ [0.3] @@ -286,10 +314,14 @@ ÷ 0903 × 0308 ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 0903 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 0903 × 0308 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0903 ÷ 0915 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0903 × 0308 ÷ 0915 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 0903 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0903 × 0308 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0903 × 0300 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 0903 × 0308 × 0300 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0903 × 094D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0903 × 0308 × 094D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 0903 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0903 × 0308 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0903 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] (Other) ÷ [0.3] @@ -320,10 +352,14 @@ ÷ 1100 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 1100 × AC01 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [6.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 1100 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1100 ÷ 0915 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 1100 × 0308 ÷ 0915 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 1100 ÷ 231A ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 1100 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 1100 × 0300 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 1100 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1100 × 094D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 1100 × 0308 × 094D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 1100 × 200D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 1100 × 0308 × 200D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 1100 ÷ 0378 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] (Other) ÷ [0.3] @@ -354,10 +390,14 @@ ÷ 1160 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 1160 ÷ AC01 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 1160 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 1160 ÷ 0915 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 1160 × 0308 ÷ 0915 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 1160 ÷ 231A ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 1160 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 1160 × 0300 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 1160 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 1160 × 094D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 1160 × 0308 × 094D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 1160 × 200D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 1160 × 0308 × 200D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 1160 ÷ 0378 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] (Other) ÷ [0.3] @@ -388,10 +428,14 @@ ÷ 11A8 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 11A8 ÷ AC01 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 11A8 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 11A8 ÷ 0915 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 11A8 × 0308 ÷ 0915 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 11A8 ÷ 231A ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 11A8 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 11A8 × 0300 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 11A8 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 11A8 × 094D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 11A8 × 0308 × 094D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 11A8 × 200D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 11A8 × 0308 × 200D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 11A8 ÷ 0378 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] (Other) ÷ [0.3] @@ -422,10 +466,14 @@ ÷ AC00 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ AC00 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ AC00 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ AC00 ÷ 0915 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ AC00 × 0308 ÷ 0915 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ AC00 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ AC00 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ AC00 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ AC00 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ AC00 × 094D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ AC00 × 0308 × 094D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ AC00 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ AC00 × 0308 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ AC00 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] (Other) ÷ [0.3] @@ -456,14 +504,56 @@ ÷ AC01 × 0308 ÷ AC00 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ AC01 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ AC01 × 0308 ÷ AC01 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ AC01 ÷ 0915 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ AC01 × 0308 ÷ 0915 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ AC01 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ AC01 × 0308 ÷ 231A ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ AC01 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ AC01 × 0308 × 0300 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ AC01 × 094D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ AC01 × 0308 × 094D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ AC01 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ AC01 × 0308 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ AC01 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] (Other) ÷ [0.3] ÷ AC01 × 0308 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 0915 ÷ 0020 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0915 × 0308 ÷ 0020 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 0915 ÷ 000D ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [5.0] (CR) ÷ [0.3] +÷ 0915 × 0308 ÷ 000D ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 0915 ÷ 000A ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [5.0] (LF) ÷ [0.3] +÷ 0915 × 0308 ÷ 000A ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 0915 ÷ 0001 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [5.0] (Control) ÷ [0.3] +÷ 0915 × 0308 ÷ 0001 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 0915 × 034F ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0915 × 0308 × 034F ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 0915 ÷ 1F1E6 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0915 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 0915 ÷ 0600 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0915 × 0308 ÷ 0600 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 0915 × 0903 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0915 × 0308 × 0903 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 0915 ÷ 1100 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0915 × 0308 ÷ 1100 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 0915 ÷ 1160 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0915 × 0308 ÷ 1160 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 0915 ÷ 11A8 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0915 × 0308 ÷ 11A8 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 0915 ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0915 × 0308 ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 0915 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0915 × 0308 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0915 ÷ 0915 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 0308 ÷ 0915 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0915 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0915 × 0308 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 0915 × 0300 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0915 × 0308 × 0300 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0915 × 094D ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0915 × 0308 × 094D ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0915 × 200D ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0915 × 0308 × 200D ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 0915 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] (Other) ÷ [0.3] +÷ 0915 × 0308 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] ÷ 231A ÷ 0020 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] SPACE (Other) ÷ [0.3] ÷ 231A × 0308 ÷ 0020 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] ÷ 231A ÷ 000D ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [5.0] (CR) ÷ [0.3] @@ -490,10 +580,14 @@ ÷ 231A × 0308 ÷ AC00 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 231A ÷ AC01 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 231A × 0308 ÷ AC01 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 231A ÷ 0915 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 231A × 0308 ÷ 0915 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 231A ÷ 231A ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 231A × 0308 ÷ 231A ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 231A × 0300 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 231A × 0308 × 0300 ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 231A × 094D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 231A × 0308 × 094D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 231A × 200D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 231A × 0308 × 200D ÷ # ÷ [0.2] WATCH (ExtPict) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 231A ÷ 0378 ÷ # ÷ [0.2] WATCH (ExtPict) ÷ [999.0] (Other) ÷ [0.3] @@ -524,14 +618,56 @@ ÷ 0300 × 0308 ÷ AC00 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 0300 ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 0300 × 0308 ÷ AC01 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0300 ÷ 0915 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0300 × 0308 ÷ 0915 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 0300 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0300 × 0308 ÷ 231A ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0300 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 0300 × 0308 × 0300 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0300 × 094D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0300 × 0308 × 094D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 0300 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0300 × 0308 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0300 ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] ÷ 0300 × 0308 ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 094D ÷ 0020 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 094D × 0308 ÷ 0020 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] +÷ 094D ÷ 000D ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 094D × 0308 ÷ 000D ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] +÷ 094D ÷ 000A ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 094D × 0308 ÷ 000A ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (LF) ÷ [0.3] +÷ 094D ÷ 0001 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 094D × 0308 ÷ 0001 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [5.0] (Control) ÷ [0.3] +÷ 094D × 034F ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 094D × 0308 × 034F ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAPHEME JOINER (Extend) ÷ [0.3] +÷ 094D ÷ 1F1E6 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 094D × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3] +÷ 094D ÷ 0600 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 094D × 0308 ÷ 0600 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3] +÷ 094D × 0903 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 094D × 0308 × 0903 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3] +÷ 094D ÷ 1100 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 094D × 0308 ÷ 1100 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3] +÷ 094D ÷ 1160 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 094D × 0308 ÷ 1160 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3] +÷ 094D ÷ 11A8 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 094D × 0308 ÷ 11A8 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3] +÷ 094D ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 094D × 0308 ÷ AC00 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] +÷ 094D ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 094D × 0308 ÷ AC01 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 094D ÷ 0915 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 094D × 0308 ÷ 0915 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 094D ÷ 231A ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 094D × 0308 ÷ 231A ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] +÷ 094D × 0300 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 094D × 0308 × 0300 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 094D × 094D ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 094D × 0308 × 094D ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 094D × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 094D × 0308 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] +÷ 094D ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] +÷ 094D × 0308 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] ÷ 200D ÷ 0020 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] ÷ 200D × 0308 ÷ 0020 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] SPACE (Other) ÷ [0.3] ÷ 200D ÷ 000D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [5.0] (CR) ÷ [0.3] @@ -558,10 +694,14 @@ ÷ 200D × 0308 ÷ AC00 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 200D ÷ AC01 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 200D × 0308 ÷ AC01 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 200D ÷ 0915 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 200D × 0308 ÷ 0915 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 200D ÷ 231A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 200D × 0308 ÷ 231A ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 200D × 0300 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 200D × 0308 × 0300 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 200D × 094D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 200D × 0308 × 094D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 200D × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 200D × 0308 × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 200D ÷ 0378 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] (Other) ÷ [0.3] @@ -592,10 +732,14 @@ ÷ 0378 × 0308 ÷ AC00 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3] ÷ 0378 ÷ AC01 ÷ # ÷ [0.2] (Other) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] ÷ 0378 × 0308 ÷ AC01 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3] +÷ 0378 ÷ 0915 ÷ # ÷ [0.2] (Other) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] +÷ 0378 × 0308 ÷ 0915 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [0.3] ÷ 0378 ÷ 231A ÷ # ÷ [0.2] (Other) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0378 × 0308 ÷ 231A ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] WATCH (ExtPict) ÷ [0.3] ÷ 0378 × 0300 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] ÷ 0378 × 0308 × 0300 ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] COMBINING GRAVE ACCENT (Extend_ExtCccZwj) ÷ [0.3] +÷ 0378 × 094D ÷ # ÷ [0.2] (Other) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] +÷ 0378 × 0308 × 094D ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [0.3] ÷ 0378 × 200D ÷ # ÷ [0.2] (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0378 × 0308 × 200D ÷ # ÷ [0.2] (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [0.3] ÷ 0378 ÷ 0378 ÷ # ÷ [0.2] (Other) ÷ [999.0] (Other) ÷ [0.3] @@ -616,6 +760,15 @@ ÷ 0061 × 0308 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] COMBINING DIAERESIS (Extend_ExtCccZwj) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] ÷ 0061 × 0903 ÷ 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] LATIN SMALL LETTER B (Other) ÷ [0.3] ÷ 0061 ÷ 0600 × 0062 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) × [9.2] LATIN SMALL LETTER B (Other) ÷ [0.3] +÷ 0915 ÷ 0924 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) ÷ [999.0] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 094D × 0924 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.3] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 094D × 200D × 0924 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.3] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 093C × 200D × 094D × 0924 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN NUKTA (Extend_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.3] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 093C × 094D × 200D × 0924 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN NUKTA (Extend_ExtCccZwj) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [9.3] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 094D × 0924 × 094D × 092F ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.3] DEVANAGARI LETTER TA (LinkingConsonant) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) × [9.3] DEVANAGARI LETTER YA (LinkingConsonant) ÷ [0.3] +÷ 0915 × 094D ÷ 0061 ÷ # ÷ [0.2] DEVANAGARI LETTER KA (LinkingConsonant) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] LATIN SMALL LETTER A (Other) ÷ [0.3] +÷ 0061 × 094D ÷ 0924 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] +÷ 003F × 094D ÷ 0924 ÷ # ÷ [0.2] QUESTION MARK (Other) × [9.0] DEVANAGARI SIGN VIRAMA (Extend_Virama_ExtCccZwj) ÷ [999.0] DEVANAGARI LETTER TA (LinkingConsonant) ÷ [0.3] ÷ 1F476 × 1F3FF ÷ 1F476 ÷ # ÷ [0.2] BABY (ExtPict) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [999.0] BABY (ExtPict) ÷ [0.3] ÷ 0061 × 1F3FF ÷ 1F476 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [999.0] BABY (ExtPict) ÷ [0.3] ÷ 0061 × 1F3FF ÷ 1F476 × 200D × 1F6D1 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (Extend) ÷ [999.0] BABY (ExtPict) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [11.0] OCTAGONAL SIGN (ExtPict) ÷ [0.3] @@ -625,6 +778,6 @@ ÷ 2701 × 200D × 2701 ÷ # ÷ [0.2] UPPER BLADE SCISSORS (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) × [11.0] UPPER BLADE SCISSORS (Other) ÷ [0.3] ÷ 0061 × 200D ÷ 2701 ÷ # ÷ [0.2] LATIN SMALL LETTER A (Other) × [9.0] ZERO WIDTH JOINER (ZWJ_ExtCccZwj) ÷ [999.0] UPPER BLADE SCISSORS (Other) ÷ [0.3] # -# Lines: 602 +# Lines: 755 # # EOF diff -Nru icu-64.2/source/test/testdata/localeMatcherTest.txt icu-65.1/source/test/testdata/localeMatcherTest.txt --- icu-64.2/source/test/testdata/localeMatcherTest.txt 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/testdata/localeMatcherTest.txt 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,1959 @@ +# © 2017 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html#License +# +# Data-driven test for the language/locale matcher. +# Format: +# +# Everything after "#" is a comment. +# ** test: This line starts a group of test cases. +# +# Lines starting with an '@' sign provide matcher parameters. +# @supported= +# @default= # no value = no explicit default +# @favor=[normal|script] # no value = no explicit setting +# @threshold= # no value = no explicit setting +# +# A line with ">>" is a getBestMatch() test case: +# >> match | desired | combined +# - match is the expected best supported language +# - desired is the expected best desired language +# - combined is the expected result of combine(match, desired) +# An expected language can be "null" to check for the matcher returning null. +# An empty or omitted value is not tested. (Omitted = not even the '|' separator.) +# +# ** test: A new test group resets all matcher parameters. + +## X + +** test: testParentLocales + +# es-419, es-AR, and es-MX are in a cluster; es is in a different one + +@supported=es-419, es-ES +es-AR >> es-419 +@supported=es-ES, es-419 +es-AR >> es-419 + +@supported=es-419, es +es-AR >> es-419 +@supported=es, es-419 +es-AR >> es-419 + +@supported=es-MX, es +es-AR >> es-MX +@supported=es, es-MX +es-AR >> es-MX + +# en-GB, en-AU, and en-NZ are in a cluster; en in a different one + +@supported=en-GB, en-US +en-AU >> en-GB +@supported=en-US, en-GB +en-AU >> en-GB + +@supported=en-GB, en +en-AU >> en-GB +@supported=en, en-GB +en-AU >> en-GB + +@supported=en-NZ, en-US +en-AU >> en-NZ +@supported=en-US, en-NZ +en-AU >> en-NZ + +@supported=en-NZ, en +en-AU >> en-NZ +@supported=en, en-NZ +en-AU >> en-NZ + +# pt-AU and pt-PT in one cluster; pt-BR in another + +@supported=pt-PT, pt-BR +pt-AO >> pt-PT +@supported=pt-BR, pt-PT +pt-AO >> pt-PT + +@supported=pt-PT, pt +pt-AO >> pt-PT +@supported=pt, pt-PT +pt-AO >> pt-PT + +@supported=zh-MO, zh-TW +zh-HK >> zh-MO +@supported=zh-TW, zh-MO +zh-HK >> zh-MO + +@supported=zh-MO, zh-CN +zh-HK >> zh-MO +@supported=zh-CN, zh-MO +zh-HK >> zh-MO + +@supported=zh-MO, zh +zh-HK >> zh-MO +@supported=zh, zh-MO +zh-HK >> zh-MO + +@favor=script +@supported=es-419, es-ES +es-AR >> es-419 +@supported=es-ES, es-419 +es-AR >> es-419 +@supported=es-419, es +es-AR >> es-419 +@supported=es, es-419 +es-AR >> es-419 +@supported=es-MX, es +es-AR >> es-MX +@supported=es, es-MX +es-AR >> es-MX +@supported=en-GB, en-US +en-AU >> en-GB +@supported=en-US, en-GB +en-AU >> en-GB +@supported=en-GB, en +en-AU >> en-GB +@supported=en, en-GB +en-AU >> en-GB +@supported=en-NZ, en-US +en-AU >> en-NZ +@supported=en-US, en-NZ +en-AU >> en-NZ +@supported=en-NZ, en +en-AU >> en-NZ +@supported=en, en-NZ +en-AU >> en-NZ +@supported=pt-PT, pt-BR +pt-AO >> pt-PT +@supported=pt-BR, pt-PT +pt-AO >> pt-PT +@supported=pt-PT, pt +pt-AO >> pt-PT +@supported=pt, pt-PT +pt-AO >> pt-PT +@supported=zh-MO, zh-TW +zh-HK >> zh-MO +@supported=zh-TW, zh-MO +zh-HK >> zh-MO +@supported=zh-MO, zh-CN +zh-HK >> zh-MO +@supported=zh-CN, zh-MO +zh-HK >> zh-MO +@supported=zh-MO, zh +zh-HK >> zh-MO +@supported=zh, zh-MO +zh-HK >> zh-MO + +** test: testChinese + +@supported=zh-CN, zh-TW, iw +zh-Hant-TW >> zh-TW +zh-Hant >> zh-TW +zh-TW >> zh-TW +zh-Hans-CN >> zh-CN +zh-CN >> zh-CN +zh >> zh-CN + +@favor=script +zh-Hant-TW >> zh-TW +zh-Hant >> zh-TW +zh-TW >> zh-TW +zh-Hans-CN >> zh-CN +zh-CN >> zh-CN +zh >> zh-CN + +** test: testenGB + +@supported=fr, en, en-GB, es-419, es-MX, es +en-NZ >> en-GB +es-ES >> es +es-AR >> es-419 +es-MX >> es-MX + +@favor=script +en-NZ >> en-GB +es-ES >> es +es-AR >> es-419 +es-MX >> es-MX + +** test: testFallbacks + +@supported=91, en, hi +sa >> hi + +@favor=script +sa >> hi + +** test: testBasics + +@supported=fr, en-GB, en +en-GB >> en-GB +en >> en +fr >> fr +ja >> fr # return first if no match + +@favor=script +en-GB >> en-GB +en >> en +fr >> fr +ja >> fr + +** test: testFallback + +# check that script fallbacks are handled right + +@supported=zh-CN, zh-TW, iw +zh-Hant >> zh-TW +zh >> zh-CN +zh-Hans-CN >> zh-CN +zh-Hant-HK >> zh-TW +he-IT >> iw + +@favor=script +zh-Hant >> zh-TW +zh >> zh-CN +zh-Hans-CN >> zh-CN +zh-Hant-HK >> zh-TW +he-IT >> iw + +** test: testSpecials + +# check that nearby languages are handled + +@supported=en, fil, ro, nn +tl >> fil +mo >> ro +nb >> nn + +# make sure default works + +ja >> en + +@favor=script +tl >> fil +mo >> ro +nb >> nn +ja >> en + +** test: testRegionalSpecials + +# verify that en-AU is closer to en-GB than to en (which is en-US) + +@supported=en, en-GB, es, es-419 +es-MX >> es-419 +en-AU >> en-GB +es-ES >> es + +@favor=script +es-MX >> es-419 +en-AU >> en-GB +es-ES >> es + +** test: testHK + +# HK and MO are closer to each other for Hant than to TW + +@supported=zh, zh-TW, zh-MO +zh-HK >> zh-MO +@supported=zh, zh-TW, zh-HK +zh-MO >> zh-HK + +@favor=script +@supported=zh, zh-TW, zh-MO +zh-HK >> zh-MO +@supported=zh, zh-TW, zh-HK +zh-MO >> zh-HK + +** test: testMatch-matchOnMazimized + +@supported=zh, zh-Hant +und-TW >> zh-Hant # und-TW should be closer to zh-Hant than to zh + +@supported=en-Hant-TW, und-TW +zh-Hant >> und-TW # zh-Hant should be closer to und-TW than to en-Hant-TW +zh >> und-TW # zh should be closer to und-TW than to en-Hant-TW + +@favor=script +@supported=zh, zh-Hant +und-TW >> zh-Hant +@supported=en-Hant-TW, und-TW +zh-Hant >> und-TW +zh >> und-TW + +** test: testMatchGrandfatheredCode + +@supported=fr, i-klingon, en-Latn-US +en-GB-oed >> en-Latn-US + +@favor=script +en-GB-oed >> en-Latn-US + +** test: testGetBestMatchForList-exactMatch +@supported=fr, en-GB, ja, es-ES, es-MX +ja, de >> ja + +@favor=script +ja, de >> ja + +** test: testGetBestMatchForList-simpleVariantMatch +@supported=fr, en-GB, ja, es-ES, es-MX +de, en-US >> en-GB # Intentionally avoiding a perfect-match or two candidates for variant matches. + +# Fallback. + +de, zh >> fr + +@favor=script +de, en-US >> en-GB +de, zh >> fr + +** test: testGetBestMatchForList-matchOnMaximized +# Check that if the preference is maximized already, it works as well. + +@supported=en, ja +ja-Jpan-JP, en-AU >> ja # Match for ja-Jpan-JP (maximized already) + +# ja-JP matches ja on likely subtags, and it's listed first, thus it wins over the second preference en-GB. + +ja-JP, en-US >> ja # Match for ja-Jpan-JP (maximized already) + +# Check that if the preference is maximized already, it works as well. + +ja-Jpan-JP, en-US >> ja # Match for ja-Jpan-JP (maximized already) + +@favor=script +ja-Jpan-JP, en-AU >> ja +ja-JP, en-US >> ja +ja-Jpan-JP, en-US >> ja + +** test: testGetBestMatchForList-noMatchOnMaximized +# Regression test for http://b/5714572 . +# de maximizes to de-DE. Pick the exact match for the secondary language instead. +@supported=en, de, fr, ja +de-CH, fr >> de + +@favor=script +de-CH, fr >> de + +** test: testBestMatchForTraditionalChinese + +# Scenario: An application that only supports Simplified Chinese (and some other languages), +# but does not support Traditional Chinese. zh-Hans-CN could be replaced with zh-CN, zh, or +# zh-Hans, it wouldn't make much of a difference. + +# The script distance (simplified vs. traditional Han) is considered small enough +# to be an acceptable match. The regional difference is considered almost insignificant. + +@supported=fr, zh-Hans-CN, en-US +zh-TW >> zh-Hans-CN +zh-Hant >> zh-Hans-CN + +# For geopolitical reasons, you might want to avoid a zh-Hant -> zh-Hans match. +# In this case, if zh-TW, zh-HK or a tag starting with zh-Hant is requested, you can +# change your call to getBestMatch to include a 2nd language preference. +# "en" is a better match since its distance to "en-US" is closer than the distance +# from "zh-TW" to "zh-CN" (script distance). + +zh-TW, en >> en-US +zh-Hant-CN, en >> en-US +zh-Hans, en >> zh-Hans-CN + +@favor=script +zh-TW >> zh-Hans-CN +zh-Hant >> zh-Hans-CN +zh-TW, en >> en-US +zh-Hant-CN, en >> en-US +zh-Hans, en >> zh-Hans-CN + +** test: testUndefined +# When the undefined language doesn't match anything in the list, +# getBestMatch returns the default, as usual. + +@supported=it, fr +und >> it + +# When it *does* occur in the list, bestMatch returns it, as expected. +@supported=it, und +und >> und + +# The unusual part: max("und") = "en-Latn-US", and since matching is based on maximized +# tags, the undefined language would normally match English. But that would produce the +# counterintuitive results that getBestMatch("und", XLocaleMatcher("it,en")) would be "en", and +# getBestMatch("en", XLocaleMatcher("it,und")) would be "und". + +# To avoid that, we change the matcher's definitions of max +# so that max("und")="und". That produces the following, more desirable +# results: + +@supported=it, en +und >> it +@supported=it, und +en >> it + +@favor=script +@supported=it, fr +und >> it +@supported=it, und +und >> und +@supported=it, en +und >> it +@supported=it, und +en >> it + +** test: testGetBestMatch-regionDistance + +@supported=es-AR, es +es-MX >> es-AR +@supported=fr, en, en-GB +en-CA >> en-GB +@supported=de-AT, de-DE, de-CH +de >> de-DE + +@favor=script +@supported=es-AR, es +es-MX >> es-AR +@supported=fr, en, en-GB +en-CA >> en-GB +@supported=de-AT, de-DE, de-CH +de >> de-DE + +** test: testAsymmetry + +@supported=mul, nl +af >> nl # af => nl +@supported=mul, af +nl >> mul # but nl !=> af + +@favor=script +@supported=mul, nl +af >> nl +@supported=mul, af +nl >> mul + +** test: testGetBestMatchForList-matchOnMaximized2 + +# ja-JP matches ja on likely subtags, and it's listed first, thus it wins over the second preference en-GB. + +@supported=fr, en-GB, ja, es-ES, es-MX +ja-JP, en-GB >> ja # Match for ja-JP, with likely region subtag + +# Check that if the preference is maximized already, it works as well. + +ja-Jpan-JP, en-GB >> ja # Match for ja-Jpan-JP (maximized already) + +@favor=script +ja-JP, en-GB >> ja +ja-Jpan-JP, en-GB >> ja + +** test: testGetBestMatchForList-closeEnoughMatchOnMaximized + +@supported=en-GB, en, de, fr, ja +de-CH, fr >> de +en-US, ar, nl, de, ja >> en + +@favor=script +de-CH, fr >> de +en-US, ar, nl, de, ja >> en + +** test: testGetBestMatchForPortuguese + +# pt might be supported and not pt-PT + +# European user who prefers Spanish over Brazilian Portuguese as a fallback. + +@supported=pt-PT, pt-BR, es, es-419 +pt-PT, es, pt >> pt-PT +@supported=pt-PT, pt, es, es-419 +pt-PT, es, pt >> pt-PT # pt implicit + +# Brazilian user who prefers South American Spanish over European Portuguese as a fallback. +# The asymmetry between this case and above is because it's "pt-PT" that's missing between the +# matchers as "pt-BR" is a much more common language. + +@supported=pt-PT, pt-BR, es, es-419 +pt, es-419, pt-PT >> pt-BR +pt-PT, es, pt >> pt-PT +@supported=pt-PT, pt, es, es-419 +pt-PT, es, pt >> pt-PT +pt, es-419, pt-PT >> pt + +@supported=pt-BR, es, es-419 +pt, es-419, pt-PT >> pt-BR + +# Code that adds the user's country can get "pt-US" for a user's language. +# That should fall back to "pt-BR". + +@supported=pt-PT, pt-BR, es, es-419 +pt-US, pt-PT >> pt-BR +@supported=pt-PT, pt, es, es-419 +pt-US, pt-PT, pt >> pt # pt-BR implicit + +@favor=script +@supported=pt-PT, pt-BR, es, es-419 +pt-PT, es, pt >> pt-PT +@supported=pt-PT, pt, es, es-419 +pt-PT, es, pt >> pt-PT + +@supported=pt-PT, pt-BR, es, es-419 +pt, es-419, pt-PT >> pt-BR +pt-PT, es, pt >> pt-PT +@supported=pt-PT, pt, es, es-419 +pt-PT, es, pt >> pt-PT +pt, es-419, pt-PT >> pt + +@supported=pt-BR, es, es-419 +pt, es-419, pt-PT >> pt-BR + +@supported=pt-PT, pt-BR, es, es-419 +pt-US, pt-PT >> pt-BR +@supported=pt-PT, pt, es, es-419 +pt-US, pt-PT, pt >> pt + +** test: testVariantWithScriptMatch 1 and 2 + +@supported=fr, en, sv +en-GB >> en +@supported=en, sv +en-GB, sv >> en + +@favor=script +@supported=fr, en, sv +en-GB >> en +@supported=en, sv +en-GB, sv >> en + +** test: testLongLists + +@supported=en, sv +sv >> sv + +@supported=af, am, ar, az, be, bg, bn, bs, ca, cs, cy, da, de, el, en, en-GB, es, es-419, et, eu, fa, fi, fil, fr, ga, gl, gu, hi, hr, hu, hy, id, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, ne, nl, no, pa, pl, pt, pt-PT, ro, ru, si, sk, sl, sq, sr, sr-Latn, sv, sw, ta, te, th, tr, uk, ur, uz, vi, zh-CN, zh-TW, zu +sv >> sv + +@supported=af, af-NA, af-ZA, agq, agq-CM, ak, ak-GH, am, am-ET, ar, ar-001, ar-AE, ar-BH, ar-DJ, ar-DZ, ar-EG, ar-EH, ar-ER, ar-IL, ar-IQ, ar-JO, ar-KM, ar-KW, ar-LB, ar-LY, ar-MA, ar-MR, ar-OM, ar-PS, ar-QA, ar-SA, ar-SD, ar-SO, ar-SS, ar-SY, ar-TD, ar-TN, ar-YE, as, as-IN, asa, asa-TZ, ast, ast-ES, az, az-Cyrl, az-Cyrl-AZ, az-Latn, az-Latn-AZ, bas, bas-CM, be, be-BY, bem, bem-ZM, bez, bez-TZ, bg, bg-BG, bm, bm-ML, bn, bn-BD, bn-IN, bo, bo-CN, bo-IN, br, br-FR, brx, brx-IN, bs, bs-Cyrl, bs-Cyrl-BA, bs-Latn, bs-Latn-BA, ca, ca-AD, ca-ES, ca-ES-VALENCIA, ca-FR, ca-IT, ce, ce-RU, cgg, cgg-UG, chr, chr-US, ckb, ckb-IQ, ckb-IR, cs, cs-CZ, cu, cu-RU, cy, cy-GB, da, da-DK, da-GL, dav, dav-KE, de, de-AT, de-BE, de-CH, de-DE, de-LI, de-LU, dje, dje-NE, dsb, dsb-DE, dua, dua-CM, dyo, dyo-SN, dz, dz-BT, ebu, ebu-KE, ee, ee-GH, ee-TG, el, el-CY, el-GR, en, en-001, en-150, en-AG, en-AI, en-AS, en-AT, en-AU, en-BB, en-BE, en-BI, en-BM, en-BS, en-BW, en-BZ, en-CA, en-CC, en-CH, en-CK, en-CM, en-CX, en-CY, en-DE, en-DG, en-DK, en-DM, en-ER, en-FI, en-FJ, en-FK, en-FM, en-GB, en-GD, en-GG, en-GH, en-GI, en-GM, en-GU, en-GY, en-HK, en-IE, en-IL, en-IM, en-IN, en-IO, en-JE, en-JM, en-KE, en-KI, en-KN, en-KY, en-LC, en-LR, en-LS, en-MG, en-MH, en-MO, en-MP, en-MS, en-MT, en-MU, en-MW, en-MY, en-NA, en-NF, en-NG, en-NL, en-NR, en-NU, en-NZ, en-PG, en-PH, en-PK, en-PN, en-PR, en-PW, en-RW, en-SB, en-SC, en-SD, en-SE, en-SG, en-SH, en-SI, en-SL, en-SS, en-SX, en-SZ, en-TC, en-TK, en-TO, en-TT, en-TV, en-TZ, en-UG, en-UM, en-US, en-US-POSIX, en-VC, en-VG, en-VI, en-VU, en-WS, en-ZA, en-ZM, en-ZW, eo, eo-001, es, es-419, es-AR, es-BO, es-CL, es-CO, es-CR, es-CU, es-DO, es-EA, es-EC, es-ES, es-GQ, es-GT, es-HN, es-IC, es-MX, es-NI, es-PA, es-PE, es-PH, es-PR, es-PY, es-SV, es-US, es-UY, es-VE, et, et-EE, eu, eu-ES, ewo, ewo-CM, fa, fa-AF, fa-IR, ff, ff-CM, ff-GN, ff-MR, ff-SN, fi, fi-FI, fil, fil-PH, fo, fo-DK, fo-FO, fr, fr-BE, fr-BF, fr-BI, fr-BJ, fr-BL, fr-CA, fr-CD, fr-CF, fr-CG, fr-CH, fr-CI, fr-CM, fr-DJ, fr-DZ, fr-FR, fr-GA, fr-GF, fr-GN, fr-GP, fr-GQ, fr-HT, fr-KM, fr-LU, fr-MA, fr-MC, fr-MF, fr-MG, fr-ML, fr-MQ, fr-MR, fr-MU, fr-NC, fr-NE, fr-PF, fr-PM, fr-RE, fr-RW, fr-SC, fr-SN, fr-SY, fr-TD, fr-TG, fr-TN, fr-VU, fr-WF, fr-YT, fur, fur-IT, fy, fy-NL, ga, ga-IE, gd, gd-GB, gl, gl-ES, gsw, gsw-CH, gsw-FR, gsw-LI, gu, gu-IN, guz, guz-KE, gv, gv-IM, ha, ha-GH, ha-NE, ha-NG, haw, haw-US, he, he-IL, hi, hi-IN, hr, hr-BA, hr-HR, hsb, hsb-DE, hu, hu-HU, hy, hy-AM, id, id-ID, ig, ig-NG, ii, ii-CN, is, is-IS, it, it-CH, it-IT, it-SM, ja, ja-JP, jgo, jgo-CM, jmc, jmc-TZ, ka, ka-GE, kab, kab-DZ, kam, kam-KE, kde, kde-TZ, kea, kea-CV, khq, khq-ML, ki, ki-KE, kk, kk-KZ, kkj, kkj-CM, kl, kl-GL, kln, kln-KE, km, km-KH, kn, kn-IN, ko, ko-KP, ko-KR, kok, kok-IN, ks, ks-IN, ksb, ksb-TZ, ksf, ksf-CM, ksh, ksh-DE, kw, kw-GB, ky, ky-KG, lag, lag-TZ, lb, lb-LU, lg, lg-UG, lkt, lkt-US, ln, ln-AO, ln-CD, ln-CF, ln-CG, lo, lo-LA, lrc, lrc-IQ, lrc-IR, lt, lt-LT, lu, lu-CD, luo, luo-KE, luy, luy-KE, lv, lv-LV, mas, mas-KE, mas-TZ, mer, mer-KE, mfe, mfe-MU, mg, mg-MG, mgh, mgh-MZ, mgo, mgo-CM, mk, mk-MK, ml, ml-IN, mn, mn-MN, mr, mr-IN, ms, ms-BN, ms-MY, ms-SG, mt, mt-MT, mua, mua-CM, my, my-MM, mzn, mzn-IR, naq, naq-NA, nb, nb-NO, nb-SJ, nd, nd-ZW, ne, ne-IN, ne-NP, nl, nl-AW, nl-BE, nl-BQ, nl-CW, nl-NL, nl-SR, nl-SX, nmg, nmg-CM, nn, nn-NO, nnh, nnh-CM, nus, nus-SS, nyn, nyn-UG, om, om-ET, om-KE, or, or-IN, os, os-GE, os-RU, pa, pa-Arab, pa-Arab-PK, pa-Guru, pa-Guru-IN, pl, pl-PL, prg, prg-001, ps, ps-AF, pt, pt-AO, pt-BR, pt-CV, pt-GW, pt-MO, pt-MZ, pt-PT, pt-ST, pt-TL, qu, qu-BO, qu-EC, qu-PE, rm, rm-CH, rn, rn-BI, ro, ro-MD, ro-RO, rof, rof-TZ, root, ru, ru-BY, ru-KG, ru-KZ, ru-MD, ru-RU, ru-UA, rw, rw-RW, rwk, rwk-TZ, sah, sah-RU, saq, saq-KE, sbp, sbp-TZ, se, se-FI, se-NO, se-SE, seh, seh-MZ, ses, ses-ML, sg, sg-CF, shi, shi-Latn, shi-Latn-MA, shi-Tfng, shi-Tfng-MA, si, si-LK, sk, sk-SK, sl, sl-SI, smn, smn-FI, sn, sn-ZW, so, so-DJ, so-ET, so-KE, so-SO, sq, sq-AL, sq-MK, sq-XK, sr, sr-Cyrl, sr-Cyrl-BA, sr-Cyrl-ME, sr-Cyrl-RS, sr-Cyrl-XK, sr-Latn, sr-Latn-BA, sr-Latn-ME, sr-Latn-RS, sr-Latn-XK, sv, sv-AX, sv-FI, sv-SE, sw, sw-CD, sw-KE, sw-TZ, sw-UG, ta, ta-IN, ta-LK, ta-MY, ta-SG, te, te-IN, teo, teo-KE, teo-UG, th, th-TH, ti, ti-ER, ti-ET, tk, tk-TM, to, to-TO, tr, tr-CY, tr-TR, twq, twq-NE, tzm, tzm-MA, ug, ug-CN, uk, uk-UA, ur, ur-IN, ur-PK, uz, uz-Arab, uz-Arab-AF, uz-Cyrl, uz-Cyrl-UZ, uz-Latn, uz-Latn-UZ, vai, vai-Latn, vai-Latn-LR, vai-Vaii, vai-Vaii-LR, vi, vi-VN, vo, vo-001, vun, vun-TZ, wae, wae-CH, xog, xog-UG, yav, yav-CM, yi, yi-001, yo, yo-BJ, yo-NG, zgh, zgh-MA, zh, zh-Hans, zh-Hans-CN, zh-Hans-HK, zh-Hans-MO, zh-Hans-SG, zh-Hant, zh-Hant-HK, zh-Hant-MO, zh-Hant-TW, zu, zu-ZA +sv >> sv + +@favor=script +@supported=en, sv +sv >> sv + +@supported=af, am, ar, az, be, bg, bn, bs, ca, cs, cy, da, de, el, en, en-GB, es, es-419, et, eu, fa, fi, fil, fr, ga, gl, gu, hi, hr, hu, hy, id, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, ne, nl, no, pa, pl, pt, pt-PT, ro, ru, si, sk, sl, sq, sr, sr-Latn, sv, sw, ta, te, th, tr, uk, ur, uz, vi, zh-CN, zh-TW, zu +sv >> sv + +@supported=af, af-NA, af-ZA, agq, agq-CM, ak, ak-GH, am, am-ET, ar, ar-001, ar-AE, ar-BH, ar-DJ, ar-DZ, ar-EG, ar-EH, ar-ER, ar-IL, ar-IQ, ar-JO, ar-KM, ar-KW, ar-LB, ar-LY, ar-MA, ar-MR, ar-OM, ar-PS, ar-QA, ar-SA, ar-SD, ar-SO, ar-SS, ar-SY, ar-TD, ar-TN, ar-YE, as, as-IN, asa, asa-TZ, ast, ast-ES, az, az-Cyrl, az-Cyrl-AZ, az-Latn, az-Latn-AZ, bas, bas-CM, be, be-BY, bem, bem-ZM, bez, bez-TZ, bg, bg-BG, bm, bm-ML, bn, bn-BD, bn-IN, bo, bo-CN, bo-IN, br, br-FR, brx, brx-IN, bs, bs-Cyrl, bs-Cyrl-BA, bs-Latn, bs-Latn-BA, ca, ca-AD, ca-ES, ca-ES-VALENCIA, ca-FR, ca-IT, ce, ce-RU, cgg, cgg-UG, chr, chr-US, ckb, ckb-IQ, ckb-IR, cs, cs-CZ, cu, cu-RU, cy, cy-GB, da, da-DK, da-GL, dav, dav-KE, de, de-AT, de-BE, de-CH, de-DE, de-LI, de-LU, dje, dje-NE, dsb, dsb-DE, dua, dua-CM, dyo, dyo-SN, dz, dz-BT, ebu, ebu-KE, ee, ee-GH, ee-TG, el, el-CY, el-GR, en, en-001, en-150, en-AG, en-AI, en-AS, en-AT, en-AU, en-BB, en-BE, en-BI, en-BM, en-BS, en-BW, en-BZ, en-CA, en-CC, en-CH, en-CK, en-CM, en-CX, en-CY, en-DE, en-DG, en-DK, en-DM, en-ER, en-FI, en-FJ, en-FK, en-FM, en-GB, en-GD, en-GG, en-GH, en-GI, en-GM, en-GU, en-GY, en-HK, en-IE, en-IL, en-IM, en-IN, en-IO, en-JE, en-JM, en-KE, en-KI, en-KN, en-KY, en-LC, en-LR, en-LS, en-MG, en-MH, en-MO, en-MP, en-MS, en-MT, en-MU, en-MW, en-MY, en-NA, en-NF, en-NG, en-NL, en-NR, en-NU, en-NZ, en-PG, en-PH, en-PK, en-PN, en-PR, en-PW, en-RW, en-SB, en-SC, en-SD, en-SE, en-SG, en-SH, en-SI, en-SL, en-SS, en-SX, en-SZ, en-TC, en-TK, en-TO, en-TT, en-TV, en-TZ, en-UG, en-UM, en-US, en-US-POSIX, en-VC, en-VG, en-VI, en-VU, en-WS, en-ZA, en-ZM, en-ZW, eo, eo-001, es, es-419, es-AR, es-BO, es-CL, es-CO, es-CR, es-CU, es-DO, es-EA, es-EC, es-ES, es-GQ, es-GT, es-HN, es-IC, es-MX, es-NI, es-PA, es-PE, es-PH, es-PR, es-PY, es-SV, es-US, es-UY, es-VE, et, et-EE, eu, eu-ES, ewo, ewo-CM, fa, fa-AF, fa-IR, ff, ff-CM, ff-GN, ff-MR, ff-SN, fi, fi-FI, fil, fil-PH, fo, fo-DK, fo-FO, fr, fr-BE, fr-BF, fr-BI, fr-BJ, fr-BL, fr-CA, fr-CD, fr-CF, fr-CG, fr-CH, fr-CI, fr-CM, fr-DJ, fr-DZ, fr-FR, fr-GA, fr-GF, fr-GN, fr-GP, fr-GQ, fr-HT, fr-KM, fr-LU, fr-MA, fr-MC, fr-MF, fr-MG, fr-ML, fr-MQ, fr-MR, fr-MU, fr-NC, fr-NE, fr-PF, fr-PM, fr-RE, fr-RW, fr-SC, fr-SN, fr-SY, fr-TD, fr-TG, fr-TN, fr-VU, fr-WF, fr-YT, fur, fur-IT, fy, fy-NL, ga, ga-IE, gd, gd-GB, gl, gl-ES, gsw, gsw-CH, gsw-FR, gsw-LI, gu, gu-IN, guz, guz-KE, gv, gv-IM, ha, ha-GH, ha-NE, ha-NG, haw, haw-US, he, he-IL, hi, hi-IN, hr, hr-BA, hr-HR, hsb, hsb-DE, hu, hu-HU, hy, hy-AM, id, id-ID, ig, ig-NG, ii, ii-CN, is, is-IS, it, it-CH, it-IT, it-SM, ja, ja-JP, jgo, jgo-CM, jmc, jmc-TZ, ka, ka-GE, kab, kab-DZ, kam, kam-KE, kde, kde-TZ, kea, kea-CV, khq, khq-ML, ki, ki-KE, kk, kk-KZ, kkj, kkj-CM, kl, kl-GL, kln, kln-KE, km, km-KH, kn, kn-IN, ko, ko-KP, ko-KR, kok, kok-IN, ks, ks-IN, ksb, ksb-TZ, ksf, ksf-CM, ksh, ksh-DE, kw, kw-GB, ky, ky-KG, lag, lag-TZ, lb, lb-LU, lg, lg-UG, lkt, lkt-US, ln, ln-AO, ln-CD, ln-CF, ln-CG, lo, lo-LA, lrc, lrc-IQ, lrc-IR, lt, lt-LT, lu, lu-CD, luo, luo-KE, luy, luy-KE, lv, lv-LV, mas, mas-KE, mas-TZ, mer, mer-KE, mfe, mfe-MU, mg, mg-MG, mgh, mgh-MZ, mgo, mgo-CM, mk, mk-MK, ml, ml-IN, mn, mn-MN, mr, mr-IN, ms, ms-BN, ms-MY, ms-SG, mt, mt-MT, mua, mua-CM, my, my-MM, mzn, mzn-IR, naq, naq-NA, nb, nb-NO, nb-SJ, nd, nd-ZW, ne, ne-IN, ne-NP, nl, nl-AW, nl-BE, nl-BQ, nl-CW, nl-NL, nl-SR, nl-SX, nmg, nmg-CM, nn, nn-NO, nnh, nnh-CM, nus, nus-SS, nyn, nyn-UG, om, om-ET, om-KE, or, or-IN, os, os-GE, os-RU, pa, pa-Arab, pa-Arab-PK, pa-Guru, pa-Guru-IN, pl, pl-PL, prg, prg-001, ps, ps-AF, pt, pt-AO, pt-BR, pt-CV, pt-GW, pt-MO, pt-MZ, pt-PT, pt-ST, pt-TL, qu, qu-BO, qu-EC, qu-PE, rm, rm-CH, rn, rn-BI, ro, ro-MD, ro-RO, rof, rof-TZ, root, ru, ru-BY, ru-KG, ru-KZ, ru-MD, ru-RU, ru-UA, rw, rw-RW, rwk, rwk-TZ, sah, sah-RU, saq, saq-KE, sbp, sbp-TZ, se, se-FI, se-NO, se-SE, seh, seh-MZ, ses, ses-ML, sg, sg-CF, shi, shi-Latn, shi-Latn-MA, shi-Tfng, shi-Tfng-MA, si, si-LK, sk, sk-SK, sl, sl-SI, smn, smn-FI, sn, sn-ZW, so, so-DJ, so-ET, so-KE, so-SO, sq, sq-AL, sq-MK, sq-XK, sr, sr-Cyrl, sr-Cyrl-BA, sr-Cyrl-ME, sr-Cyrl-RS, sr-Cyrl-XK, sr-Latn, sr-Latn-BA, sr-Latn-ME, sr-Latn-RS, sr-Latn-XK, sv, sv-AX, sv-FI, sv-SE, sw, sw-CD, sw-KE, sw-TZ, sw-UG, ta, ta-IN, ta-LK, ta-MY, ta-SG, te, te-IN, teo, teo-KE, teo-UG, th, th-TH, ti, ti-ER, ti-ET, tk, tk-TM, to, to-TO, tr, tr-CY, tr-TR, twq, twq-NE, tzm, tzm-MA, ug, ug-CN, uk, uk-UA, ur, ur-IN, ur-PK, uz, uz-Arab, uz-Arab-AF, uz-Cyrl, uz-Cyrl-UZ, uz-Latn, uz-Latn-UZ, vai, vai-Latn, vai-Latn-LR, vai-Vaii, vai-Vaii-LR, vi, vi-VN, vo, vo-001, vun, vun-TZ, wae, wae-CH, xog, xog-UG, yav, yav-CM, yi, yi-001, yo, yo-BJ, yo-NG, zgh, zgh-MA, zh, zh-Hans, zh-Hans-CN, zh-Hans-HK, zh-Hans-MO, zh-Hans-SG, zh-Hant, zh-Hant-HK, zh-Hant-MO, zh-Hant-TW, zu, zu-ZA +sv >> sv + +** test: test8288 + +@supported=it, en +und >> it +und, en >> en + +# examples from +# http://unicode.org/repos/cldr/tags/latest/common/bcp47/ +# http://unicode.org/repos/cldr/tags/latest/common/validity/variant.xml + +@favor=script +und >> it +und, en >> en + +** test: testUnHack + +@supported=en-NZ, en-IT +en-US >> en-NZ + +@favor=script +en-US >> en-NZ + +** test: testEmptySupported => null +en >> null + +# testVariantsAndExtensions + +** test: tests the .combine() method + +@supported=und, fr +fr-BE-fonipa >> fr | | fr-BE-fonipa +@supported=und, fr-CA +fr-BE-fonipa >> fr-CA | | fr-BE-fonipa +@supported=und, fr-fonupa +fr-BE-fonipa >> fr-fonupa | | fr-BE-fonipa +@supported=und, no +nn-BE-fonipa >> no | | no-BE-fonipa +@supported=und, en-GB-u-sd-gbsct +en-fonipa-u-nu-Arab-ca-buddhist-t-m0-iso-i0-pinyin >> en-GB-u-sd-gbsct | | en-GB-fonipa-u-nu-Arab-ca-buddhist-t-m0-iso-i0-pinyin + +@supported=en-PSCRACK, de-PSCRACK, fr-PSCRACK, pt-PT-PSCRACK +fr-PSCRACK >> fr-PSCRACK +fr >> en-PSCRACK +de-CH >> en-PSCRACK + +@favor=script +@supported=und, fr +fr-BE-fonipa >> fr +@supported=und, fr-CA +fr-BE-fonipa >> fr-CA +@supported=und, fr-fonupa +fr-BE-fonipa >> fr-fonupa +@supported=und, no +nn-BE-fonipa >> no | | no-BE-fonipa +@supported=und, en-GB-u-sd-gbsct +en-fonipa-u-nu-Arab-ca-buddhist-t-m0-iso-i0-pinyin >> en-GB-u-sd-gbsct | | en-GB-fonipa-u-nu-Arab-ca-buddhist-t-m0-iso-i0-pinyin + +@supported=en-PSCRACK, de-PSCRACK, fr-PSCRACK, pt-PT-PSCRACK +fr-PSCRACK >> fr-PSCRACK +fr >> en-PSCRACK +de-CH >> en-PSCRACK + +** test: testClusters +# we favor es-419 over others in cluster. Clusters: es- {ES, MA, EA} {419, AR, MX} + +@supported=und, es, es-MA, es-MX, es-419 +es-AR >> es-419 +@supported=und, es-MA, es, es-419, es-MX +es-AR >> es-419 +@supported=und, es, es-MA, es-MX, es-419 +es-EA >> es +@supported=und, es-MA, es, es-419, es-MX +es-EA >> es + +# of course, fall back to within cluster + +@supported=und, es, es-MA, es-MX +es-AR >> es-MX +@supported=und, es-MA, es, es-MX +es-AR >> es-MX +@supported=und, es-MA, es-MX, es-419 +es-EA >> es-MA +@supported=und, es-MA, es-419, es-MX +es-EA >> es-MA + +# we favor es-GB over others in cluster. Clusters: en- {US, GU, VI} {GB, IN, ZA} + +@supported=und, en, en-GU, en-IN, en-GB +en-ZA >> en-GB +@supported=und, en-GU, en, en-GB, en-IN +en-ZA >> en-GB +@supported=und, en, en-GU, en-IN, en-GB +en-VI >> en +@supported=und, en-GU, en, en-GB, en-IN +en-VI >> en + +# of course, fall back to within cluster + +@supported=und, en, en-GU, en-IN +en-ZA >> en-IN +@supported=und, en-GU, en, en-IN +en-ZA >> en-IN +@supported=und, en-GU, en-IN, en-GB +en-VI >> en-GU +@supported=und, en-GU, en-GB, en-IN +en-VI >> en-GU + +@favor=script +@supported=und, es, es-MA, es-MX, es-419 +es-AR >> es-419 +@supported=und, es-MA, es, es-419, es-MX +es-AR >> es-419 +@supported=und, es, es-MA, es-MX, es-419 +es-EA >> es +@supported=und, es-MA, es, es-419, es-MX +es-EA >> es + +@supported=und, es, es-MA, es-MX +es-AR >> es-MX +@supported=und, es-MA, es, es-MX +es-AR >> es-MX +@supported=und, es-MA, es-MX, es-419 +es-EA >> es-MA +@supported=und, es-MA, es-419, es-MX +es-EA >> es-MA + +@supported=und, en, en-GU, en-IN, en-GB +en-ZA >> en-GB +@supported=und, en-GU, en, en-GB, en-IN +en-ZA >> en-GB +@supported=und, en, en-GU, en-IN, en-GB +en-VI >> en +@supported=und, en-GU, en, en-GB, en-IN +en-VI >> en + +@supported=und, en, en-GU, en-IN +en-ZA >> en-IN +@supported=und, en-GU, en, en-IN +en-ZA >> en-IN +@supported=und, en-GU, en-IN, en-GB +en-VI >> en-GU +@supported=und, en-GU, en-GB, en-IN +en-VI >> en-GU + +** test: testThreshold +@supported=50, und, fr-CA-fonupa +@threshold=60 +fr-BE-fonipa >> fr-CA-fonupa | | fr-BE-fonipa +@supported=und, fr-Cyrl-CA-fonupa +fr-BE-fonipa >> fr-Cyrl-CA-fonupa | | fr-Cyrl-BE-fonipa +@threshold=50 +fr-BE-fonipa >> und + +@favor=script +@supported=50, und, fr-CA-fonupa +@threshold= +fr-BE-fonipa >> fr-CA-fonupa | | fr-BE-fonipa +@supported=und, fr-Cyrl-CA-fonupa +fr-BE-fonipa >> und + +** test: testScriptFirst +@supported=ru, fr +zh, pl >> ru +zh-Cyrl, pl >> ru +@supported=hr, en-Cyrl +sr >> hr +@supported=da, ru, hr +sr >> da + +@favor=script +@supported=ru, fr +zh, pl >> fr +zh-Cyrl, pl >> ru +@supported=hr, en-Cyrl +sr >> en-Cyrl +@supported=da, ru, hr +sr >> ru + +## III + +** test: testBasicsWithDefault +@supported=en-GB, en +@default=fr +en-GB >> en-GB +en-US >> en +fr >> fr +ja >> fr + +@favor=script +en-GB >> en-GB +en-US >> en +fr >> en-GB +ja >> fr + +** test: testEmptyWithDefault +@default=en +fr >> en + +** test: testGetBestMatchForList_exactMatch +@supported=fr, en-GB, ja, es-ES, es-MX +ja, de >> ja + +** test: testGetBestMatchForList_simpleVariantMatch +# Intentionally avoiding a perfect-match or two candidates for variant matches. +@supported=fr, en-GB, ja, es-ES, es-MX +de, en-US >> en-GB +# Fall back. +de, zh >> fr + +** test: TestEuHack +@supported=en-NZ, en-IT +en-US >> en-NZ + +** test: TestBasics +@supported=fr, en-GB, en +en-GB >> en-GB +en-US >> en +fr-FR >> fr +ja-JP >> fr +# For a language that doesn't match anything, return the default. +zu >> en-GB +zxx >> fr + +@favor=script +en-GB >> en-GB +en-US >> en +fr-FR >> fr +ja-JP >> fr +zu >> en-GB +zxx >> en + +** test: TestExactMatch +@supported=fr, en-GB, ja, es-ES, es-MX +ja, de >> ja + +** test: TestSimpleVariantMatch +@supported=fr, en-GB, ja, es-ES, es-MX +de, en-US >> en-GB +de, zh >> fr + +** test: TestMatchOnMaximized +# ja-JP matches ja on likely subtags, and it's listed first, thus it wins +# over the secondary preference en-GB. +@supported=fr, en-GB, ja, es-ES, es-MX +ja-JP, en-GB >> ja +# Check that if the preference is maximized already, it works as well. +ja-Jpan-JP, en-GB >> ja +@supported=fr, zh-Hant, en +zh, en >> en + +@favor=script +zh, en >> en + +** test: TestCloseEnoughMatchOnMaximized +@supported=en-GB, en, de, fr, ja +de-CH, fr >> de +en-US, ar, nl, de, ja >> en + +** test: TestGetBestMatchForPortuguese +# 1. a supported set containing an explicit pt: {pt-PT, pt-BR, es, es-419} +# 2. a supported set containing an implicit pt: {pt-PT, pt, es, es-419} +# 3. a supported set containing no pt: {pt-BR, es, es-419} +# European user who prefers Spanish over Brazilian Portuguese as a fallback. +@supported=pt-PT, pt-BR, es, es-419 +pt-PT, es, pt >> pt-PT +@supported=pt-PT, pt, es, es-419 +pt-PT, es, pt >> pt-PT +@supported=pt-BR, es, es-419 +pt-PT, es, pt >> pt-BR + +# Brazilian user who prefers South American Spanish over European Portuguese +# as a fallback. The asymmetry between this case and above is because it's +# "pt-PT" that's missing between the matchers. +@supported=pt-PT, pt-BR, es, es-419 +pt, es-419, pt-PT >> pt-BR +@supported=pt-PT, pt, es, es-419 +pt, es-419, pt-PT >> pt +@supported=pt-BR, es, es-419 +pt, es-419, pt-PT >> pt-BR + +# Sometimes we get "pt-US" for a user's language (which CLDR doesn't +# recognize) but we deal with that as a synonym for "pt-BR". +@supported=pt-PT, pt-BR, es, es-419 +pt-US, pt-PT >> pt-BR +@supported=pt-PT, pt, es, es-419 +pt-US, pt-PT >> pt + +@favor=script +@supported=pt-BR, es, es-419 +pt-PT, es, pt >> pt-BR +@supported=pt-PT, pt, es, es-419 +pt-US, pt-PT >> pt + +** test: TestScriptAndRegion +@supported=en-GB, en +en-CA >> en-GB +# fr-CA is a "close enough" match to "fr" to be returned in favor of "en-GB" +@supported=fr, en-GB, en +fr-CA, en-CA >> fr +@supported=zh-Hant, zh-TW +zh-HK >> zh-Hant + +@favor=script +@supported=en-GB, en +en-CA >> en-GB +@supported=fr, en-GB, en +fr-CA, en-CA >> fr +@supported=zh-Hant, zh-TW +zh-HK >> zh-Hant + +** test: TestFallback +@supported=zh-CN, zh-TW, iw +zh-Hant >> zh-TW +zh >> zh-CN +zh-Hans-CN >> zh-CN +zh-Hant-HK >> zh-TW +he-IT >> iw + +** test: TestFallbackWithDefault +# Check that script fallbacks are handled right and that we don't have to +# fall back to the default. +@supported=zh-CN, zh-TW, iw +@default=fr +zh-Hant >> zh-TW +zh >> zh-CN +zh-Hans-CN >> zh-CN +zh-Hant-HK >> zh-TW +he-IT >> iw + +@favor=script +zh-Hant >> zh-TW +zh >> zh-CN +zh-Hans-CN >> zh-CN +zh-Hant-HK >> zh-TW +he-IT >> iw + +** test: TestSpecials +# Check that nearby languages are handled. +@supported=en, fil, ro, nn +tl >> fil +mo >> ro +nb >> nn +ja >> en # Make sure default works. + +** test: TestRegionalSpecials +# Verify that en-AU is closer to en-GB than to en (which is en-US). +@supported=en, en-GB, es-ES, es-419 +en-AU >> en-GB +# Following 2 cases test closer/smaller region difference. +es-MX >> es-419 +es-PT >> es-ES + +@favor=script +en-AU >> en-GB +es-MX >> es-419 +es-PT >> es-ES + +** test: TestEmpty +fr >> null + +** test: TestUndefined +# When the undefined language doesn't match anything in the list, +# return the default. +@supported=it, fr +und >> it +# When it *does* occur in the list, return it. +@supported=it, und +und >> und +# The unusual part: +# max("und") = "en-Latn-US", and since matching is based on +# maximized tags, the undefined language would normally match +# English. But that would produce the counterintuitive results +# that BestMatchFor("und", LanguageMatcher("it,en")) would be "en", +# and BestMatchFor("en", LanguageMatcher("it,und")) would be "und". + +# To avoid that, we change the matcher's definitions of max +# (AddLikelySubtagsWithDefaults) so that max("und")="und". That +# produces the following, more desirable results: +@supported=it, en +und >> it +@supported=it, und +en >> it + +** test: TestVariantWithScriptMatch +@supported=fr, en, sv +en-GB >> en +en-GB, sv >> en + +@favor=script +en-GB, sv >> en + +** test: Serbian +@supported=und, sr +sr-ME >> sr +@supported=und, sr-ME +sr >> sr-ME +@supported=und, sr-Latn +bs >> und +@supported=und, bs +sr-Latn >> und +@supported=und, sr +bs >> und +@supported=und, bs +sr >> und +@supported=und, sr-Latn +sr >> sr-Latn +@supported=und, sr +sr-Latn >> sr + +@favor=script +sr-ME >> sr +@supported=und, sr-ME +sr >> sr-ME +@supported=und, sr-Latn +bs >> sr-Latn +@supported=und, bs +sr-Latn >> bs +@supported=und, sr +bs >> und +@supported=und, bs +sr >> und +@supported=und, sr-Latn +sr >> sr-Latn +@supported=und, sr +sr-Latn >> sr + +** test: MatchGooglePrivateUseSubtag +@supported=fr, x-bork, en-Latn-US +x-piglatin >> fr +x-bork >> x-bork +@supported=fr, en-GB, x-bork, es-ES, es-419 +x-piglatin >> fr +x-bork >> x-bork + +@favor=script +@supported=fr, x-bork, en-Latn-US +x-piglatin >> x-bork +x-bork >> x-bork +@supported=fr, en-GB, x-bork, es-ES, es-419 +x-piglatin >> x-bork +x-bork >> x-bork + +** test: MatchGrandfatheredCode +@supported=fr, i-klingon, en-Latn-US +en-GB-oed >> en-Latn-US +i-klingon >> tlh + +@favor=script +en-GB-oed >> en-Latn-US +i-klingon >> tlh + +** test: MatchGooglePseudoLocale +# Google pseudo locales using variant subtags. +# (See below for the region code based pseudo locales.) +@supported=fr, en-PSACCENT, ar-PSBIDI, en-PSCRACK, zh-Hans-PSCRACK, pt-PT-PSCRACK, pt +de >> fr +en-US >> fr +en >> fr +ar-PSBIDI >> ar-PSBIDI +en-PSACCENT >> en-PSACCENT +en-PSCRACK >> en-PSCRACK +pt-BR >> pt +pt-PT-PSCRACK >> pt-PT-PSCRACK +zh-Hans-PSCRACK >> zh-Hans-PSCRACK + +@favor=script +de >> fr +en-US >> fr +en >> fr +ar-PSBIDI >> ar-PSBIDI +en-PSACCENT >> en-PSACCENT +en-PSCRACK >> en-PSCRACK +pt-BR >> pt +pt-PT-PSCRACK >> pt-PT-PSCRACK +zh-Hans-PSCRACK >> zh-Hans-PSCRACK + +** test: MatchGooglePseudoLocaleWithFallbacks +# Pseudo locales based on the fall back option (XA..XC region codes). +@supported=fr, en-XA, ar-XB, en-XC, zh-Hans-XC, pt +de >> fr +en-US >> fr +en >> fr +ar-XB >> ar-XB +en-XA >> en-XA +en-XC >> en-XC +pt-BR >> pt +zh-Hans-XC >> zh-Hans-XC + +@favor=script +de >> fr +en-US >> fr +en >> fr +ar-XB >> ar-XB +en-XA >> en-XA +en-XC >> en-XC +pt-BR >> pt +zh-Hans-XC >> zh-Hans-XC + +** test: DoNotMatchGooglePseudoLocale +@supported=fr, en-XA, ar-XB, en-PSACCENT, ar-PSBIDI, en-DE, pt, ar-SY, ar-PSCRACK +de >> fr +# We wouldn't want to return pseudo locales when there's a good match for an +# ordinary locale. +# Note: If LanguageMatcher was not aware of PSACCENT, it would consider the +# distance from "en" to "en-PSACCENT" smaller than to "en-DE" (the standard +# variant distance is smaller than a region distance). +en >> en-DE +ar-EG >> ar-SY +pt-BR >> pt +ar-XB >> ar-XB +ar-PSBIDI >> ar-XB # These are equivalent. +en-XA >> en-XA +en-PSACCENT >> en-XA # These are equivalent. +ar-PSCRACK >> ar-PSCRACK + +@favor=script +de >> en-DE +en >> en-DE +ar-EG >> ar-SY +pt-BR >> pt +ar-XB >> ar-XB +ar-PSBIDI >> ar-XB # These are equivalent. +en-XA >> en-XA +en-PSACCENT >> en-XA # These are equivalent. +ar-PSCRACK >> ar-PSCRACK + +** test: BestMatchForTraditionalChinese +# Scenario: An application that only supports Simplified Chinese (and some +# other languages), but does not support Traditional Chinese. zh-Hans-CN +# could be replaced with zh-CN, zh, or zh-Hans, it wouldn't make much of a +# difference. +# The script distance (simplified vs. traditional Han) is considered small +# enough to be an acceptable match. The regional difference is considered +# almost insignificant. +@supported=fr, zh-Hans-CN, en-US +zh-TW >> zh-Hans-CN +zh-Hant >> zh-Hans-CN + +# For geopolitical reasons, you might want to avoid a zh-Hant -> zh-Hans +# match. In this case, if zh-TW, zh-HK or a tag starting with zh-Hant is +# requested, you can change your call to getBestMatch to include a 2nd +# language preference. "en" is a better match since its distance to "en-US" +# is closer than the distance from "zh-TW" to "zh-CN" (script distance). +zh-TW, en >> en-US +zh-Hant-CN, en >> en-US +zh-Hans, en >> zh-Hans-CN + +** test: MaxBeforeEquals +# Compare maximized forms of earlier items before testing equality +# of later items. +@supported=en, fr-CA +en-US, fr-CA >> en + +@favor=script +en-US, fr-CA >> en + +** test: SiblingDefaultRegion +@supported=de-AT, de-DE, de-CH +de >> de-DE + +** test: ReturnDefaultInsteadOfNullForEmptyPriorityList +@default=und +de >> und + +** test: ReturnSpecifiedDefaultForNoMatch +@supported=de, en, fr +@default=und +hi >> und + +@favor=script +hi >> und + +** test: MatchedLanguageIgnoresDefault +@supported=de, en, fr +@default=und +fr >> fr + +@favor=script +fr >> fr + +## GenX + +** test: TwoSpanishes +@supported=es, es-MX +@default=und +es-001 >> es +und >> und +ca >> und +gl-ES >> es +es >> es +es-MX >> es-MX +es-002 >> es +es-003 >> es-MX +es-005 >> es-MX +es-019 >> es-MX +es-029 >> es-MX +es-419 >> es-MX +es-142 >> es +es-150 >> es +es-AD >> es +es-AR >> es-MX +es-BO >> es-MX +es-BZ >> es-MX +es-CA >> es-MX +es-CL >> es-MX +es-CO >> es-MX +es-CR >> es-MX +es-CU >> es-MX +es-DO >> es-MX +es-EC >> es-MX +es-ES >> es +es-GI >> es +es-GQ >> es +es-GT >> es-MX +es-HN >> es-MX +es-NI >> es-MX +es-PA >> es-MX +es-PE >> es-MX +es-PH >> es +es-PR >> es-MX +es-PY >> es-MX +es-SV >> es-MX +es-US >> es-MX +es-UY >> es-MX +es-VE >> es-MX + +@favor=script +es-001 >> es +und >> und +ca >> es +gl-ES >> es +es >> es +es-MX >> es-MX +es-002 >> es +es-003 >> es-MX +es-005 >> es-MX +es-019 >> es-MX +es-029 >> es-MX +es-419 >> es-MX +es-142 >> es +es-150 >> es +es-AD >> es +es-AR >> es-MX +es-BO >> es-MX +es-BZ >> es-MX +es-CA >> es-MX +es-CL >> es-MX +es-CO >> es-MX +es-CR >> es-MX +es-CU >> es-MX +es-DO >> es-MX +es-EC >> es-MX +es-ES >> es +es-GI >> es +es-GQ >> es +es-GT >> es-MX +es-HN >> es-MX +es-NI >> es-MX +es-PA >> es-MX +es-PE >> es-MX +es-PH >> es +es-PR >> es-MX +es-PY >> es-MX +es-SV >> es-MX +es-US >> es-MX +es-UY >> es-MX +es-VE >> es-MX + +** test: Three Spanishes +@supported=es, es-419, es-MX +@default=und +es-001 >> es +und >> und +ca >> und +gl-ES >> es +es >> es +es-419 >> es-419 +es-002 >> es +es-003 >> es-419 +es-005 >> es-419 +es-019 >> es-419 +es-029 >> es-419 +es-142 >> es +es-150 >> es +es-AD >> es +es-AR >> es-419 +es-BO >> es-419 +es-BZ >> es-419 +es-CA >> es-419 +es-CL >> es-419 +es-CO >> es-419 +es-CR >> es-419 +es-CU >> es-419 +es-DO >> es-419 +es-EC >> es-419 +es-ES >> es +es-GI >> es +es-GQ >> es +es-GT >> es-419 +es-HN >> es-419 +es-MX >> es-MX +es-NI >> es-419 +es-PA >> es-419 +es-PE >> es-419 +es-PH >> es +es-PR >> es-419 +es-PY >> es-419 +es-SV >> es-419 +es-US >> es-419 +es-UY >> es-419 +es-VE >> es-419 + +@favor=script +es-001 >> es +und >> und +ca >> es +gl-ES >> es +es >> es +es-419 >> es-419 +es-002 >> es +es-003 >> es-419 +es-005 >> es-419 +es-019 >> es-419 +es-029 >> es-419 +es-142 >> es +es-150 >> es +es-AD >> es +es-AR >> es-419 +es-BO >> es-419 +es-BZ >> es-419 +es-CA >> es-419 +es-CL >> es-419 +es-CO >> es-419 +es-CR >> es-419 +es-CU >> es-419 +es-DO >> es-419 +es-EC >> es-419 +es-ES >> es +es-GI >> es +es-GQ >> es +es-GT >> es-419 +es-HN >> es-419 +es-MX >> es-MX +es-NI >> es-419 +es-PA >> es-419 +es-PE >> es-419 +es-PH >> es +es-PR >> es-419 +es-PY >> es-419 +es-SV >> es-419 +es-US >> es-419 +es-UY >> es-419 +es-VE >> es-419 + +** test: Englishes +@supported=en-GB, en-US +@default=und +und >> und +ja >> und +fr-CA >> und + +# Great Britain fallback +en-AU >> en-GB +en-BZ >> en-GB +en-CA >> en-GB +en-IN >> en-GB +en-IE >> en-GB +en-JM >> en-GB +en-NZ >> en-GB +en-PK >> en-GB +en-TT >> en-GB +en-ZA >> en-GB + +# United States fallback +en-US >> en-US +en >> en-US + +@favor=script +und >> und +ja >> und +fr-CA >> en-GB +en-AU >> en-GB +en-BZ >> en-GB +en-CA >> en-GB +en-IN >> en-GB +en-IE >> en-GB +en-JM >> en-GB +en-NZ >> en-GB +en-PK >> en-GB +en-TT >> en-GB +en-ZA >> en-GB +en-US >> en-US +en >> en-US + +** test: TestFallback +# manyEnMatcher +@supported=en-GB, en-US, en, en-AU +@default=und +und >> und +ja >> und +fr-CA >> und + +# nonUsMatcher +fr >> und + +# onlyAuMatcher +@supported=en-AU, ja, ca +fr >> und + +# noEnMatcher +@supported=pl, ja, ca +fr >> und + +@favor=script +@supported=en-GB, en-US, en, en-AU +und >> und +ja >> und +fr-CA >> en-GB +fr >> en-GB +@supported=en-AU, ja, ca +fr >> en-AU +@supported=pl, ja, ca +fr >> pl + +## Go + +** test: basics +@supported=fr, en-GB, en +en-GB >> en-GB +en-US >> en +fr-FR >> fr +ja-JP >> fr + +** test: script fallbacks +@supported=zh-CN, zh-TW, iw +zh-Hant >> zh-TW +zh >> zh-CN +zh-Hans-CN >> zh-CN +zh-Hant-HK >> zh-TW +@default=iw +he-IT >> iw + +@favor=script +he-IT >> iw + +** test: language-specific script fallbacks 1 +@supported=en, sr, nl +sr-Latn >> sr +sh >> en +hr >> en +bs >> en +nl-Cyrl >> en # Mark: Expected value should be en not sr. Script difference exceeds threshold, so can't be nl + +@favor=script +sr-Latn >> sr +hr >> en +bs >> en +nl-Cyrl >> sr + +** test: language-specific script fallbacks 2 +@supported=en, sr-Latn +sr >> sr-Latn +sr-Cyrl >> sr-Latn +@default=und +hr >> und + +@favor=script +@default= +sr >> sr-Latn +sr-Cyrl >> sr-Latn +@default=und +hr >> en + +** test: don't match hr to sr-Latn +@supported=en, sr-Latn +hr >> en + +@favor=script +hr >> en + +** test: both deprecated and not +@supported=fil, tl, iw, he +he-IT >> iw +he >> iw +iw >> iw +fil-IT >> fil +fil >> fil +tl >> fil + +@favor=script +he-IT >> iw +he >> iw +iw >> iw +fil-IT >> fil +fil >> fil +tl >> fil + +** test: nearby languages: Nynorsk to Bokmål +@supported=en, nb +nn >> nb + +@favor=script +nn >> nb + +** test: nearby languages: Danish does not match nn +@supported=en, nn +da >> en + +@favor=script +da >> en + +** test: nearby languages: Danish matches no +@supported=en, no +da >> no + +@favor=script +da >> no + +** test: nearby languages: Danish matches nb +@supported=en, nb +da >> nb + +** test: prefer matching languages over language variants. +@supported=nn, en-GB +no, en-US >> nn +nb, en-US >> nn + +@favor=script +no, en-US >> nn +nb, en-US >> nn + +** test: deprecated version is closer than same language with other differences +@supported=nl, he, en-GB +iw, en-US >> he + +@favor=script +iw, en-US >> he + +** test: macro equivalent is closer than same language with other differences +@supported=nl, zh, en-GB, no +cmn, en-US >> zh +nb, en-US >> no + +@favor=script +cmn, en-US >> zh +nb, en-US >> no + +** test: legacy equivalent is closer than same language with other differences +@supported=nl, fil, en-GB +tl, en-US >> fil + +@favor=script +tl, en-US >> fil + +** test: distinguish near equivalents +@supported=en, ro, mo, ro-MD +ro >> ro +mo >> ro # ro=mo for the locale matcher +ro-MD >> ro-MD + +@favor=script +ro >> ro +mo >> ro # ro=mo for the locale matcher +ro-MD >> ro-MD + +** test: maximization of legacy +@supported=sr-Cyrl, sr-Latn, ro, ro-MD +sh >> sr-Latn +mo >> ro + +@favor=script +sh >> sr-Latn +mo >> ro + +** test: empty +fr >> null +en >> null + +** test: private use subtags +@supported=fr, en-GB, x-bork, es-ES, es-419 +x-piglatin >> fr +x-bork >> x-bork + +** test: grandfathered codes +@supported=fr, i-klingon, en-Latn-US +en-GB-oed >> en-Latn-US +i-klingon >> tlh + + +** test: simple variant match +@supported=fr, en-GB, ja, es-ES, es-MX +de, en-US >> en-GB +de, zh >> fr + +** test: best match for traditional Chinese +@supported=fr, zh-Hans-CN, en-US +zh-TW >> zh-Hans-CN +zh-Hant >> zh-Hans-CN +zh-TW, en >> en-US +zh-Hant-CN, en >> en-US +zh-Hans, en >> zh-Hans-CN + +** test: return first among likely-subtags equivalent locales +# Was: more specific script should win in case regions are identical +# with some different results. +@supported=af, af-Latn, af-Arab +af >> af +af-ZA >> af +af-Latn-ZA >> af +af-Latn >> af + +@favor=script +af >> af +af-ZA >> af +af-Latn-ZA >> af +af-Latn >> af + +# Was: more specific region should win +# with some different results. +@supported=nl, nl-NL, nl-BE +@favor= +nl >> nl +nl-Latn >> nl +nl-Latn-NL >> nl +nl-NL >> nl + +@favor=script +nl >> nl +nl-Latn >> nl +nl-Latn-NL >> nl +nl-NL >> nl + +# Was: more specific region wins over more specific script +# with some different results. +@supported=nl, nl-Latn, nl-NL, nl-BE +@favor= +nl >> nl +nl-Latn >> nl +nl-NL >> nl +nl-Latn-NL >> nl + +@favor=script +nl >> nl +nl-Latn >> nl +nl-NL >> nl +nl-Latn-NL >> nl + +** test: region may replace matched if matched is enclosing +@supported=es-419, es +@default=es-MX +es-MX >> es-419 +@default= +es-SG >> es + +@favor=script +@default=es-MX +es-MX >> es-419 +@default= +es-SG >> es + +** test: region distance Portuguese +@supported=pt, pt-PT +pt-ES >> pt-PT + +@favor=script +pt-ES >> pt-PT + +** test: if no preferred locale specified, pick top language, not regional +@supported=en, fr, fr-CA, fr-CH +fr-US >> fr + +@favor=script +fr-US >> fr + +** test: region distance German +@supported=de-AT, de-DE, de-CH +de >> de-DE + +** test: en-AU is closer to en-GB than to en (which is en-US) +@supported=en, en-GB, es-ES, es-419 +en-AU >> en-GB +@default=es-MX +es-MX >> es-419 +@default= +es-PT >> es-ES + +@favor=script +en-AU >> en-GB +es-MX >> es-419 +@default= +es-PT >> es-ES + +** test: undefined +@supported=it, fr +und >> it + +** test: und does not match en +@supported=it, en +und >> it + +** test: undefined in priority list +@supported=it, und +und >> und +en >> it + +** test: undefined +@supported=it, fr, zh +und-FR >> fr +und-CN >> zh +und-Hans >> zh +und-Hant >> zh +und-Latn >> it + +@favor=script +und-FR >> fr +und-CN >> zh +und-Hans >> zh +und-Hant >> zh +und-Latn >> it + +** test: match on maximized tag +@supported=fr, en-GB, ja, es-ES, es-MX +ja-JP, en-GB >> ja +ja-Jpan-JP, en-GB >> ja + +** test: pick best maximized tag +@supported=ja, ja-Jpan-US, ja-JP, en, ru +ja-Jpan, ru >> ja +ja-JP, ru >> ja +ja-US, ru >> ja-Jpan-US + +@favor=script +ja-Jpan, ru >> ja +ja-JP, ru >> ja +ja-US, ru >> ja-Jpan-US + +** test: termination: pick best maximized match +@supported=ja, ja-Jpan, ja-JP, en, ru +ja-Jpan-JP, ru >> ja +ja-Jpan, ru >> ja + +@favor=script +ja-Jpan-JP, ru >> ja +ja-Jpan, ru >> ja + +** test: same language over exact, but distinguish when user is explicit +@supported=fr, en-GB, ja, es-ES, es-MX +ja, de >> ja +@supported=en, de, fr, ja +de-CH, fr >> de +@supported=en-GB, nl +en, nl >> en-GB +en, nl, en-GB >> en-GB + +@favor=script +@supported=fr, en-GB, ja, es-ES, es-MX +ja, de >> ja +@supported=en, de, fr, ja +de-CH, fr >> de +@supported=en-GB, nl +en, nl >> en-GB +en, nl, en-GB >> en-GB + +** test: parent relation preserved +@supported=en, en-US, en-GB, es, es-419, pt, pt-BR, pt-PT, zh, zh-Hant, zh-Hant-HK +en-150 >> en-GB +en-AU >> en-GB +en-BE >> en-GB +en-GG >> en-GB +en-GI >> en-GB +en-HK >> en-GB +en-IE >> en-GB +en-IM >> en-GB +en-IN >> en-GB +en-JE >> en-GB +en-MT >> en-GB +en-NZ >> en-GB +en-PK >> en-GB +en-SG >> en-GB +en-DE >> en-GB +@default=es-AR +es-AR >> es-419 +@default=es-BO +es-BO >> es-419 +@default=es-CL +es-CL >> es-419 +@default=es-CO +es-CO >> es-419 +@default=es-CR +es-CR >> es-419 +@default=es-CU +es-CU >> es-419 +@default=es-DO +es-DO >> es-419 +@default=es-EC +es-EC >> es-419 +@default=es-GT +es-GT >> es-419 +@default=es-HN +es-HN >> es-419 +@default=es-MX +es-MX >> es-419 +@default=es-NI +es-NI >> es-419 +@default=es-PA +es-PA >> es-419 +@default=es-PE +es-PE >> es-419 +@default=es-PR +es-PR >> es-419 +@default= +es-PT >> es +@default=es-PY +es-PY >> es-419 +@default=es-SV +es-SV >> es-419 +@default= +es-US >> es-419 +@default=es-UY +es-UY >> es-419 +@default=es-VE +es-VE >> es-419 +@default= +pt-AO >> pt-PT +pt-CV >> pt-PT +pt-GW >> pt-PT +pt-MO >> pt-PT +pt-MZ >> pt-PT +pt-ST >> pt-PT +pt-TL >> pt-PT + +@favor=script +en-150 >> en-GB +en-AU >> en-GB +en-BE >> en-GB +en-GG >> en-GB +en-GI >> en-GB +en-HK >> en-GB +en-IE >> en-GB +en-IM >> en-GB +en-IN >> en-GB +en-JE >> en-GB +en-MT >> en-GB +en-NZ >> en-GB +en-PK >> en-GB +en-SG >> en-GB +en-DE >> en-GB +@default=es-AR +es-AR >> es-419 +@default=es-BO +es-BO >> es-419 +@default=es-CL +es-CL >> es-419 +@default=es-CO +es-CO >> es-419 +@default=es-CR +es-CR >> es-419 +@default=es-CU +es-CU >> es-419 +@default=es-DO +es-DO >> es-419 +@default=es-EC +es-EC >> es-419 +@default=es-GT +es-GT >> es-419 +@default=es-HN +es-HN >> es-419 +@default=es-MX +es-MX >> es-419 +@default=es-NI +es-NI >> es-419 +@default=es-PA +es-PA >> es-419 +@default=es-PE +es-PE >> es-419 +@default=es-PR +es-PR >> es-419 +@default= +es-PT >> es +@default=es-PY +es-PY >> es-419 +@default=es-SV +es-SV >> es-419 +@default= +es-US >> es-419 +@default=es-UY +es-UY >> es-419 +@default=es-VE +es-VE >> es-419 +@default= +pt-AO >> pt-PT +pt-CV >> pt-PT +pt-GW >> pt-PT +pt-MO >> pt-PT +pt-MZ >> pt-PT +pt-ST >> pt-PT +pt-TL >> pt-PT + +** test: preserve extensions +@supported=en, de, sl-NEDIS +@default=de-u-co-phonebk +de-FR-u-co-phonebk >> de +@default=sl-NEDIS-u-cu-eur +sl-NEDIS-u-cu-eur >> sl-NEDIS +sl-u-cu-eur >> sl-NEDIS +sl-HR-NEDIS-u-cu-eur >> sl-NEDIS +@default=de-t-m0-iso-i0-pinyin +de-t-m0-iso-i0-pinyin >> de + +@favor=script +@default=de-u-co-phonebk +de-FR-u-co-phonebk >> de +@default=sl-NEDIS-u-cu-eur +sl-NEDIS-u-cu-eur >> sl-NEDIS +sl-u-cu-eur >> sl-NEDIS +sl-HR-NEDIS-u-cu-eur >> sl-NEDIS +@default=de-t-m0-iso-i0-pinyin +de-t-m0-iso-i0-pinyin >> de + +## ULS + +** test: testEmptyUserLanguagesGetsEmpty_getBestMatches +@supported=de + >> de + +** test: testNoStrongMatchGetsEmpty_getBestMatches +@supported=de +fr >> de + +@favor=script +fr >> de + +** test: testLooseMatchForGeneral_getBestMatches +@supported=es-419 +es-MX >> es-419 + +@favor=script +es-MX >> es-419 + +** test: testLooseMatchForEnglish_getBestMatches +@supported=en, en-GB +en-CA >> en-GB + +@favor=script +en-CA >> en-GB + +** test: testLooseMatchForChinese_getBestMatches +@supported=zh +zh-TW >> zh + +@favor=script +zh-TW >> zh + +## Geo + +** test: testGetBestMatchWithMinMatchScore +@supported=fr-FR, fr, fr-CA, en +@default=und +fr >> fr-FR # First likely-subtags equivalent match is chosen. +@supported=en, fr, fr-CA +fr-FR >> fr # Parent match is chosen. +@supported=en, fr-CA +fr-FR >> fr-CA # Sibling match is chosen. +@supported=fr-CA, fr-FR +fr >> fr-FR # Inferred region match is chosen. +fr-SN >> fr-CA +@supported=en, fr-FR +fr >> fr-FR # Child match is chosen. +@supported=de, en, it +fr >> und +@supported=iw, en +iw-Latn >> und +@supported=iw, no +ru >> und +@supported=iw-Latn, iw-Cyrl, iw +ru >> und +@supported=iw, iw-Latn +ru >> und +en >> und +@supported=en, uk +ru >> und +@supported=zh-TW, en +zh-CN >> zh-TW +@supported=ja +ru >> und + +@favor=script +@supported=fr-FR, fr, fr-CA, en +fr >> fr-FR +@supported=en, fr, fr-CA +fr-FR >> fr +@supported=en, fr-CA +fr-FR >> fr-CA +@supported=fr-CA, fr-FR +fr >> fr-FR +fr-SN >> fr-CA +@supported=en, fr-FR +fr >> fr-FR +@supported=de, en, it +fr >> en +@supported=iw, en +iw-Latn >> en +@supported=iw, no +ru >> und +@supported=iw-Latn, iw-Cyrl, iw +ru >> iw-Cyrl +@supported=iw, iw-Latn +ru >> und +en >> iw-Latn +@supported=en, uk +ru >> uk +@supported=zh-TW, en +zh-CN >> zh-TW +@supported=ja +ru >> und diff -Nru icu-64.2/source/test/testdata/numberformattestspecification.txt icu-65.1/source/test/testdata/numberformattestspecification.txt --- icu-64.2/source/test/testdata/numberformattestspecification.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/numberformattestspecification.txt 2019-10-03 11:16:41.000000000 +0000 @@ -10,7 +10,6 @@ // per line. // // Field names: -// H = ICU4J 58 (archive) // J = ICU4J (current) // K = JDK (ignored if not OpenJDK 1.8) // C = ICU4C (current) @@ -25,7 +24,7 @@ set pattern +0;-# begin format output breaks -6 \u061C+\u0666 HK +6 \u061C+\u0666 K -6 \u061C-\u0666 K test basic patterns @@ -188,7 +187,7 @@ // JDK gives 12,3001E3 ##0.000#E0 12300.1 12,30E3 K ##0.000#E0 12301 12,301E3 -0.05E0 12301.2 1,25E4 HK +0.05E0 12301.2 1,25E4 K ##0.000#E0 0.17 170,0E-3 // JDK doesn't support significant digits in exponents @@@E0 6.235 6,24E0 K @@ -270,17 +269,16 @@ ####,##0$*x;n#'*' -1234 n1\u202f234*xx K *y%4.2###### 4.33 yyyy%432,6 K // In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4) -\u00a4\u00a4 **####0.00 433.0 EUR *433,00 HK -// In H ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4) +\u00a4\u00a4 **####0.00 433.0 EUR *433,00 K // P fails this one because the test code bypasses CurrencyUsage -\u00a4\u00a4 **#######0 433.0 EUR *433,00 HKP +\u00a4\u00a4 **#######0 433.0 EUR *433,00 KP test padding and currencies begin locale currency pattern format output breaks // In J, JPY is considered 2 char (2 * 0xa4) even though padding is done // after prefix. In C this test works. -fr JPY \u00a4\u00a4 **#######0 433.22 JPY ****433 HK +fr JPY \u00a4\u00a4 **#######0 433.22 JPY ****433 K // JDK doesn't correct rounding for currency, shows USD (433 en USD \u00a4\u00a4 **#######0;\u00a4\u00a4 (#) -433.22 USD (433.22) K @@ -310,9 +308,7 @@ set minGroupingDigits 2 begin format output breaks -// min grouping digits not supported in any existing implementation -// but could be easily added to the new DecimalFormat C code. -1000 1000 HK +1000 1000 K 10000 10,000 100000 100,000 1000000 1,000,000 @@ -351,7 +347,7 @@ // JDK gives E0 instead of allowing for unlimited precision 0 0 0 0 2.99792458E8 K // J gives 2.9979E8 -0 1 0 5 2.99792E8 HK +0 1 0 5 2.99792E8 K // JDK gives 300E6 0 3 0 0 299.792458E6 K // JDK gives 299.8E6 (maybe maxInt + maxFrac instead of minInt + maxFrac)? @@ -368,7 +364,7 @@ // JDK gives E0 0 0 1 0 2.99792458E8 K // J gives 2.998E8 -0 0 0 4 .29979E9 HK +0 0 0 4 .29979E9 K // According to the spec, if maxInt>minInt and minInt>1, then set // Context: #13289 2 8 1 6 2.9979246E8 K @@ -423,7 +419,7 @@ format maxIntegerDigits output breaks 123 1 3 // C obeys maxIntegerDigits and prints after the decimal place -0 0 .0 HKP +0 0 .0 KP // CJP ignore max integer if it is less than zero and prints "123" 123 -2147483648 0 CJP 12345 1 5 @@ -516,7 +512,7 @@ output grouping grouping2 minGroupingDigits breaks 1,23,45,6789 4 2 2 K 123,456789 6 6 3 -123456789 6 6 4 HK +123456789 6 6 4 K test multiplier setters set locale en_US @@ -524,10 +520,10 @@ format multiplier output breaks 23 -12 -276 23 -1 -23 -// H (ICU4J 58) and J (current ICU4J) throw exception on zero multiplier. +// J (current ICU4J) throws exception on zero multiplier. // ICU4C prints 23. // Q multiplies by zero and prints 0. -23 0 0 CHJ +23 0 0 CJ 23 1 23 23 12 276 -23 12 -276 @@ -599,12 +595,12 @@ currency currencyUsage toPattern breaks // These work in J, but it prepends an extra hash sign to the pattern. // K does not support this feature. -USD standard 0.00 HK -CHF standard 0.00 HK -CZK standard 0.00 HK -USD cash 0.00 HK -CHF cash 0.05 HK -CZK cash 0 HK +USD standard 0.00 K +CHF standard 0.00 K +CZK standard 0.00 K +USD cash 0.00 K +CHF cash 0.05 K +CZK cash 0 K test currency rounding set locale en @@ -688,7 +684,7 @@ -Inf (\u221e) K // J does not print the affixes // K prints \uFFFD -NaN [NaN] HK +NaN [NaN] K test nan and infinity with multiplication set locale en @@ -711,10 +707,10 @@ Inf afterSuffix $$$\u221e$ K // J does not print the affixes // K prints \uFFFD -NaN beforePrefix $$$NaN$ HK -NaN afterPrefix $$$ NaN$ HK -NaN beforeSuffix $$$NaN $ HK -NaN afterSuffix $$$NaN$ HK +NaN beforePrefix $$$NaN$ K +NaN afterPrefix $$$ NaN$ K +NaN beforeSuffix $$$NaN $ K +NaN afterSuffix $$$NaN$ K test apply formerly localized patterns begin @@ -742,8 +738,7 @@ pattern toPattern breaks // All of the C and S failures in this section are because of functionally equivalent patterns // JDK doesn't support any patterns with padding or both negative prefix and suffix -// Breaks ICU4J See ticket 11671 -**0,000 **0,000 HK +**0,000 **0,000 K **##0,000 **##0,000 K **###0,000 **###0,000 K **####0,000 **#,##0,000 CJKP @@ -783,25 +778,24 @@ +5347,,, 5347 +5347,,,d8 5347 (5,347.25) -5347.25 -// H requires prefix and suffix for lenient parsing, but C doesn't -5,347.25 5347.25 HK -(5,347.25 -5347.25 H +5,347.25 5347.25 K +(5,347.25 -5347.25 // S is successful at parsing this as -5347.25 in lenient mode --5,347.25 -5347.25 HK +-5,347.25 -5347.25 K +3.52E4 35200 (34.8E-3) -0.0348 // JDK stops parsing at the spaces. JDK doesn't see space as a grouping separator (34 25E-1) -342.5 K (34,,25E-1) -342.5 // Trailing grouping separators are not OK. -// H fails; C/J/P stop at the offending separator. +// C/J/P stop at the offending separator. (34,,25,E-1) fail CJKP -(34,,25,E-1) -3425 HK -(34 25 E-1) -342.5 HK -(34,,25 E-1) -342.5 HK +(34,,25,E-1) -3425 K +(34 25 E-1) -342.5 K +(34,,25 E-1) -342.5 K // Spaces are not allowed after exponent symbol -// C parses up to the E but H bails -(34 25E -1) -3425 HK +// C parses up to the E +(34 25E -1) -3425 K +3.52EE4 3.52 +1,234,567.8901 1234567.8901 +1,23,4567.8901 1234567.8901 @@ -818,29 +812,21 @@ + 79 79 K +,79,,20,33 792033 +7920d3 7920 -// Whitespace immediately after prefix doesn't count as digit separator -// in C but is does in H -+ ,79,,20,33 792033 HK +// Whitespace immediately after prefix doesn't count as digit separator in C ++ ,79,,20,33 792033 K ( 19 45) -1945 K // C allows trailing separators when there is a prefix and suffix. -// H allows trailing separators only when there is just a prefix. -// In this case, H just bails -( 19 45 ) -1945 HK +( 19 45 ) -1945 K (,,19,45) -1945 -// C parses to the space, but H bails -(,,19 45) -19 H -// H bails b/c comma different separator than space. C doesn't treat leading spaces -// as a separator. -( 19,45) -1945 HK -// H bails. Doesn't allow trailing separators when there is prefix and suffix. -(,,19,45,) -1945 H -// H bails on next 4 because H doesn't allow letters inside prefix and suffix. +// C parses to the spaces +(,,19 45) -19 +( 19,45) -1945 K +(,,19,45,) -1945 // C will parse up to the letter. -(,,19,45,d1) -1945 H -(,,19,45d1) -1945 H -( 19 45 d1) -1945 HK -( 19 45d1) -1945 HK -// H does allow trailing separator before a decimal point +(,,19,45,d1) -1945 +(,,19,45d1) -1945 +( 19 45 d1) -1945 K +( 19 45d1) -1945 K (19,45,.25) -1945.25 // 2nd decimal points are ignored +4.12.926 4.12 @@ -851,18 +837,16 @@ begin parse output breaks // J and K just bail. -3426 3426 HK +3426 3426 K 3426+ 3426 // J bails; K sees -34 -34 d1+ 34 HK +34 d1+ 34 K // JDK sees this as -1234 for some reason -// H bails b/c of trailing separators -1,234,,,+ 1234 HK +1,234,,,+ 1234 K 1,234- -1234 -// H, C, and P bail because of trailing separators -1,234,- -1234 CHJP -// J bails here too -1234 - -1234 H +// C and P bail because of trailing separators +1,234,- -1234 CJP +1234 - -1234 @@ -888,8 +872,7 @@ (3425E-1) -342.5 // Strict doesn't allow separators in sci notation. (63,425) -63425 -// H does not allow grouping separators in scientific notation. -(63,425E-1) -6342.5 H +(63,425E-1) -6342.5 // Both prefix and suffix needed for strict. // JDK accepts this and parses as -342.5 (3425E-1 fail K @@ -913,8 +896,7 @@ +1,234.5 1234.5 // Comma after decimal means parse to a comma +1,23,456.78,9 123456.78 -// H fails upon seeing the second decimal point -+1,23,456.78.9 123456.78 H ++1,23,456.78.9 123456.78 +79 79 +79 79 + 79 fail @@ -952,8 +934,7 @@ begin parse output breaks 35 35 -// S accepts leading plus signs -+35 35 HK ++35 35 K -35 -35 2.63 2 -39.99 -39 @@ -967,8 +948,8 @@ 0 5e2 500 K 0 5.3E2 530 // See ticket 11725 -1 5e2 5 H -1 5.3E2 5.3 HK +1 5e2 5 +1 5.3E2 5.3 K test parse currency fail set pattern 0 @@ -1006,8 +987,8 @@ parse output breaks // A non-greedy parse is required to pass these cases. // All of the implementations being tested are greedy. -6549K 654 CHJKP -6549N -654 CHJKP +6549K 654 CJKP +6549N -654 CJKP test really strange prefix set locale en @@ -1076,41 +1057,41 @@ $53.45 53.45 USD C 53.45 USD 53.45 USD 53.45 GBP 53.45 GBP -USD 53.45 53.45 USD H -53.45USD 53.45 USD H +USD 53.45 53.45 USD +53.45USD 53.45 USD USD53.45 53.45 USD (7.92) USD -7.92 USD (7.92) GBP -7.92 GBP (7.926) USD -7.926 USD -(7.926 USD) -7.926 USD H -(USD 7.926) -7.926 USD H -USD (7.926) -7.926 USD H -USD (7.92) -7.92 USD H -(7.92)USD -7.92 USD H -USD(7.92) -7.92 USD H +(7.926 USD) -7.926 USD +(USD 7.926) -7.926 USD +USD (7.926) -7.926 USD +USD (7.92) -7.92 USD +(7.92)USD -7.92 USD +USD(7.92) -7.92 USD (8) USD -8 USD -8 USD -8 USD 67 USD 67 USD -53.45$ 53.45 USD CH -US Dollars 53.45 53.45 USD H +53.45$ 53.45 USD C +US Dollars 53.45 53.45 USD 53.45 US Dollars 53.45 USD -US Dollar 53.45 53.45 USD H +US Dollar 53.45 53.45 USD 53.45 US Dollar 53.45 USD US Dollars53.45 53.45 USD -53.45US Dollars 53.45 USD H +53.45US Dollars 53.45 USD US Dollar53.45 53.45 USD US Dollat53.45 fail USD -53.45US Dollar 53.45 USD H -US Dollars (53.45) -53.45 USD H +53.45US Dollar 53.45 USD +US Dollars (53.45) -53.45 USD (53.45) US Dollars -53.45 USD (53.45) Euros -53.45 EUR -US Dollar (53.45) -53.45 USD H +US Dollar (53.45) -53.45 USD (53.45) US Dollar -53.45 USD -US Dollars(53.45) -53.45 USD H -(53.45)US Dollars -53.45 USD H -US Dollar(53.45) -53.45 USD H +US Dollars(53.45) -53.45 USD +(53.45)US Dollars -53.45 USD +US Dollar(53.45) -53.45 USD US Dollat(53.45) fail USD -(53.45)US Dollar -53.45 USD H +(53.45)US Dollar -53.45 USD test parse currency ISO negative @@ -1123,27 +1104,27 @@ $53.45 53.45 USD C 53.45 USD 53.45 USD 53.45 GBP 53.45 GBP -USD 53.45 53.45 USD H -53.45USD 53.45 USD H +USD 53.45 53.45 USD +53.45USD 53.45 USD USD53.45 53.45 USD -7.92 USD -7.92 USD -7.92 GBP -7.92 GBP -7.926 USD -7.926 USD -USD -7.926 -7.926 USD H --7.92USD -7.92 USD H -USD-7.92 -7.92 USD H +USD -7.926 -7.926 USD +-7.92USD -7.92 USD +USD-7.92 -7.92 USD -8 USD -8 USD 67 USD 67 USD -53.45$ 53.45 USD CH -US Dollars 53.45 53.45 USD H +53.45$ 53.45 USD C +US Dollars 53.45 53.45 USD 53.45 US Dollars 53.45 USD -US Dollar 53.45 53.45 USD H +US Dollar 53.45 53.45 USD 53.45 US Dollar 53.45 USD US Dollars53.45 53.45 USD -53.45US Dollars 53.45 USD H +53.45US Dollars 53.45 USD US Dollar53.45 53.45 USD US Dollat53.45 fail USD -53.45US Dollar 53.45 USD H +53.45US Dollar 53.45 USD test parse currency long @@ -1151,38 +1132,36 @@ set locale en_GB begin parse output outputCurrency breaks -// H throws a NullPointerException on the first case 53.45 fail GBP £53.45 53.45 GBP $53.45 53.45 USD C 53.45 USD 53.45 USD 53.45 GBP 53.45 GBP -USD 53.45 53.45 USD H -53.45USD 53.45 USD H +USD 53.45 53.45 USD +53.45USD 53.45 USD USD53.45 53.45 USD (7.92) USD -7.92 USD (7.92) GBP -7.92 GBP (7.926) USD -7.926 USD -(7.926 USD) -7.926 USD H -(USD 7.926) -7.926 USD H -USD (7.926) -7.926 USD H -USD (7.92) -7.92 USD H -(7.92)USD -7.92 USD H -USD(7.92) -7.92 USD H +(7.926 USD) -7.926 USD +(USD 7.926) -7.926 USD +USD (7.926) -7.926 USD +USD (7.92) -7.92 USD +(7.92)USD -7.92 USD +USD(7.92) -7.92 USD (8) USD -8 USD -8 USD -8 USD 67 USD 67 USD -// H throws a NullPointerException on the next case -53.45$ 53.45 USD CH -US Dollars 53.45 53.45 USD H +53.45$ 53.45 USD C +US Dollars 53.45 53.45 USD 53.45 US Dollars 53.45 USD -US Dollar 53.45 53.45 USD H +US Dollar 53.45 53.45 USD 53.45 US Dollar 53.45 USD US Dollars53.45 53.45 USD -53.45US Dollars 53.45 USD H +53.45US Dollars 53.45 USD US Dollar53.45 53.45 USD US Dollat53.45 fail USD -53.45US Dollar 53.45 USD H +53.45US Dollar 53.45 USD test parse currency short @@ -1195,31 +1174,31 @@ $53.45 53.45 USD C 53.45 USD 53.45 USD 53.45 GBP 53.45 GBP -USD 53.45 53.45 USD H -53.45USD 53.45 USD H +USD 53.45 53.45 USD +53.45USD 53.45 USD USD53.45 53.45 USD (7.92) USD -7.92 USD (7.92) GBP -7.92 GBP (7.926) USD -7.926 USD -(7.926 USD) -7.926 USD H -(USD 7.926) -7.926 USD H -USD (7.926) -7.926 USD H -USD (7.92) -7.92 USD H -(7.92)USD -7.92 USD H -USD(7.92) -7.92 USD H +(7.926 USD) -7.926 USD +(USD 7.926) -7.926 USD +USD (7.926) -7.926 USD +USD (7.92) -7.92 USD +(7.92)USD -7.92 USD +USD(7.92) -7.92 USD (8) USD -8 USD -8 USD -8 USD 67 USD 67 USD -53.45$ 53.45 USD CH -US Dollars 53.45 53.45 USD H +53.45$ 53.45 USD C +US Dollars 53.45 53.45 USD 53.45 US Dollars 53.45 USD -US Dollar 53.45 53.45 USD H +US Dollar 53.45 53.45 USD 53.45 US Dollar 53.45 USD US Dollars53.45 53.45 USD -53.45US Dollars 53.45 USD H +53.45US Dollars 53.45 USD US Dollar53.45 53.45 USD US Dollat53.45 fail USD -53.45US Dollar 53.45 USD H +53.45US Dollar 53.45 USD test parse currency short prefix @@ -1232,31 +1211,31 @@ $53.45 53.45 USD C 53.45 USD 53.45 USD 53.45 GBP 53.45 GBP -USD 53.45 53.45 USD H -53.45USD 53.45 USD H +USD 53.45 53.45 USD +53.45USD 53.45 USD USD53.45 53.45 USD // C and P fail these because '(' is an incomplete prefix. -(7.92) USD -7.92 USD CHJP -(7.92) GBP -7.92 GBP CHJP -(7.926) USD -7.926 USD CHJP -(7.926 USD) -7.926 USD CHJP -(USD 7.926) -7.926 USD H -USD (7.926) -7.926 USD CHJP -USD (7.92) -7.92 USD CHJP -(7.92)USD -7.92 USD CHJP -USD(7.92) -7.92 USD CHJP -(8) USD -8 USD CHJP +(7.92) USD -7.92 USD CJP +(7.92) GBP -7.92 GBP CJP +(7.926) USD -7.926 USD CJP +(7.926 USD) -7.926 USD CJP +(USD 7.926) -7.926 USD +USD (7.926) -7.926 USD CJP +USD (7.92) -7.92 USD CJP +(7.92)USD -7.92 USD CJP +USD(7.92) -7.92 USD CJP +(8) USD -8 USD CJP -8 USD -8 USD 67 USD 67 USD -53.45$ 53.45 USD CH -US Dollars 53.45 53.45 USD H +53.45$ 53.45 USD C +US Dollars 53.45 53.45 USD 53.45 US Dollars 53.45 USD -US Dollar 53.45 53.45 USD H +US Dollar 53.45 53.45 USD 53.45 US Dollar 53.45 USD US Dollars53.45 53.45 USD -53.45US Dollars 53.45 USD H +53.45US Dollars 53.45 USD US Dollar53.45 53.45 USD -53.45US Dollar 53.45 USD H +53.45US Dollar 53.45 USD test format foreign currency set locale fa_IR @@ -1371,7 +1350,7 @@ (7.92)USD fail USD USD(7.92) fail USD (8) USD -8 USD --8 USD fail USD H +-8 USD fail USD 67 USD 67 USD 53.45$ fail USD US Dollars 53.45 fail USD @@ -1400,7 +1379,7 @@ set maxFractionDigits 0 begin format output breaks --0.99 -0 HK +-0.99 -0 K test parse decimalPatternMatchRequired set locale en @@ -1409,11 +1388,11 @@ pattern parse output breaks // K doesn't support this feature. 0 123 123 -0 123. fail HK -0 1.23 fail HK +0 123. fail K +0 1.23 fail K 0 -513 -513 -0 -513. fail HK -0 -5.13 fail HK +0 -513. fail K +0 -5.13 fail K 0.0 123 fail K 0.0 123. 123 0.0 1.23 1.23 @@ -1427,13 +1406,13 @@ begin pattern parse output breaks # -123 -123 -# - 123 -123 HK -# -123 -123 HK -# - 123 -123 HK +# - 123 -123 K +# -123 -123 K +# - 123 -123 K # 123- 123 # 123 - 123 #;#- 123- -123 -#;#- 123 - -123 HK +#;#- 123 - -123 K test parse case sensitive set locale en @@ -1444,19 +1423,18 @@ Aa1.23 1 1.23 Aa1.23 0 1.23 AA1.23 1 fail -// H and K do not support case-insensitive parsing for prefix/suffix. -// H supports it for the exponent separator, but not K. -AA1.23 0 1.23 HK +// K does not support case-insensitive parsing for prefix/suffix. +AA1.23 0 1.23 K aa1.23 1 fail -aa1.23 0 1.23 HK +aa1.23 0 1.23 K Aa1.23E3 1 1230 Aa1.23E3 0 1230 -Aa1.23e3 1 1.23 H +Aa1.23e3 1 1.23 Aa1.23e3 0 1230 K NaN 1 NaN K NaN 0 NaN K nan 1 fail -nan 0 NaN HK +nan 0 NaN K test parse infinity and scientific notation overflow set locale en @@ -1472,13 +1450,13 @@ -1E-99999999999999 -0.0 1E2147483648 Inf K 1E2147483647 Inf K -// H, J and K get Infinity -1E2147483646 1E+2147483646 HJK +// J and K get Infinity +1E2147483646 1E+2147483646 JK 1E-2147483649 0 1E-2147483648 0 -// H and K return zero here -1E-2147483647 1E-2147483647 HJK -1E-2147483646 1E-2147483646 HJK +// K returns zero here +1E-2147483647 1E-2147483647 JK +1E-2147483646 1E-2147483646 JK test format push limits set locale en @@ -1506,13 +1484,13 @@ pattern lenient parse output breaks // Groups after the first group need 2 digits to be accepted. // JDK does not see space as grouping and parses most of these as 9. -#,##0 1 9 9 9 H +#,##0 1 9 9 9 #,##0 1 9 99 999 K #,##0 1 9 999 9999 K -#,##0 1 9 9 9 9 H +#,##0 1 9 9 9 9 #,##0 1 ,9 9 #,##0 1 99,.0 99 -#,##0 1 9 9. 9 H +#,##0 1 9 9. 9 #,##0 1 9 99. 999 K 0 1 9 9 9 0 1 9 99 9 @@ -1559,36 +1537,36 @@ x a‎b56c df 56 x a‎b56c df 56 K x ab56c df 56 K -x ab56c df 56 HK +x ab56c df 56 K x ab56c df 56 K -x ab56 56 HK -x a b56 56 HK -56cdf 56 HK -56c df 56 HK -56cd f 56 HK -56c‎d‎f 56 HK -56cdf 56 HK -56c d‎f 56 HK -56‎c df 56 HK +x ab56 56 K +x a b56 56 K +56cdf 56 K +56c df 56 K +56cd f 56 K +56c‎d‎f 56 K +56cdf 56 K +56c d‎f 56 K +56‎c df 56 K y g‎h56i jk -56 y g‎h56i jk -56 K y gh56i jk -56 K -y gh56i jk -56 HK +y gh56i jk -56 K y gh56i jk -56 K -y gh56 -56 HK -y g h56 -56 HK +y gh56 -56 K +y g h56 -56 K // S stops parsing after the 'i' for these and returns -56 // C stops before the 'i' and gets 56 -56ijk -56 HK -56i jk -56 HK -56ij k -56 HK -56i‎j‎k -56 HK -56ijk -56 HK -56i j‎k -56 HK -56‎i jk -56 HK -// S and C get 56 (accepts ' ' gs grouping); H and K get null +56ijk -56 K +56i jk -56 K +56ij k -56 K +56i‎j‎k -56 K +56ijk -56 K +56i j‎k -56 K +56‎i jk -56 K +// S and C get 56 (accepts ' ' gs grouping); K gets null 5 6 fail CJP -5‎6 5 HK +5‎6 5 K test parse spaces in grouping // This test gives the ideal behavior of these cases, which @@ -1598,7 +1576,7 @@ set pattern #,##0 begin parse output breaks -1 2 1 H +1 2 1 1 23 123 K // K gets 1 here; doesn't pick up the grouping separator 1 234 1234 K @@ -1614,7 +1592,7 @@ // C and J get "1" // P gets "1.0" // K gets "1.1" (??) -0.975 0.98 CHJKP +0.975 0.98 CJKP test lenient parse currency match // This test is for #13112 @@ -1622,8 +1600,8 @@ set pattern ¤#,##0.00 begin parse output breaks -// H and K get null -1.23!@#$%^ 1.23 HK +// K gets null +1.23!@#$%^ 1.23 K test percentage parsing multiplier // This test is for #13114 @@ -1632,9 +1610,9 @@ begin parse output breaks 55% 0.55 -// H and K get null +// K gets null // C and P scale by 100 even if the percent sign is not present -55 0.55 HK +55 0.55 K test trailing grouping separators in pattern // This test is for #13115 @@ -1653,8 +1631,8 @@ pattern format output breaks 0 -15 -15 0; -15 -15 -// H and K still prepend a '-' even though the pattern says otherwise -0;0 -15 15 HK +// K still prepends a '-' even though the pattern says otherwise +0;0 -15 15 K test percentage multiplier parsing // This test is for #13129 @@ -1670,9 +1648,9 @@ set signAlwaysShown 1 begin format output breaks -// H and K do not support this feature -42 +42 HK -0 +0 HK +// K does not support this feature +42 +42 K +0 +0 K -42 -42 test parse strict with plus sign @@ -1683,14 +1661,14 @@ lenient parse output breaks 1 42 42 1 -42 -42 -1 +42 42 HK +1 +42 42 K 1 0 0 -1 +0 0 HK -0 42 fail HK +1 +0 0 K +0 42 fail K 0 -42 -42 -0 +42 42 HK -0 0 fail HK -0 +0 0 HK +0 +42 42 K +0 0 fail K +0 +0 0 K test parse with scientific-separator-affix overlap set locale en @@ -1708,13 +1686,13 @@ begin parse output breaks USD123 123 -USD 123 123 HK +USD 123 123 K usd123 123 K -usd 123 123 HK +usd 123 123 K Usd123 123 K -Usd 123 123 HK +Usd 123 123 K // US$ is not used for US dollars in en-US -US$123 fail H +US$123 fail us$123 fail Us$123 fail 123 US dollars 123 K @@ -1733,11 +1711,11 @@ begin parse output outputCurrency breaks USD123 123 USD -USD 123 123 USD H +USD 123 123 USD usd123 123 USD -usd 123 123 USD H +usd 123 123 USD Usd123 123 USD -Usd 123 123 USD H +Usd 123 123 USD US$123 123 USD C us$123 fail fail Us$123 fail fail @@ -1746,10 +1724,16 @@ 123 us dollars 123 USD GBP123 123 GBP gbp123 123 GBP C -British pounds 123 123 GBP H -british POUNDS 123 123 GBP H - +British pounds 123 123 GBP +british POUNDS 123 123 GBP +test parse scientific with bidi marks +begin +locale parse output breaks +en 4E\u200E+02 400 K +en 4E+02 400 K +he 4E\u200E+02 400 K +he 4E+02 400 K diff -Nru icu-64.2/source/test/testdata/numberpermutationtest.txt icu-65.1/source/test/testdata/numberpermutationtest.txt --- icu-64.2/source/test/testdata/numberpermutationtest.txt 1970-01-01 00:00:00.000000000 +0000 +++ icu-65.1/source/test/testdata/numberpermutationtest.txt 2019-10-03 11:16:41.000000000 +0000 @@ -0,0 +1,9103 @@ +# © 2019 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html + +compact-short percent unit-width-narrow + es-MX + 0 % + 92 k + -0.22 % + zh-TW + 0% + 9.2萬 + -0.22% + bn-BD + ০% + ৯২ হা + -০.২২% + +compact-short percent unit-width-full-name + es-MX + 0 % + 92 k + -0.22 % + zh-TW + 0% + 9.2萬 + -0.22% + bn-BD + ০% + ৯২ হা + -০.২২% + +compact-short currency/EUR unit-width-narrow + es-MX + €0 + 92 k€ + -€0.22 + zh-TW + €0 + €9.2萬 + -€0.22 + bn-BD + ০€ + ৯২ হা€ + -০.২২€ + +compact-short currency/EUR unit-width-full-name + es-MX + 0 euros + 92 k euros + -0.22 euros + zh-TW + 0 歐元 + 9.2萬 歐元 + -0.22 歐元 + bn-BD + ০ ইউরো + ৯২ হা ইউরো + -০.২২ ইউরো + +compact-short measure-unit/length-furlong unit-width-narrow + es-MX + 0 fur + 92 k fur + -0.22 fur + zh-TW + 0化朗 + 9.2萬化朗 + -0.22化朗 + bn-BD + ০ ফার্লং + ৯২ হা ফার্লং + -০.২২ ফার্লং + +compact-short measure-unit/length-furlong unit-width-full-name + es-MX + 0 fur + 92 k fur + -0.22 fur + zh-TW + 0 化朗 + 9.2萬 化朗 + -0.22 化朗 + bn-BD + ০ ফার্লং + ৯২ হা ফার্লং + -০.২২ ফার্লং + +scientific/+ee/sign-always percent unit-width-narrow + es-MX + 0E+00 % + 9.182736E+04 % + -2.2222E-01 % + zh-TW + 0E+00% + 9.182736E+04% + -2.2222E-01% + bn-BD + ০E+০০% + ৯.১৮২৭৩৬E+০৪% + -২.২২২২E-০১% + +scientific/+ee/sign-always percent unit-width-full-name + es-MX + 0E+00 % + 9.182736E+04 % + -2.2222E-01 % + zh-TW + 0E+00% + 9.182736E+04% + -2.2222E-01% + bn-BD + ০E+০০% + ৯.১৮২৭৩৬E+০৪% + -২.২২২২E-০১% + +scientific/+ee/sign-always currency/EUR unit-width-narrow + es-MX + €0.00E+00 + €9.18E+04 + -€2.22E-01 + zh-TW + €0.00E+00 + €9.18E+04 + -€2.22E-01 + bn-BD + ০.০০E+০০€ + ৯.১৮E+০৪€ + -২.২২E-০১€ + +scientific/+ee/sign-always currency/EUR unit-width-full-name + es-MX + 0.00E+00 euros + 9.18E+04 euros + -2.22E-01 euros + zh-TW + 0.00E+00 歐元 + 9.18E+04 歐元 + -2.22E-01 歐元 + bn-BD + ০.০০E+০০ ইউরো + ৯.১৮E+০৪ ইউরো + -২.২২E-০১ ইউরো + +scientific/+ee/sign-always measure-unit/length-furlong unit-width-narrow + es-MX + 0E+00 fur + 9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0E+00化朗 + 9.182736E+04化朗 + -2.2222E-01化朗 + bn-BD + ০E+০০ ফার্লং + ৯.১৮২৭৩৬E+০৪ ফার্লং + -২.২২২২E-০১ ফার্লং + +scientific/+ee/sign-always measure-unit/length-furlong unit-width-full-name + es-MX + 0E+00 fur + 9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0E+00 化朗 + 9.182736E+04 化朗 + -2.2222E-01 化朗 + bn-BD + ০E+০০ ফার্লং + ৯.১৮২৭৩৬E+০৪ ফার্লং + -২.২২২২E-০১ ফার্লং + +compact-short percent precision-integer + es-MX + 0 % + 92 k + -0 % + zh-TW + 0% + 9萬 + -0% + bn-BD + ০% + ৯২ হা + -০% + +compact-short percent .000 + es-MX + 0.000 % + 91.827 k + -0.222 % + zh-TW + 0.000% + 9.183萬 + -0.222% + bn-BD + ০.০০০% + ৯১.৮২৭ হা + -০.২২২% + +compact-short percent .##/@@@+ + es-MX + 0 % + 91.83 k + -0.222 % + zh-TW + 0% + 9.18萬 + -0.222% + bn-BD + ০% + ৯১.৮৩ হা + -০.২২২% + +compact-short percent @@ + es-MX + 0.0 % + 92 k + -0.22 % + zh-TW + 0.0% + 9.2萬 + -0.22% + bn-BD + ০.০% + ৯২ হা + -০.২২% + +compact-short currency/EUR precision-integer + es-MX + EUR 0 + 92 kEUR + -EUR 0 + zh-TW + €0 + €9萬 + -€0 + bn-BD + ০€ + ৯২ হা€ + -০€ + +compact-short currency/EUR .000 + es-MX + EUR 0.000 + 91.827 kEUR + -EUR 0.222 + zh-TW + €0.000 + €9.183萬 + -€0.222 + bn-BD + ০.০০০€ + ৯১.৮২৭ হা€ + -০.২২২€ + +compact-short currency/EUR .##/@@@+ + es-MX + EUR 0 + 91.83 kEUR + -EUR 0.222 + zh-TW + €0 + €9.18萬 + -€0.222 + bn-BD + ০€ + ৯১.৮৩ হা€ + -০.২২২€ + +compact-short currency/EUR @@ + es-MX + EUR 0.0 + 92 kEUR + -EUR 0.22 + zh-TW + €0.0 + €9.2萬 + -€0.22 + bn-BD + ০.০€ + ৯২ হা€ + -০.২২€ + +compact-short measure-unit/length-furlong precision-integer + es-MX + 0 fur + 92 k fur + -0 fur + zh-TW + 0 化朗 + 9萬 化朗 + -0 化朗 + bn-BD + ০ ফার্লং + ৯২ হা ফার্লং + -০ ফার্লং + +compact-short measure-unit/length-furlong .000 + es-MX + 0.000 fur + 91.827 k fur + -0.222 fur + zh-TW + 0.000 化朗 + 9.183萬 化朗 + -0.222 化朗 + bn-BD + ০.০০০ ফার্লং + ৯১.৮২৭ হা ফার্লং + -০.২২২ ফার্লং + +compact-short measure-unit/length-furlong .##/@@@+ + es-MX + 0 fur + 91.83 k fur + -0.222 fur + zh-TW + 0 化朗 + 9.18萬 化朗 + -0.222 化朗 + bn-BD + ০ ফার্লং + ৯১.৮৩ হা ফার্লং + -০.২২২ ফার্লং + +compact-short measure-unit/length-furlong @@ + es-MX + 0.0 fur + 92 k fur + -0.22 fur + zh-TW + 0.0 化朗 + 9.2萬 化朗 + -0.22 化朗 + bn-BD + ০.০ ফার্লং + ৯২ হা ফার্লং + -০.২২ ফার্লং + +scientific/+ee/sign-always percent precision-integer + es-MX + 0E+00 % + 9E+04 % + -2E-01 % + zh-TW + 0E+00% + 9E+04% + -2E-01% + bn-BD + ০E+০০% + ৯E+০৪% + -২E-০১% + +scientific/+ee/sign-always percent .000 + es-MX + 0.000E+00 % + 9.183E+04 % + -2.222E-01 % + zh-TW + 0.000E+00% + 9.183E+04% + -2.222E-01% + bn-BD + ০.০০০E+০০% + ৯.১৮৩E+০৪% + -২.২২২E-০১% + +scientific/+ee/sign-always percent .##/@@@+ + es-MX + 0E+00 % + 9.18E+04 % + -2.22E-01 % + zh-TW + 0E+00% + 9.18E+04% + -2.22E-01% + bn-BD + ০E+০০% + ৯.১৮E+০৪% + -২.২২E-০১% + +scientific/+ee/sign-always percent @@ + es-MX + 0.0E+00 % + 9.2E+04 % + -2.2E-01 % + zh-TW + 0.0E+00% + 9.2E+04% + -2.2E-01% + bn-BD + ০.০E+০০% + ৯.২E+০৪% + -২.২E-০১% + +scientific/+ee/sign-always currency/EUR precision-integer + es-MX + EUR 0E+00 + EUR 9E+04 + -EUR 2E-01 + zh-TW + €0E+00 + €9E+04 + -€2E-01 + bn-BD + ০E+০০€ + ৯E+০৪€ + -২E-০১€ + +scientific/+ee/sign-always currency/EUR .000 + es-MX + EUR 0.000E+00 + EUR 9.183E+04 + -EUR 2.222E-01 + zh-TW + €0.000E+00 + €9.183E+04 + -€2.222E-01 + bn-BD + ০.০০০E+০০€ + ৯.১৮৩E+০৪€ + -২.২২২E-০১€ + +scientific/+ee/sign-always currency/EUR .##/@@@+ + es-MX + EUR 0E+00 + EUR 9.18E+04 + -EUR 2.22E-01 + zh-TW + €0E+00 + €9.18E+04 + -€2.22E-01 + bn-BD + ০E+০০€ + ৯.১৮E+০৪€ + -২.২২E-০১€ + +scientific/+ee/sign-always currency/EUR @@ + es-MX + EUR 0.0E+00 + EUR 9.2E+04 + -EUR 2.2E-01 + zh-TW + €0.0E+00 + €9.2E+04 + -€2.2E-01 + bn-BD + ০.০E+০০€ + ৯.২E+০৪€ + -২.২E-০১€ + +scientific/+ee/sign-always measure-unit/length-furlong precision-integer + es-MX + 0E+00 fur + 9E+04 fur + -2E-01 fur + zh-TW + 0E+00 化朗 + 9E+04 化朗 + -2E-01 化朗 + bn-BD + ০E+০০ ফার্লং + ৯E+০৪ ফার্লং + -২E-০১ ফার্লং + +scientific/+ee/sign-always measure-unit/length-furlong .000 + es-MX + 0.000E+00 fur + 9.183E+04 fur + -2.222E-01 fur + zh-TW + 0.000E+00 化朗 + 9.183E+04 化朗 + -2.222E-01 化朗 + bn-BD + ০.০০০E+০০ ফার্লং + ৯.১৮৩E+০৪ ফার্লং + -২.২২২E-০১ ফার্লং + +scientific/+ee/sign-always measure-unit/length-furlong .##/@@@+ + es-MX + 0E+00 fur + 9.18E+04 fur + -2.22E-01 fur + zh-TW + 0E+00 化朗 + 9.18E+04 化朗 + -2.22E-01 化朗 + bn-BD + ০E+০০ ফার্লং + ৯.১৮E+০৪ ফার্লং + -২.২২E-০১ ফার্লং + +scientific/+ee/sign-always measure-unit/length-furlong @@ + es-MX + 0.0E+00 fur + 9.2E+04 fur + -2.2E-01 fur + zh-TW + 0.0E+00 化朗 + 9.2E+04 化朗 + -2.2E-01 化朗 + bn-BD + ০.০E+০০ ফার্লং + ৯.২E+০৪ ফার্লং + -২.২E-০১ ফার্লং + +compact-short percent rounding-mode-floor + es-MX + 0 % + 91 k + -0.23 % + zh-TW + 0% + 9.1萬 + -0.23% + bn-BD + ০% + ৯১ হা + -০.২৩% + +compact-short currency/EUR rounding-mode-floor + es-MX + EUR 0 + 91 kEUR + -EUR 0.23 + zh-TW + €0 + €9.1萬 + -€0.23 + bn-BD + ০€ + ৯১ হা€ + -০.২৩€ + +compact-short measure-unit/length-furlong rounding-mode-floor + es-MX + 0 fur + 91 k fur + -0.23 fur + zh-TW + 0 化朗 + 9.1萬 化朗 + -0.23 化朗 + bn-BD + ০ ফার্লং + ৯১ হা ফার্লং + -০.২৩ ফার্লং + +scientific/+ee/sign-always percent rounding-mode-floor + es-MX + 0E+00 % + 9.182736E+04 % + -2.2222E-01 % + zh-TW + 0E+00% + 9.182736E+04% + -2.2222E-01% + bn-BD + ০E+০০% + ৯.১৮২৭৩৬E+০৪% + -২.২২২২E-০১% + +scientific/+ee/sign-always currency/EUR rounding-mode-floor + es-MX + EUR 0.00E+00 + EUR 9.18E+04 + -EUR 2.23E-01 + zh-TW + €0.00E+00 + €9.18E+04 + -€2.23E-01 + bn-BD + ০.০০E+০০€ + ৯.১৮E+০৪€ + -২.২৩E-০১€ + +scientific/+ee/sign-always measure-unit/length-furlong rounding-mode-floor + es-MX + 0E+00 fur + 9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0E+00 化朗 + 9.182736E+04 化朗 + -2.2222E-01 化朗 + bn-BD + ০E+০০ ফার্লং + ৯.১৮২৭৩৬E+০৪ ফার্লং + -২.২২২২E-০১ ফার্লং + +compact-short percent integer-width/##00 + es-MX + 00 % + 92 k + -00.22 % + zh-TW + 00% + 09.2萬 + -00.22% + bn-BD + ০০% + ৯২ হা + -০০.২২% + +compact-short currency/EUR integer-width/##00 + es-MX + EUR 00 + 92 kEUR + -EUR 00.22 + zh-TW + €00 + €09.2萬 + -€00.22 + bn-BD + ০০€ + ৯২ হা€ + -০০.২২€ + +compact-short measure-unit/length-furlong integer-width/##00 + es-MX + 00 fur + 92 k fur + -00.22 fur + zh-TW + 00 化朗 + 09.2萬 化朗 + -00.22 化朗 + bn-BD + ০০ ফার্লং + ৯২ হা ফার্লং + -০০.২২ ফার্লং + +scientific/+ee/sign-always percent integer-width/##00 + es-MX + 00E+00 % + 09.182736E+04 % + -02.2222E-01 % + zh-TW + 00E+00% + 09.182736E+04% + -02.2222E-01% + bn-BD + ০০E+০০% + ০৯.১৮২৭৩৬E+০৪% + -০২.২২২২E-০১% + +scientific/+ee/sign-always currency/EUR integer-width/##00 + es-MX + EUR 00.00E+00 + EUR 09.18E+04 + -EUR 02.22E-01 + zh-TW + €00.00E+00 + €09.18E+04 + -€02.22E-01 + bn-BD + ০০.০০E+০০€ + ০৯.১৮E+০৪€ + -০২.২২E-০১€ + +scientific/+ee/sign-always measure-unit/length-furlong integer-width/##00 + es-MX + 00E+00 fur + 09.182736E+04 fur + -02.2222E-01 fur + zh-TW + 00E+00 化朗 + 09.182736E+04 化朗 + -02.2222E-01 化朗 + bn-BD + ০০E+০০ ফার্লং + ০৯.১৮২৭৩৬E+০৪ ফার্লং + -০২.২২২২E-০১ ফার্লং + +compact-short percent scale/0.5 + es-MX + 0 % + 46 k + -0.11 % + zh-TW + 0% + 4.6萬 + -0.11% + bn-BD + ০% + ৪৬ হা + -০.১১% + +compact-short currency/EUR scale/0.5 + es-MX + EUR 0 + 46 kEUR + -EUR 0.11 + zh-TW + €0 + €4.6萬 + -€0.11 + bn-BD + ০€ + ৪৬ হা€ + -০.১১€ + +compact-short measure-unit/length-furlong scale/0.5 + es-MX + 0 fur + 46 k fur + -0.11 fur + zh-TW + 0 化朗 + 4.6萬 化朗 + -0.11 化朗 + bn-BD + ০ ফার্লং + ৪৬ হা ফার্লং + -০.১১ ফার্লং + +scientific/+ee/sign-always percent scale/0.5 + es-MX + 0E+00 % + 4.591368E+04 % + -1.1111E-01 % + zh-TW + 0E+00% + 4.591368E+04% + -1.1111E-01% + bn-BD + ০E+০০% + ৪.৫৯১৩৬৮E+০৪% + -১.১১১১E-০১% + +scientific/+ee/sign-always currency/EUR scale/0.5 + es-MX + EUR 0.00E+00 + EUR 4.59E+04 + -EUR 1.11E-01 + zh-TW + €0.00E+00 + €4.59E+04 + -€1.11E-01 + bn-BD + ০.০০E+০০€ + ৪.৫৯E+০৪€ + -১.১১E-০১€ + +scientific/+ee/sign-always measure-unit/length-furlong scale/0.5 + es-MX + 0E+00 fur + 4.591368E+04 fur + -1.1111E-01 fur + zh-TW + 0E+00 化朗 + 4.591368E+04 化朗 + -1.1111E-01 化朗 + bn-BD + ০E+০০ ফার্লং + ৪.৫৯১৩৬৮E+০৪ ফার্লং + -১.১১১১E-০১ ফার্লং + +compact-short percent group-on-aligned + es-MX + 0 % + 92 k + -0.22 % + zh-TW + 0% + 9.2萬 + -0.22% + bn-BD + ০% + ৯২ হা + -০.২২% + +compact-short currency/EUR group-on-aligned + es-MX + EUR 0 + 92 kEUR + -EUR 0.22 + zh-TW + €0 + €9.2萬 + -€0.22 + bn-BD + ০€ + ৯২ হা€ + -০.২২€ + +compact-short measure-unit/length-furlong group-on-aligned + es-MX + 0 fur + 92 k fur + -0.22 fur + zh-TW + 0 化朗 + 9.2萬 化朗 + -0.22 化朗 + bn-BD + ০ ফার্লং + ৯২ হা ফার্লং + -০.২২ ফার্লং + +scientific/+ee/sign-always percent group-on-aligned + es-MX + 0E+00 % + 9.182736E+04 % + -2.2222E-01 % + zh-TW + 0E+00% + 9.182736E+04% + -2.2222E-01% + bn-BD + ০E+০০% + ৯.১৮২৭৩৬E+০৪% + -২.২২২২E-০১% + +scientific/+ee/sign-always currency/EUR group-on-aligned + es-MX + EUR 0.00E+00 + EUR 9.18E+04 + -EUR 2.22E-01 + zh-TW + €0.00E+00 + €9.18E+04 + -€2.22E-01 + bn-BD + ০.০০E+০০€ + ৯.১৮E+০৪€ + -২.২২E-০১€ + +scientific/+ee/sign-always measure-unit/length-furlong group-on-aligned + es-MX + 0E+00 fur + 9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0E+00 化朗 + 9.182736E+04 化朗 + -2.2222E-01 化朗 + bn-BD + ০E+০০ ফার্লং + ৯.১৮২৭৩৬E+০৪ ফার্লং + -২.২২২২E-০১ ফার্লং + +compact-short percent latin + es-MX + 0 % + 92 k + -0.22 % + zh-TW + 0% + 9.2萬 + -0.22% + bn-BD + 0% + 92 হা + -0.22% + +compact-short currency/EUR latin + es-MX + EUR 0 + 92 kEUR + -EUR 0.22 + zh-TW + €0 + €9.2萬 + -€0.22 + bn-BD + 0€ + 92 হা€ + -0.22€ + +compact-short measure-unit/length-furlong latin + es-MX + 0 fur + 92 k fur + -0.22 fur + zh-TW + 0 化朗 + 9.2萬 化朗 + -0.22 化朗 + bn-BD + 0 ফার্লং + 92 হা ফার্লং + -0.22 ফার্লং + +scientific/+ee/sign-always percent latin + es-MX + 0E+00 % + 9.182736E+04 % + -2.2222E-01 % + zh-TW + 0E+00% + 9.182736E+04% + -2.2222E-01% + bn-BD + 0E+00% + 9.182736E+04% + -2.2222E-01% + +scientific/+ee/sign-always currency/EUR latin + es-MX + EUR 0.00E+00 + EUR 9.18E+04 + -EUR 2.22E-01 + zh-TW + €0.00E+00 + €9.18E+04 + -€2.22E-01 + bn-BD + 0.00E+00€ + 9.18E+04€ + -2.22E-01€ + +scientific/+ee/sign-always measure-unit/length-furlong latin + es-MX + 0E+00 fur + 9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0E+00 化朗 + 9.182736E+04 化朗 + -2.2222E-01 化朗 + bn-BD + 0E+00 ফার্লং + 9.182736E+04 ফার্লং + -2.2222E-01 ফার্লং + +compact-short percent sign-accounting-except-zero + es-MX + 0 % + +92 k + -0.22 % + zh-TW + 0% + +9.2萬 + -0.22% + bn-BD + ০% + +৯২ হা + -০.২২% + +compact-short currency/EUR sign-accounting-except-zero + es-MX + EUR 0 + +92 kEUR + -EUR 0.22 + zh-TW + €0 + +€9.2萬 + (€0.22) + bn-BD + ০€ + +৯২ হা€ + (০.২২ €) + +compact-short measure-unit/length-furlong sign-accounting-except-zero + es-MX + 0 fur + +92 k fur + -0.22 fur + zh-TW + 0 化朗 + +9.2萬 化朗 + -0.22 化朗 + bn-BD + ০ ফার্লং + +৯২ হা ফার্লং + -০.২২ ফার্লং + +scientific/+ee/sign-always percent sign-accounting-except-zero + es-MX + 0E+00 % + +9.182736E+04 % + -2.2222E-01 % + zh-TW + 0E+00% + +9.182736E+04% + -2.2222E-01% + bn-BD + ০E+০০% + +৯.১৮২৭৩৬E+০৪% + -২.২২২২E-০১% + +scientific/+ee/sign-always currency/EUR sign-accounting-except-zero + es-MX + EUR 0.00E+00 + +EUR 9.18E+04 + -EUR 2.22E-01 + zh-TW + €0.00E+00 + +€9.18E+04 + (€2.22E-01) + bn-BD + ০.০০E+০০€ + +৯.১৮E+০৪€ + (২.২২E-০১ €) + +scientific/+ee/sign-always measure-unit/length-furlong sign-accounting-except-zero + es-MX + 0E+00 fur + +9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0E+00 化朗 + +9.182736E+04 化朗 + -2.2222E-01 化朗 + bn-BD + ০E+০০ ফার্লং + +৯.১৮২৭৩৬E+০৪ ফার্লং + -২.২২২২E-০১ ফার্লং + +compact-short percent decimal-always + es-MX + 0. % + 92. k + -0.22 % + zh-TW + 0.% + 9.2萬 + -0.22% + bn-BD + ০.% + ৯২. হা + -০.২২% + +compact-short currency/EUR decimal-always + es-MX + EUR 0. + 92. kEUR + -EUR 0.22 + zh-TW + €0. + €9.2萬 + -€0.22 + bn-BD + ০.€ + ৯২. হা€ + -০.২২€ + +compact-short measure-unit/length-furlong decimal-always + es-MX + 0. fur + 92. k fur + -0.22 fur + zh-TW + 0. 化朗 + 9.2萬 化朗 + -0.22 化朗 + bn-BD + ০. ফার্লং + ৯২. হা ফার্লং + -০.২২ ফার্লং + +scientific/+ee/sign-always percent decimal-always + es-MX + 0.E+00 % + 9.182736E+04 % + -2.2222E-01 % + zh-TW + 0.E+00% + 9.182736E+04% + -2.2222E-01% + bn-BD + ০.E+০০% + ৯.১৮২৭৩৬E+০৪% + -২.২২২২E-০১% + +scientific/+ee/sign-always currency/EUR decimal-always + es-MX + EUR 0.00E+00 + EUR 9.18E+04 + -EUR 2.22E-01 + zh-TW + €0.00E+00 + €9.18E+04 + -€2.22E-01 + bn-BD + ০.০০E+০০€ + ৯.১৮E+০৪€ + -২.২২E-০১€ + +scientific/+ee/sign-always measure-unit/length-furlong decimal-always + es-MX + 0.E+00 fur + 9.182736E+04 fur + -2.2222E-01 fur + zh-TW + 0.E+00 化朗 + 9.182736E+04 化朗 + -2.2222E-01 化朗 + bn-BD + ০.E+০০ ফার্লং + ৯.১৮২৭৩৬E+০৪ ফার্লং + -২.২২২২E-০১ ফার্লং + +compact-short unit-width-narrow precision-integer + es-MX + 0 + 92 k + -0 + zh-TW + 0 + 9萬 + -0 + bn-BD + ০ + ৯২ হা + -০ + +compact-short unit-width-narrow .000 + es-MX + 0.000 + 91.827 k + -0.222 + zh-TW + 0.000 + 9.183萬 + -0.222 + bn-BD + ০.০০০ + ৯১.৮২৭ হা + -০.২২২ + +compact-short unit-width-narrow .##/@@@+ + es-MX + 0 + 91.83 k + -0.222 + zh-TW + 0 + 9.18萬 + -0.222 + bn-BD + ০ + ৯১.৮৩ হা + -০.২২২ + +compact-short unit-width-narrow @@ + es-MX + 0.0 + 92 k + -0.22 + zh-TW + 0.0 + 9.2萬 + -0.22 + bn-BD + ০.০ + ৯২ হা + -০.২২ + +compact-short unit-width-full-name precision-integer + es-MX + 0 + 92 k + -0 + zh-TW + 0 + 9萬 + -0 + bn-BD + ০ + ৯২ হা + -০ + +compact-short unit-width-full-name .000 + es-MX + 0.000 + 91.827 k + -0.222 + zh-TW + 0.000 + 9.183萬 + -0.222 + bn-BD + ০.০০০ + ৯১.৮২৭ হা + -০.২২২ + +compact-short unit-width-full-name .##/@@@+ + es-MX + 0 + 91.83 k + -0.222 + zh-TW + 0 + 9.18萬 + -0.222 + bn-BD + ০ + ৯১.৮৩ হা + -০.২২২ + +compact-short unit-width-full-name @@ + es-MX + 0.0 + 92 k + -0.22 + zh-TW + 0.0 + 9.2萬 + -0.22 + bn-BD + ০.০ + ৯২ হা + -০.২২ + +scientific/+ee/sign-always unit-width-narrow precision-integer + es-MX + 0E+00 + 9E+04 + -2E-01 + zh-TW + 0E+00 + 9E+04 + -2E-01 + bn-BD + ০E+০০ + ৯E+০৪ + -২E-০১ + +scientific/+ee/sign-always unit-width-narrow .000 + es-MX + 0.000E+00 + 9.183E+04 + -2.222E-01 + zh-TW + 0.000E+00 + 9.183E+04 + -2.222E-01 + bn-BD + ০.০০০E+০০ + ৯.১৮৩E+০৪ + -২.২২২E-০১ + +scientific/+ee/sign-always unit-width-narrow .##/@@@+ + es-MX + 0E+00 + 9.18E+04 + -2.22E-01 + zh-TW + 0E+00 + 9.18E+04 + -2.22E-01 + bn-BD + ০E+০০ + ৯.১৮E+০৪ + -২.২২E-০১ + +scientific/+ee/sign-always unit-width-narrow @@ + es-MX + 0.0E+00 + 9.2E+04 + -2.2E-01 + zh-TW + 0.0E+00 + 9.2E+04 + -2.2E-01 + bn-BD + ০.০E+০০ + ৯.২E+০৪ + -২.২E-০১ + +scientific/+ee/sign-always unit-width-full-name precision-integer + es-MX + 0E+00 + 9E+04 + -2E-01 + zh-TW + 0E+00 + 9E+04 + -2E-01 + bn-BD + ০E+০০ + ৯E+০৪ + -২E-০১ + +scientific/+ee/sign-always unit-width-full-name .000 + es-MX + 0.000E+00 + 9.183E+04 + -2.222E-01 + zh-TW + 0.000E+00 + 9.183E+04 + -2.222E-01 + bn-BD + ০.০০০E+০০ + ৯.১৮৩E+০৪ + -২.২২২E-০১ + +scientific/+ee/sign-always unit-width-full-name .##/@@@+ + es-MX + 0E+00 + 9.18E+04 + -2.22E-01 + zh-TW + 0E+00 + 9.18E+04 + -2.22E-01 + bn-BD + ০E+০০ + ৯.১৮E+০৪ + -২.২২E-০১ + +scientific/+ee/sign-always unit-width-full-name @@ + es-MX + 0.0E+00 + 9.2E+04 + -2.2E-01 + zh-TW + 0.0E+00 + 9.2E+04 + -2.2E-01 + bn-BD + ০.০E+০০ + ৯.২E+০৪ + -২.২E-০১ + +compact-short unit-width-narrow rounding-mode-floor + es-MX + 0 + 91 k + -0.23 + zh-TW + 0 + 9.1萬 + -0.23 + bn-BD + ০ + ৯১ হা + -০.২৩ + +compact-short unit-width-full-name rounding-mode-floor + es-MX + 0 + 91 k + -0.23 + zh-TW + 0 + 9.1萬 + -0.23 + bn-BD + ০ + ৯১ হা + -০.২৩ + +scientific/+ee/sign-always unit-width-narrow rounding-mode-floor + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +scientific/+ee/sign-always unit-width-full-name rounding-mode-floor + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short unit-width-narrow integer-width/##00 + es-MX + 00 + 92 k + -00.22 + zh-TW + 00 + 09.2萬 + -00.22 + bn-BD + ০০ + ৯২ হা + -০০.২২ + +compact-short unit-width-full-name integer-width/##00 + es-MX + 00 + 92 k + -00.22 + zh-TW + 00 + 09.2萬 + -00.22 + bn-BD + ০০ + ৯২ হা + -০০.২২ + +scientific/+ee/sign-always unit-width-narrow integer-width/##00 + es-MX + 00E+00 + 09.182736E+04 + -02.2222E-01 + zh-TW + 00E+00 + 09.182736E+04 + -02.2222E-01 + bn-BD + ০০E+০০ + ০৯.১৮২৭৩৬E+০৪ + -০২.২২২২E-০১ + +scientific/+ee/sign-always unit-width-full-name integer-width/##00 + es-MX + 00E+00 + 09.182736E+04 + -02.2222E-01 + zh-TW + 00E+00 + 09.182736E+04 + -02.2222E-01 + bn-BD + ০০E+০০ + ০৯.১৮২৭৩৬E+০৪ + -০২.২২২২E-০১ + +compact-short unit-width-narrow scale/0.5 + es-MX + 0 + 46 k + -0.11 + zh-TW + 0 + 4.6萬 + -0.11 + bn-BD + ০ + ৪৬ হা + -০.১১ + +compact-short unit-width-full-name scale/0.5 + es-MX + 0 + 46 k + -0.11 + zh-TW + 0 + 4.6萬 + -0.11 + bn-BD + ০ + ৪৬ হা + -০.১১ + +scientific/+ee/sign-always unit-width-narrow scale/0.5 + es-MX + 0E+00 + 4.591368E+04 + -1.1111E-01 + zh-TW + 0E+00 + 4.591368E+04 + -1.1111E-01 + bn-BD + ০E+০০ + ৪.৫৯১৩৬৮E+০৪ + -১.১১১১E-০১ + +scientific/+ee/sign-always unit-width-full-name scale/0.5 + es-MX + 0E+00 + 4.591368E+04 + -1.1111E-01 + zh-TW + 0E+00 + 4.591368E+04 + -1.1111E-01 + bn-BD + ০E+০০ + ৪.৫৯১৩৬৮E+০৪ + -১.১১১১E-০১ + +compact-short unit-width-narrow group-on-aligned + es-MX + 0 + 92 k + -0.22 + zh-TW + 0 + 9.2萬 + -0.22 + bn-BD + ০ + ৯২ হা + -০.২২ + +compact-short unit-width-full-name group-on-aligned + es-MX + 0 + 92 k + -0.22 + zh-TW + 0 + 9.2萬 + -0.22 + bn-BD + ০ + ৯২ হা + -০.২২ + +scientific/+ee/sign-always unit-width-narrow group-on-aligned + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +scientific/+ee/sign-always unit-width-full-name group-on-aligned + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short unit-width-narrow latin + es-MX + 0 + 92 k + -0.22 + zh-TW + 0 + 9.2萬 + -0.22 + bn-BD + 0 + 92 হা + -0.22 + +compact-short unit-width-full-name latin + es-MX + 0 + 92 k + -0.22 + zh-TW + 0 + 9.2萬 + -0.22 + bn-BD + 0 + 92 হা + -0.22 + +scientific/+ee/sign-always unit-width-narrow latin + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + 0E+00 + 9.182736E+04 + -2.2222E-01 + +scientific/+ee/sign-always unit-width-full-name latin + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + 0E+00 + 9.182736E+04 + -2.2222E-01 + +compact-short unit-width-narrow sign-accounting-except-zero + es-MX + 0 + +92 k + -0.22 + zh-TW + 0 + +9.2萬 + -0.22 + bn-BD + ০ + +৯২ হা + -০.২২ + +compact-short unit-width-full-name sign-accounting-except-zero + es-MX + 0 + +92 k + -0.22 + zh-TW + 0 + +9.2萬 + -0.22 + bn-BD + ০ + +৯২ হা + -০.২২ + +scientific/+ee/sign-always unit-width-narrow sign-accounting-except-zero + es-MX + 0E+00 + +9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + +9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + +৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +scientific/+ee/sign-always unit-width-full-name sign-accounting-except-zero + es-MX + 0E+00 + +9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + +9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + +৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short unit-width-narrow decimal-always + es-MX + 0. + 92. k + -0.22 + zh-TW + 0. + 9.2萬 + -0.22 + bn-BD + ০. + ৯২. হা + -০.২২ + +compact-short unit-width-full-name decimal-always + es-MX + 0. + 92. k + -0.22 + zh-TW + 0. + 9.2萬 + -0.22 + bn-BD + ০. + ৯২. হা + -০.২২ + +scientific/+ee/sign-always unit-width-narrow decimal-always + es-MX + 0.E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0.E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০.E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +scientific/+ee/sign-always unit-width-full-name decimal-always + es-MX + 0.E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0.E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০.E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short precision-integer rounding-mode-floor + es-MX + 0 + 91 k + -1 + zh-TW + 0 + 9萬 + -1 + bn-BD + ০ + ৯১ হা + -১ + +compact-short .000 rounding-mode-floor + es-MX + 0.000 + 91.827 k + -0.223 + zh-TW + 0.000 + 9.182萬 + -0.223 + bn-BD + ০.০০০ + ৯১.৮২৭ হা + -০.২২৩ + +compact-short .##/@@@+ rounding-mode-floor + es-MX + 0 + 91.82 k + -0.223 + zh-TW + 0 + 9.18萬 + -0.223 + bn-BD + ০ + ৯১.৮২ হা + -০.২২৩ + +compact-short @@ rounding-mode-floor + es-MX + 0.0 + 91 k + -0.23 + zh-TW + 0.0 + 9.1萬 + -0.23 + bn-BD + ০.০ + ৯১ হা + -০.২৩ + +scientific/+ee/sign-always precision-integer rounding-mode-floor + es-MX + 0E+00 + 9E+04 + -3E-01 + zh-TW + 0E+00 + 9E+04 + -3E-01 + bn-BD + ০E+০০ + ৯E+০৪ + -৩E-০১ + +scientific/+ee/sign-always .000 rounding-mode-floor + es-MX + 0.000E+00 + 9.182E+04 + -2.223E-01 + zh-TW + 0.000E+00 + 9.182E+04 + -2.223E-01 + bn-BD + ০.০০০E+০০ + ৯.১৮২E+০৪ + -২.২২৩E-০১ + +scientific/+ee/sign-always .##/@@@+ rounding-mode-floor + es-MX + 0E+00 + 9.18E+04 + -2.23E-01 + zh-TW + 0E+00 + 9.18E+04 + -2.23E-01 + bn-BD + ০E+০০ + ৯.১৮E+০৪ + -২.২৩E-০১ + +scientific/+ee/sign-always @@ rounding-mode-floor + es-MX + 0.0E+00 + 9.1E+04 + -2.3E-01 + zh-TW + 0.0E+00 + 9.1E+04 + -2.3E-01 + bn-BD + ০.০E+০০ + ৯.১E+০৪ + -২.৩E-০১ + +compact-short precision-integer integer-width/##00 + es-MX + 00 + 92 k + -00 + zh-TW + 00 + 09萬 + -00 + bn-BD + ০০ + ৯২ হা + -০০ + +compact-short .000 integer-width/##00 + es-MX + 00.000 + 91.827 k + -00.222 + zh-TW + 00.000 + 09.183萬 + -00.222 + bn-BD + ০০.০০০ + ৯১.৮২৭ হা + -০০.২২২ + +compact-short .##/@@@+ integer-width/##00 + es-MX + 00 + 91.83 k + -00.222 + zh-TW + 00 + 09.18萬 + -00.222 + bn-BD + ০০ + ৯১.৮৩ হা + -০০.২২২ + +compact-short @@ integer-width/##00 + es-MX + 00.0 + 92 k + -00.22 + zh-TW + 00.0 + 09.2萬 + -00.22 + bn-BD + ০০.০ + ৯২ হা + -০০.২২ + +scientific/+ee/sign-always precision-integer integer-width/##00 + es-MX + 00E+00 + 09E+04 + -02E-01 + zh-TW + 00E+00 + 09E+04 + -02E-01 + bn-BD + ০০E+০০ + ০৯E+০৪ + -০২E-০১ + +scientific/+ee/sign-always .000 integer-width/##00 + es-MX + 00.000E+00 + 09.183E+04 + -02.222E-01 + zh-TW + 00.000E+00 + 09.183E+04 + -02.222E-01 + bn-BD + ০০.০০০E+০০ + ০৯.১৮৩E+০৪ + -০২.২২২E-০১ + +scientific/+ee/sign-always .##/@@@+ integer-width/##00 + es-MX + 00E+00 + 09.18E+04 + -02.22E-01 + zh-TW + 00E+00 + 09.18E+04 + -02.22E-01 + bn-BD + ০০E+০০ + ০৯.১৮E+০৪ + -০২.২২E-০১ + +scientific/+ee/sign-always @@ integer-width/##00 + es-MX + 00.0E+00 + 09.2E+04 + -02.2E-01 + zh-TW + 00.0E+00 + 09.2E+04 + -02.2E-01 + bn-BD + ০০.০E+০০ + ০৯.২E+০৪ + -০২.২E-০১ + +compact-short precision-integer scale/0.5 + es-MX + 0 + 46 k + -0 + zh-TW + 0 + 5萬 + -0 + bn-BD + ০ + ৪৬ হা + -০ + +compact-short .000 scale/0.5 + es-MX + 0.000 + 45.914 k + -0.111 + zh-TW + 0.000 + 4.591萬 + -0.111 + bn-BD + ০.০০০ + ৪৫.৯১৪ হা + -০.১১১ + +compact-short .##/@@@+ scale/0.5 + es-MX + 0 + 45.91 k + -0.111 + zh-TW + 0 + 4.59萬 + -0.111 + bn-BD + ০ + ৪৫.৯১ হা + -০.১১১ + +compact-short @@ scale/0.5 + es-MX + 0.0 + 46 k + -0.11 + zh-TW + 0.0 + 4.6萬 + -0.11 + bn-BD + ০.০ + ৪৬ হা + -০.১১ + +scientific/+ee/sign-always precision-integer scale/0.5 + es-MX + 0E+00 + 5E+04 + -1E-01 + zh-TW + 0E+00 + 5E+04 + -1E-01 + bn-BD + ০E+০০ + ৫E+০৪ + -১E-০১ + +scientific/+ee/sign-always .000 scale/0.5 + es-MX + 0.000E+00 + 4.591E+04 + -1.111E-01 + zh-TW + 0.000E+00 + 4.591E+04 + -1.111E-01 + bn-BD + ০.০০০E+০০ + ৪.৫৯১E+০৪ + -১.১১১E-০১ + +scientific/+ee/sign-always .##/@@@+ scale/0.5 + es-MX + 0E+00 + 4.59E+04 + -1.11E-01 + zh-TW + 0E+00 + 4.59E+04 + -1.11E-01 + bn-BD + ০E+০০ + ৪.৫৯E+০৪ + -১.১১E-০১ + +scientific/+ee/sign-always @@ scale/0.5 + es-MX + 0.0E+00 + 4.6E+04 + -1.1E-01 + zh-TW + 0.0E+00 + 4.6E+04 + -1.1E-01 + bn-BD + ০.০E+০০ + ৪.৬E+০৪ + -১.১E-০১ + +compact-short precision-integer group-on-aligned + es-MX + 0 + 92 k + -0 + zh-TW + 0 + 9萬 + -0 + bn-BD + ০ + ৯২ হা + -০ + +compact-short .000 group-on-aligned + es-MX + 0.000 + 91.827 k + -0.222 + zh-TW + 0.000 + 9.183萬 + -0.222 + bn-BD + ০.০০০ + ৯১.৮২৭ হা + -০.২২২ + +compact-short .##/@@@+ group-on-aligned + es-MX + 0 + 91.83 k + -0.222 + zh-TW + 0 + 9.18萬 + -0.222 + bn-BD + ০ + ৯১.৮৩ হা + -০.২২২ + +compact-short @@ group-on-aligned + es-MX + 0.0 + 92 k + -0.22 + zh-TW + 0.0 + 9.2萬 + -0.22 + bn-BD + ০.০ + ৯২ হা + -০.২২ + +scientific/+ee/sign-always precision-integer group-on-aligned + es-MX + 0E+00 + 9E+04 + -2E-01 + zh-TW + 0E+00 + 9E+04 + -2E-01 + bn-BD + ০E+০০ + ৯E+০৪ + -২E-০১ + +scientific/+ee/sign-always .000 group-on-aligned + es-MX + 0.000E+00 + 9.183E+04 + -2.222E-01 + zh-TW + 0.000E+00 + 9.183E+04 + -2.222E-01 + bn-BD + ০.০০০E+০০ + ৯.১৮৩E+০৪ + -২.২২২E-০১ + +scientific/+ee/sign-always .##/@@@+ group-on-aligned + es-MX + 0E+00 + 9.18E+04 + -2.22E-01 + zh-TW + 0E+00 + 9.18E+04 + -2.22E-01 + bn-BD + ০E+০০ + ৯.১৮E+০৪ + -২.২২E-০১ + +scientific/+ee/sign-always @@ group-on-aligned + es-MX + 0.0E+00 + 9.2E+04 + -2.2E-01 + zh-TW + 0.0E+00 + 9.2E+04 + -2.2E-01 + bn-BD + ০.০E+০০ + ৯.২E+০৪ + -২.২E-০১ + +compact-short precision-integer latin + es-MX + 0 + 92 k + -0 + zh-TW + 0 + 9萬 + -0 + bn-BD + 0 + 92 হা + -0 + +compact-short .000 latin + es-MX + 0.000 + 91.827 k + -0.222 + zh-TW + 0.000 + 9.183萬 + -0.222 + bn-BD + 0.000 + 91.827 হা + -0.222 + +compact-short .##/@@@+ latin + es-MX + 0 + 91.83 k + -0.222 + zh-TW + 0 + 9.18萬 + -0.222 + bn-BD + 0 + 91.83 হা + -0.222 + +compact-short @@ latin + es-MX + 0.0 + 92 k + -0.22 + zh-TW + 0.0 + 9.2萬 + -0.22 + bn-BD + 0.0 + 92 হা + -0.22 + +scientific/+ee/sign-always precision-integer latin + es-MX + 0E+00 + 9E+04 + -2E-01 + zh-TW + 0E+00 + 9E+04 + -2E-01 + bn-BD + 0E+00 + 9E+04 + -2E-01 + +scientific/+ee/sign-always .000 latin + es-MX + 0.000E+00 + 9.183E+04 + -2.222E-01 + zh-TW + 0.000E+00 + 9.183E+04 + -2.222E-01 + bn-BD + 0.000E+00 + 9.183E+04 + -2.222E-01 + +scientific/+ee/sign-always .##/@@@+ latin + es-MX + 0E+00 + 9.18E+04 + -2.22E-01 + zh-TW + 0E+00 + 9.18E+04 + -2.22E-01 + bn-BD + 0E+00 + 9.18E+04 + -2.22E-01 + +scientific/+ee/sign-always @@ latin + es-MX + 0.0E+00 + 9.2E+04 + -2.2E-01 + zh-TW + 0.0E+00 + 9.2E+04 + -2.2E-01 + bn-BD + 0.0E+00 + 9.2E+04 + -2.2E-01 + +compact-short precision-integer sign-accounting-except-zero + es-MX + 0 + +92 k + -0 + zh-TW + 0 + +9萬 + -0 + bn-BD + ০ + +৯২ হা + -০ + +compact-short .000 sign-accounting-except-zero + es-MX + 0.000 + +91.827 k + -0.222 + zh-TW + 0.000 + +9.183萬 + -0.222 + bn-BD + ০.০০০ + +৯১.৮২৭ হা + -০.২২২ + +compact-short .##/@@@+ sign-accounting-except-zero + es-MX + 0 + +91.83 k + -0.222 + zh-TW + 0 + +9.18萬 + -0.222 + bn-BD + ০ + +৯১.৮৩ হা + -০.২২২ + +compact-short @@ sign-accounting-except-zero + es-MX + 0.0 + +92 k + -0.22 + zh-TW + 0.0 + +9.2萬 + -0.22 + bn-BD + ০.০ + +৯২ হা + -০.২২ + +scientific/+ee/sign-always precision-integer sign-accounting-except-zero + es-MX + 0E+00 + +9E+04 + -2E-01 + zh-TW + 0E+00 + +9E+04 + -2E-01 + bn-BD + ০E+০০ + +৯E+০৪ + -২E-০১ + +scientific/+ee/sign-always .000 sign-accounting-except-zero + es-MX + 0.000E+00 + +9.183E+04 + -2.222E-01 + zh-TW + 0.000E+00 + +9.183E+04 + -2.222E-01 + bn-BD + ০.০০০E+০০ + +৯.১৮৩E+০৪ + -২.২২২E-০১ + +scientific/+ee/sign-always .##/@@@+ sign-accounting-except-zero + es-MX + 0E+00 + +9.18E+04 + -2.22E-01 + zh-TW + 0E+00 + +9.18E+04 + -2.22E-01 + bn-BD + ০E+০০ + +৯.১৮E+০৪ + -২.২২E-০১ + +scientific/+ee/sign-always @@ sign-accounting-except-zero + es-MX + 0.0E+00 + +9.2E+04 + -2.2E-01 + zh-TW + 0.0E+00 + +9.2E+04 + -2.2E-01 + bn-BD + ০.০E+০০ + +৯.২E+০৪ + -২.২E-০১ + +compact-short precision-integer decimal-always + es-MX + 0. + 92. k + -0. + zh-TW + 0. + 9.萬 + -0. + bn-BD + ০. + ৯২. হা + -০. + +compact-short .000 decimal-always + es-MX + 0.000 + 91.827 k + -0.222 + zh-TW + 0.000 + 9.183萬 + -0.222 + bn-BD + ০.০০০ + ৯১.৮২৭ হা + -০.২২২ + +compact-short .##/@@@+ decimal-always + es-MX + 0. + 91.83 k + -0.222 + zh-TW + 0. + 9.18萬 + -0.222 + bn-BD + ০. + ৯১.৮৩ হা + -০.২২২ + +compact-short @@ decimal-always + es-MX + 0.0 + 92. k + -0.22 + zh-TW + 0.0 + 9.2萬 + -0.22 + bn-BD + ০.০ + ৯২. হা + -০.২২ + +scientific/+ee/sign-always precision-integer decimal-always + es-MX + 0.E+00 + 9.E+04 + -2.E-01 + zh-TW + 0.E+00 + 9.E+04 + -2.E-01 + bn-BD + ০.E+০০ + ৯.E+০৪ + -২.E-০১ + +scientific/+ee/sign-always .000 decimal-always + es-MX + 0.000E+00 + 9.183E+04 + -2.222E-01 + zh-TW + 0.000E+00 + 9.183E+04 + -2.222E-01 + bn-BD + ০.০০০E+০০ + ৯.১৮৩E+০৪ + -২.২২২E-০১ + +scientific/+ee/sign-always .##/@@@+ decimal-always + es-MX + 0.E+00 + 9.18E+04 + -2.22E-01 + zh-TW + 0.E+00 + 9.18E+04 + -2.22E-01 + bn-BD + ০.E+০০ + ৯.১৮E+০৪ + -২.২২E-০১ + +scientific/+ee/sign-always @@ decimal-always + es-MX + 0.0E+00 + 9.2E+04 + -2.2E-01 + zh-TW + 0.0E+00 + 9.2E+04 + -2.2E-01 + bn-BD + ০.০E+০০ + ৯.২E+০৪ + -২.২E-০১ + +compact-short rounding-mode-floor integer-width/##00 + es-MX + 00 + 91 k + -00.23 + zh-TW + 00 + 09.1萬 + -00.23 + bn-BD + ০০ + ৯১ হা + -০০.২৩ + +scientific/+ee/sign-always rounding-mode-floor integer-width/##00 + es-MX + 00E+00 + 09.182736E+04 + -02.2222E-01 + zh-TW + 00E+00 + 09.182736E+04 + -02.2222E-01 + bn-BD + ০০E+০০ + ০৯.১৮২৭৩৬E+০৪ + -০২.২২২২E-০১ + +compact-short rounding-mode-floor scale/0.5 + es-MX + 0 + 45 k + -0.12 + zh-TW + 0 + 4.5萬 + -0.12 + bn-BD + ০ + ৪৫ হা + -০.১২ + +scientific/+ee/sign-always rounding-mode-floor scale/0.5 + es-MX + 0E+00 + 4.591368E+04 + -1.1111E-01 + zh-TW + 0E+00 + 4.591368E+04 + -1.1111E-01 + bn-BD + ০E+০০ + ৪.৫৯১৩৬৮E+০৪ + -১.১১১১E-০১ + +compact-short rounding-mode-floor group-on-aligned + es-MX + 0 + 91 k + -0.23 + zh-TW + 0 + 9.1萬 + -0.23 + bn-BD + ০ + ৯১ হা + -০.২৩ + +scientific/+ee/sign-always rounding-mode-floor group-on-aligned + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short rounding-mode-floor latin + es-MX + 0 + 91 k + -0.23 + zh-TW + 0 + 9.1萬 + -0.23 + bn-BD + 0 + 91 হা + -0.23 + +scientific/+ee/sign-always rounding-mode-floor latin + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + 0E+00 + 9.182736E+04 + -2.2222E-01 + +compact-short rounding-mode-floor sign-accounting-except-zero + es-MX + 0 + +91 k + -0.23 + zh-TW + 0 + +9.1萬 + -0.23 + bn-BD + ০ + +৯১ হা + -০.২৩ + +scientific/+ee/sign-always rounding-mode-floor sign-accounting-except-zero + es-MX + 0E+00 + +9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + +9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + +৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short rounding-mode-floor decimal-always + es-MX + 0. + 91. k + -0.23 + zh-TW + 0. + 9.1萬 + -0.23 + bn-BD + ০. + ৯১. হা + -০.২৩ + +scientific/+ee/sign-always rounding-mode-floor decimal-always + es-MX + 0.E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0.E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০.E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short integer-width/##00 scale/0.5 + es-MX + 00 + 46 k + -00.11 + zh-TW + 00 + 04.6萬 + -00.11 + bn-BD + ০০ + ৪৬ হা + -০০.১১ + +scientific/+ee/sign-always integer-width/##00 scale/0.5 + es-MX + 00E+00 + 04.591368E+04 + -01.1111E-01 + zh-TW + 00E+00 + 04.591368E+04 + -01.1111E-01 + bn-BD + ০০E+০০ + ০৪.৫৯১৩৬৮E+০৪ + -০১.১১১১E-০১ + +compact-short integer-width/##00 group-on-aligned + es-MX + 00 + 92 k + -00.22 + zh-TW + 00 + 09.2萬 + -00.22 + bn-BD + ০০ + ৯২ হা + -০০.২২ + +scientific/+ee/sign-always integer-width/##00 group-on-aligned + es-MX + 00E+00 + 09.182736E+04 + -02.2222E-01 + zh-TW + 00E+00 + 09.182736E+04 + -02.2222E-01 + bn-BD + ০০E+০০ + ০৯.১৮২৭৩৬E+০৪ + -০২.২২২২E-০১ + +compact-short integer-width/##00 latin + es-MX + 00 + 92 k + -00.22 + zh-TW + 00 + 09.2萬 + -00.22 + bn-BD + 00 + 92 হা + -00.22 + +scientific/+ee/sign-always integer-width/##00 latin + es-MX + 00E+00 + 09.182736E+04 + -02.2222E-01 + zh-TW + 00E+00 + 09.182736E+04 + -02.2222E-01 + bn-BD + 00E+00 + 09.182736E+04 + -02.2222E-01 + +compact-short integer-width/##00 sign-accounting-except-zero + es-MX + 00 + +92 k + -00.22 + zh-TW + 00 + +09.2萬 + -00.22 + bn-BD + ০০ + +৯২ হা + -০০.২২ + +scientific/+ee/sign-always integer-width/##00 sign-accounting-except-zero + es-MX + 00E+00 + +09.182736E+04 + -02.2222E-01 + zh-TW + 00E+00 + +09.182736E+04 + -02.2222E-01 + bn-BD + ০০E+০০ + +০৯.১৮২৭৩৬E+০৪ + -০২.২২২২E-০১ + +compact-short integer-width/##00 decimal-always + es-MX + 00. + 92. k + -00.22 + zh-TW + 00. + 09.2萬 + -00.22 + bn-BD + ০০. + ৯২. হা + -০০.২২ + +scientific/+ee/sign-always integer-width/##00 decimal-always + es-MX + 00.E+00 + 09.182736E+04 + -02.2222E-01 + zh-TW + 00.E+00 + 09.182736E+04 + -02.2222E-01 + bn-BD + ০০.E+০০ + ০৯.১৮২৭৩৬E+০৪ + -০২.২২২২E-০১ + +compact-short scale/0.5 group-on-aligned + es-MX + 0 + 46 k + -0.11 + zh-TW + 0 + 4.6萬 + -0.11 + bn-BD + ০ + ৪৬ হা + -০.১১ + +scientific/+ee/sign-always scale/0.5 group-on-aligned + es-MX + 0E+00 + 4.591368E+04 + -1.1111E-01 + zh-TW + 0E+00 + 4.591368E+04 + -1.1111E-01 + bn-BD + ০E+০০ + ৪.৫৯১৩৬৮E+০৪ + -১.১১১১E-০১ + +compact-short scale/0.5 latin + es-MX + 0 + 46 k + -0.11 + zh-TW + 0 + 4.6萬 + -0.11 + bn-BD + 0 + 46 হা + -0.11 + +scientific/+ee/sign-always scale/0.5 latin + es-MX + 0E+00 + 4.591368E+04 + -1.1111E-01 + zh-TW + 0E+00 + 4.591368E+04 + -1.1111E-01 + bn-BD + 0E+00 + 4.591368E+04 + -1.1111E-01 + +compact-short scale/0.5 sign-accounting-except-zero + es-MX + 0 + +46 k + -0.11 + zh-TW + 0 + +4.6萬 + -0.11 + bn-BD + ০ + +৪৬ হা + -০.১১ + +scientific/+ee/sign-always scale/0.5 sign-accounting-except-zero + es-MX + 0E+00 + +4.591368E+04 + -1.1111E-01 + zh-TW + 0E+00 + +4.591368E+04 + -1.1111E-01 + bn-BD + ০E+০০ + +৪.৫৯১৩৬৮E+০৪ + -১.১১১১E-০১ + +compact-short scale/0.5 decimal-always + es-MX + 0. + 46. k + -0.11 + zh-TW + 0. + 4.6萬 + -0.11 + bn-BD + ০. + ৪৬. হা + -০.১১ + +scientific/+ee/sign-always scale/0.5 decimal-always + es-MX + 0.E+00 + 4.591368E+04 + -1.1111E-01 + zh-TW + 0.E+00 + 4.591368E+04 + -1.1111E-01 + bn-BD + ০.E+০০ + ৪.৫৯১৩৬৮E+০৪ + -১.১১১১E-০১ + +compact-short group-on-aligned latin + es-MX + 0 + 92 k + -0.22 + zh-TW + 0 + 9.2萬 + -0.22 + bn-BD + 0 + 92 হা + -0.22 + +scientific/+ee/sign-always group-on-aligned latin + es-MX + 0E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + 0E+00 + 9.182736E+04 + -2.2222E-01 + +compact-short group-on-aligned sign-accounting-except-zero + es-MX + 0 + +92 k + -0.22 + zh-TW + 0 + +9.2萬 + -0.22 + bn-BD + ০ + +৯২ হা + -০.২২ + +scientific/+ee/sign-always group-on-aligned sign-accounting-except-zero + es-MX + 0E+00 + +9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + +9.182736E+04 + -2.2222E-01 + bn-BD + ০E+০০ + +৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short group-on-aligned decimal-always + es-MX + 0. + 92. k + -0.22 + zh-TW + 0. + 9.2萬 + -0.22 + bn-BD + ০. + ৯২. হা + -০.২২ + +scientific/+ee/sign-always group-on-aligned decimal-always + es-MX + 0.E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0.E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + ০.E+০০ + ৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +compact-short latin sign-accounting-except-zero + es-MX + 0 + +92 k + -0.22 + zh-TW + 0 + +9.2萬 + -0.22 + bn-BD + 0 + +92 হা + -0.22 + +scientific/+ee/sign-always latin sign-accounting-except-zero + es-MX + 0E+00 + +9.182736E+04 + -2.2222E-01 + zh-TW + 0E+00 + +9.182736E+04 + -2.2222E-01 + bn-BD + 0E+00 + +9.182736E+04 + -2.2222E-01 + +compact-short latin decimal-always + es-MX + 0. + 92. k + -0.22 + zh-TW + 0. + 9.2萬 + -0.22 + bn-BD + 0. + 92. হা + -0.22 + +scientific/+ee/sign-always latin decimal-always + es-MX + 0.E+00 + 9.182736E+04 + -2.2222E-01 + zh-TW + 0.E+00 + 9.182736E+04 + -2.2222E-01 + bn-BD + 0.E+00 + 9.182736E+04 + -2.2222E-01 + +compact-short sign-accounting-except-zero decimal-always + es-MX + 0. + +92. k + -0.22 + zh-TW + 0. + +9.2萬 + -0.22 + bn-BD + ০. + +৯২. হা + -০.২২ + +scientific/+ee/sign-always sign-accounting-except-zero decimal-always + es-MX + 0.E+00 + +9.182736E+04 + -2.2222E-01 + zh-TW + 0.E+00 + +9.182736E+04 + -2.2222E-01 + bn-BD + ০.E+০০ + +৯.১৮২৭৩৬E+০৪ + -২.২২২২E-০১ + +percent unit-width-narrow precision-integer + es-MX + 0 % + 91,827 % + -0 % + zh-TW + 0% + 91,827% + -0% + bn-BD + ০% + ৯১,৮২৭% + -০% + +percent unit-width-narrow .000 + es-MX + 0.000 % + 91,827.364 % + -0.222 % + zh-TW + 0.000% + 91,827.364% + -0.222% + bn-BD + ০.০০০% + ৯১,৮২৭.৩৬৪% + -০.২২২% + +percent unit-width-narrow .##/@@@+ + es-MX + 0 % + 91,827.36 % + -0.222 % + zh-TW + 0% + 91,827.36% + -0.222% + bn-BD + ০% + ৯১,৮২৭.৩৬% + -০.২২২% + +percent unit-width-narrow @@ + es-MX + 0.0 % + 92,000 % + -0.22 % + zh-TW + 0.0% + 92,000% + -0.22% + bn-BD + ০.০% + ৯২,০০০% + -০.২২% + +percent unit-width-full-name precision-integer + es-MX + 0 % + 91,827 % + -0 % + zh-TW + 0% + 91,827% + -0% + bn-BD + ০% + ৯১,৮২৭% + -০% + +percent unit-width-full-name .000 + es-MX + 0.000 % + 91,827.364 % + -0.222 % + zh-TW + 0.000% + 91,827.364% + -0.222% + bn-BD + ০.০০০% + ৯১,৮২৭.৩৬৪% + -০.২২২% + +percent unit-width-full-name .##/@@@+ + es-MX + 0 % + 91,827.36 % + -0.222 % + zh-TW + 0% + 91,827.36% + -0.222% + bn-BD + ০% + ৯১,৮২৭.৩৬% + -০.২২২% + +percent unit-width-full-name @@ + es-MX + 0.0 % + 92,000 % + -0.22 % + zh-TW + 0.0% + 92,000% + -0.22% + bn-BD + ০.০% + ৯২,০০০% + -০.২২% + +currency/EUR unit-width-narrow precision-integer + es-MX + €0 + €91,827 + -€0 + zh-TW + €0 + €91,827 + -€0 + bn-BD + ০€ + ৯১,৮২৭€ + -০€ + +currency/EUR unit-width-narrow .000 + es-MX + €0.000 + €91,827.364 + -€0.222 + zh-TW + €0.000 + €91,827.364 + -€0.222 + bn-BD + ০.০০০€ + ৯১,৮২৭.৩৬৪€ + -০.২২২€ + +currency/EUR unit-width-narrow .##/@@@+ + es-MX + €0 + €91,827.36 + -€0.222 + zh-TW + €0 + €91,827.36 + -€0.222 + bn-BD + ০€ + ৯১,৮২৭.৩৬€ + -০.২২২€ + +currency/EUR unit-width-narrow @@ + es-MX + €0.0 + €92,000 + -€0.22 + zh-TW + €0.0 + €92,000 + -€0.22 + bn-BD + ০.০€ + ৯২,০০০€ + -০.২২€ + +currency/EUR unit-width-full-name precision-integer + es-MX + 0 euros + 91,827 euros + -0 euros + zh-TW + 0 歐元 + 91,827 歐元 + -0 歐元 + bn-BD + ০ ইউরো + ৯১,৮২৭ ইউরো + -০ ইউরো + +currency/EUR unit-width-full-name .000 + es-MX + 0.000 euros + 91,827.364 euros + -0.222 euros + zh-TW + 0.000 歐元 + 91,827.364 歐元 + -0.222 歐元 + bn-BD + ০.০০০ ইউরো + ৯১,৮২৭.৩৬৪ ইউরো + -০.২২২ ইউরো + +currency/EUR unit-width-full-name .##/@@@+ + es-MX + 0 euros + 91,827.36 euros + -0.222 euros + zh-TW + 0 歐元 + 91,827.36 歐元 + -0.222 歐元 + bn-BD + ০ ইউরো + ৯১,৮২৭.৩৬ ইউরো + -০.২২২ ইউরো + +currency/EUR unit-width-full-name @@ + es-MX + 0.0 euros + 92,000 euros + -0.22 euros + zh-TW + 0.0 歐元 + 92,000 歐元 + -0.22 歐元 + bn-BD + ০.০ ইউরো + ৯২,০০০ ইউরো + -০.২২ ইউরো + +measure-unit/length-furlong unit-width-narrow precision-integer + es-MX + 0 fur + 91,827 fur + -0 fur + zh-TW + 0化朗 + 91,827化朗 + -0化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭ ফার্লং + -০ ফার্লং + +measure-unit/length-furlong unit-width-narrow .000 + es-MX + 0.000 fur + 91,827.364 fur + -0.222 fur + zh-TW + 0.000化朗 + 91,827.364化朗 + -0.222化朗 + bn-BD + ০.০০০ ফার্লং + ৯১,৮২৭.৩৬৪ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong unit-width-narrow .##/@@@+ + es-MX + 0 fur + 91,827.36 fur + -0.222 fur + zh-TW + 0化朗 + 91,827.36化朗 + -0.222化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong unit-width-narrow @@ + es-MX + 0.0 fur + 92,000 fur + -0.22 fur + zh-TW + 0.0化朗 + 92,000化朗 + -0.22化朗 + bn-BD + ০.০ ফার্লং + ৯২,০০০ ফার্লং + -০.২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name precision-integer + es-MX + 0 fur + 91,827 fur + -0 fur + zh-TW + 0 化朗 + 91,827 化朗 + -0 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭ ফার্লং + -০ ফার্লং + +measure-unit/length-furlong unit-width-full-name .000 + es-MX + 0.000 fur + 91,827.364 fur + -0.222 fur + zh-TW + 0.000 化朗 + 91,827.364 化朗 + -0.222 化朗 + bn-BD + ০.০০০ ফার্লং + ৯১,৮২৭.৩৬৪ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name .##/@@@+ + es-MX + 0 fur + 91,827.36 fur + -0.222 fur + zh-TW + 0 化朗 + 91,827.36 化朗 + -0.222 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name @@ + es-MX + 0.0 fur + 92,000 fur + -0.22 fur + zh-TW + 0.0 化朗 + 92,000 化朗 + -0.22 化朗 + bn-BD + ০.০ ফার্লং + ৯২,০০০ ফার্লং + -০.২২ ফার্লং + +percent unit-width-narrow rounding-mode-floor + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + ০% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +percent unit-width-full-name rounding-mode-floor + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + ০% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR unit-width-narrow rounding-mode-floor + es-MX + €0.00 + €91,827.36 + -€0.23 + zh-TW + €0.00 + €91,827.36 + -€0.23 + bn-BD + ০.০০€ + ৯১,৮২৭.৩৬€ + -০.২৩€ + +currency/EUR unit-width-full-name rounding-mode-floor + es-MX + 0.00 euros + 91,827.36 euros + -0.23 euros + zh-TW + 0.00 歐元 + 91,827.36 歐元 + -0.23 歐元 + bn-BD + ০.০০ ইউরো + ৯১,৮২৭.৩৬ ইউরো + -০.২৩ ইউরো + +measure-unit/length-furlong unit-width-narrow rounding-mode-floor + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0化朗 + 91,827.3645化朗 + -0.22222化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name rounding-mode-floor + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent unit-width-narrow integer-width/##00 + es-MX + 00 % + 1827.3645 % + -00.22222 % + zh-TW + 00% + 1,827.3645% + -00.22222% + bn-BD + ০০% + ১,৮২৭.৩৬৪৫% + -০০.২২২২২% + +percent unit-width-full-name integer-width/##00 + es-MX + 00 % + 1827.3645 % + -00.22222 % + zh-TW + 00% + 1,827.3645% + -00.22222% + bn-BD + ০০% + ১,৮২৭.৩৬৪৫% + -০০.২২২২২% + +currency/EUR unit-width-narrow integer-width/##00 + es-MX + €00.00 + €1827.36 + -€00.22 + zh-TW + €00.00 + €1,827.36 + -€00.22 + bn-BD + ০০.০০€ + ১,৮২৭.৩৬€ + -০০.২২€ + +currency/EUR unit-width-full-name integer-width/##00 + es-MX + 00.00 euros + 1827.36 euros + -00.22 euros + zh-TW + 00.00 歐元 + 1,827.36 歐元 + -00.22 歐元 + bn-BD + ০০.০০ ইউরো + ১,৮২৭.৩৬ ইউরো + -০০.২২ ইউরো + +measure-unit/length-furlong unit-width-narrow integer-width/##00 + es-MX + 00 fur + 1827.3645 fur + -00.22222 fur + zh-TW + 00化朗 + 1,827.3645化朗 + -00.22222化朗 + bn-BD + ০০ ফার্লং + ১,৮২৭.৩৬৪৫ ফার্লং + -০০.২২২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name integer-width/##00 + es-MX + 00 fur + 1827.3645 fur + -00.22222 fur + zh-TW + 00 化朗 + 1,827.3645 化朗 + -00.22222 化朗 + bn-BD + ০০ ফার্লং + ১,৮২৭.৩৬৪৫ ফার্লং + -০০.২২২২২ ফার্লং + +percent unit-width-narrow scale/0.5 + es-MX + 0 % + 45,913.68225 % + -0.11111 % + zh-TW + 0% + 45,913.68225% + -0.11111% + bn-BD + ০% + ৪৫,৯১৩.৬৮২২৫% + -০.১১১১১% + +percent unit-width-full-name scale/0.5 + es-MX + 0 % + 45,913.68225 % + -0.11111 % + zh-TW + 0% + 45,913.68225% + -0.11111% + bn-BD + ০% + ৪৫,৯১৩.৬৮২২৫% + -০.১১১১১% + +currency/EUR unit-width-narrow scale/0.5 + es-MX + €0.00 + €45,913.68 + -€0.11 + zh-TW + €0.00 + €45,913.68 + -€0.11 + bn-BD + ০.০০€ + ৪৫,৯১৩.৬৮€ + -০.১১€ + +currency/EUR unit-width-full-name scale/0.5 + es-MX + 0.00 euros + 45,913.68 euros + -0.11 euros + zh-TW + 0.00 歐元 + 45,913.68 歐元 + -0.11 歐元 + bn-BD + ০.০০ ইউরো + ৪৫,৯১৩.৬৮ ইউরো + -০.১১ ইউরো + +measure-unit/length-furlong unit-width-narrow scale/0.5 + es-MX + 0 fur + 45,913.68225 fur + -0.11111 fur + zh-TW + 0化朗 + 45,913.68225化朗 + -0.11111化朗 + bn-BD + ০ ফার্লং + ৪৫,৯১৩.৬৮২২৫ ফার্লং + -০.১১১১১ ফার্লং + +measure-unit/length-furlong unit-width-full-name scale/0.5 + es-MX + 0 fur + 45,913.68225 fur + -0.11111 fur + zh-TW + 0 化朗 + 45,913.68225 化朗 + -0.11111 化朗 + bn-BD + ০ ফার্লং + ৪৫,৯১৩.৬৮২২৫ ফার্লং + -০.১১১১১ ফার্লং + +percent unit-width-narrow group-on-aligned + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + ০% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +percent unit-width-full-name group-on-aligned + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + ০% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR unit-width-narrow group-on-aligned + es-MX + €0.00 + €91,827.36 + -€0.22 + zh-TW + €0.00 + €91,827.36 + -€0.22 + bn-BD + ০.০০€ + ৯১,৮২৭.৩৬€ + -০.২২€ + +currency/EUR unit-width-full-name group-on-aligned + es-MX + 0.00 euros + 91,827.36 euros + -0.22 euros + zh-TW + 0.00 歐元 + 91,827.36 歐元 + -0.22 歐元 + bn-BD + ০.০০ ইউরো + ৯১,৮২৭.৩৬ ইউরো + -০.২২ ইউরো + +measure-unit/length-furlong unit-width-narrow group-on-aligned + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0化朗 + 91,827.3645化朗 + -0.22222化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name group-on-aligned + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent unit-width-narrow latin + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + 0% + 91,827.3645% + -0.22222% + +percent unit-width-full-name latin + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + 0% + 91,827.3645% + -0.22222% + +currency/EUR unit-width-narrow latin + es-MX + €0.00 + €91,827.36 + -€0.22 + zh-TW + €0.00 + €91,827.36 + -€0.22 + bn-BD + 0.00€ + 91,827.36€ + -0.22€ + +currency/EUR unit-width-full-name latin + es-MX + 0.00 euros + 91,827.36 euros + -0.22 euros + zh-TW + 0.00 歐元 + 91,827.36 歐元 + -0.22 歐元 + bn-BD + 0.00 ইউরো + 91,827.36 ইউরো + -0.22 ইউরো + +measure-unit/length-furlong unit-width-narrow latin + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0化朗 + 91,827.3645化朗 + -0.22222化朗 + bn-BD + 0 ফার্লং + 91,827.3645 ফার্লং + -0.22222 ফার্লং + +measure-unit/length-furlong unit-width-full-name latin + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + 0 ফার্লং + 91,827.3645 ফার্লং + -0.22222 ফার্লং + +percent unit-width-narrow sign-accounting-except-zero + es-MX + 0 % + +91,827.3645 % + -0.22222 % + zh-TW + 0% + +91,827.3645% + -0.22222% + bn-BD + ০% + +৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +percent unit-width-full-name sign-accounting-except-zero + es-MX + 0 % + +91,827.3645 % + -0.22222 % + zh-TW + 0% + +91,827.3645% + -0.22222% + bn-BD + ০% + +৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR unit-width-narrow sign-accounting-except-zero + es-MX + €0.00 + +€91,827.36 + -€0.22 + zh-TW + €0.00 + +€91,827.36 + (€0.22) + bn-BD + ০.০০€ + +৯১,৮২৭.৩৬€ + (০.২২ €) + +currency/EUR unit-width-full-name sign-accounting-except-zero + es-MX + 0.00 euros + +91,827.36 euros + -0.22 euros + zh-TW + 0.00 歐元 + +91,827.36 歐元 + -0.22 歐元 + bn-BD + ০.০০ ইউরো + +৯১,৮২৭.৩৬ ইউরো + -০.২২ ইউরো + +measure-unit/length-furlong unit-width-narrow sign-accounting-except-zero + es-MX + 0 fur + +91,827.3645 fur + -0.22222 fur + zh-TW + 0化朗 + +91,827.3645化朗 + -0.22222化朗 + bn-BD + ০ ফার্লং + +৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name sign-accounting-except-zero + es-MX + 0 fur + +91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + +91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০ ফার্লং + +৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent unit-width-narrow decimal-always + es-MX + 0. % + 91,827.3645 % + -0.22222 % + zh-TW + 0.% + 91,827.3645% + -0.22222% + bn-BD + ০.% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +percent unit-width-full-name decimal-always + es-MX + 0. % + 91,827.3645 % + -0.22222 % + zh-TW + 0.% + 91,827.3645% + -0.22222% + bn-BD + ০.% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR unit-width-narrow decimal-always + es-MX + €0.00 + €91,827.36 + -€0.22 + zh-TW + €0.00 + €91,827.36 + -€0.22 + bn-BD + ০.০০€ + ৯১,৮২৭.৩৬€ + -০.২২€ + +currency/EUR unit-width-full-name decimal-always + es-MX + 0.00 euros + 91,827.36 euros + -0.22 euros + zh-TW + 0.00 歐元 + 91,827.36 歐元 + -0.22 歐元 + bn-BD + ০.০০ ইউরো + ৯১,৮২৭.৩৬ ইউরো + -০.২২ ইউরো + +measure-unit/length-furlong unit-width-narrow decimal-always + es-MX + 0. fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0.化朗 + 91,827.3645化朗 + -0.22222化朗 + bn-BD + ০. ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +measure-unit/length-furlong unit-width-full-name decimal-always + es-MX + 0. fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0. 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০. ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent precision-integer rounding-mode-floor + es-MX + 0 % + 91,827 % + -1 % + zh-TW + 0% + 91,827% + -1% + bn-BD + ০% + ৯১,৮২৭% + -১% + +percent .000 rounding-mode-floor + es-MX + 0.000 % + 91,827.364 % + -0.223 % + zh-TW + 0.000% + 91,827.364% + -0.223% + bn-BD + ০.০০০% + ৯১,৮২৭.৩৬৪% + -০.২২৩% + +percent .##/@@@+ rounding-mode-floor + es-MX + 0 % + 91,827.36 % + -0.223 % + zh-TW + 0% + 91,827.36% + -0.223% + bn-BD + ০% + ৯১,৮২৭.৩৬% + -০.২২৩% + +percent @@ rounding-mode-floor + es-MX + 0.0 % + 91,000 % + -0.23 % + zh-TW + 0.0% + 91,000% + -0.23% + bn-BD + ০.০% + ৯১,০০০% + -০.২৩% + +currency/EUR precision-integer rounding-mode-floor + es-MX + EUR 0 + EUR 91,827 + -EUR 1 + zh-TW + €0 + €91,827 + -€1 + bn-BD + ০€ + ৯১,৮২৭€ + -১€ + +currency/EUR .000 rounding-mode-floor + es-MX + EUR 0.000 + EUR 91,827.364 + -EUR 0.223 + zh-TW + €0.000 + €91,827.364 + -€0.223 + bn-BD + ০.০০০€ + ৯১,৮২৭.৩৬৪€ + -০.২২৩€ + +currency/EUR .##/@@@+ rounding-mode-floor + es-MX + EUR 0 + EUR 91,827.36 + -EUR 0.223 + zh-TW + €0 + €91,827.36 + -€0.223 + bn-BD + ০€ + ৯১,৮২৭.৩৬€ + -০.২২৩€ + +currency/EUR @@ rounding-mode-floor + es-MX + EUR 0.0 + EUR 91,000 + -EUR 0.23 + zh-TW + €0.0 + €91,000 + -€0.23 + bn-BD + ০.০€ + ৯১,০০০€ + -০.২৩€ + +measure-unit/length-furlong precision-integer rounding-mode-floor + es-MX + 0 fur + 91,827 fur + -1 fur + zh-TW + 0 化朗 + 91,827 化朗 + -1 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭ ফার্লং + -১ ফার্লং + +measure-unit/length-furlong .000 rounding-mode-floor + es-MX + 0.000 fur + 91,827.364 fur + -0.223 fur + zh-TW + 0.000 化朗 + 91,827.364 化朗 + -0.223 化朗 + bn-BD + ০.০০০ ফার্লং + ৯১,৮২৭.৩৬৪ ফার্লং + -০.২২৩ ফার্লং + +measure-unit/length-furlong .##/@@@+ rounding-mode-floor + es-MX + 0 fur + 91,827.36 fur + -0.223 fur + zh-TW + 0 化朗 + 91,827.36 化朗 + -0.223 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬ ফার্লং + -০.২২৩ ফার্লং + +measure-unit/length-furlong @@ rounding-mode-floor + es-MX + 0.0 fur + 91,000 fur + -0.23 fur + zh-TW + 0.0 化朗 + 91,000 化朗 + -0.23 化朗 + bn-BD + ০.০ ফার্লং + ৯১,০০০ ফার্লং + -০.২৩ ফার্লং + +percent precision-integer integer-width/##00 + es-MX + 00 % + 1827 % + -00 % + zh-TW + 00% + 1,827% + -00% + bn-BD + ০০% + ১,৮২৭% + -০০% + +percent .000 integer-width/##00 + es-MX + 00.000 % + 1827.364 % + -00.222 % + zh-TW + 00.000% + 1,827.364% + -00.222% + bn-BD + ০০.০০০% + ১,৮২৭.৩৬৪% + -০০.২২২% + +percent .##/@@@+ integer-width/##00 + es-MX + 00 % + 1827.36 % + -00.222 % + zh-TW + 00% + 1,827.36% + -00.222% + bn-BD + ০০% + ১,৮২৭.৩৬% + -০০.২২২% + +percent @@ integer-width/##00 + es-MX + 00.0 % + 2000 % + -00.22 % + zh-TW + 00.0% + 2,000% + -00.22% + bn-BD + ০০.০% + ২,০০০% + -০০.২২% + +currency/EUR precision-integer integer-width/##00 + es-MX + EUR 00 + EUR 1827 + -EUR 00 + zh-TW + €00 + €1,827 + -€00 + bn-BD + ০০€ + ১,৮২৭€ + -০০€ + +currency/EUR .000 integer-width/##00 + es-MX + EUR 00.000 + EUR 1827.364 + -EUR 00.222 + zh-TW + €00.000 + €1,827.364 + -€00.222 + bn-BD + ০০.০০০€ + ১,৮২৭.৩৬৪€ + -০০.২২২€ + +currency/EUR .##/@@@+ integer-width/##00 + es-MX + EUR 00 + EUR 1827.36 + -EUR 00.222 + zh-TW + €00 + €1,827.36 + -€00.222 + bn-BD + ০০€ + ১,৮২৭.৩৬€ + -০০.২২২€ + +currency/EUR @@ integer-width/##00 + es-MX + EUR 00.0 + EUR 2000 + -EUR 00.22 + zh-TW + €00.0 + €2,000 + -€00.22 + bn-BD + ০০.০€ + ২,০০০€ + -০০.২২€ + +measure-unit/length-furlong precision-integer integer-width/##00 + es-MX + 00 fur + 1827 fur + -00 fur + zh-TW + 00 化朗 + 1,827 化朗 + -00 化朗 + bn-BD + ০০ ফার্লং + ১,৮২৭ ফার্লং + -০০ ফার্লং + +measure-unit/length-furlong .000 integer-width/##00 + es-MX + 00.000 fur + 1827.364 fur + -00.222 fur + zh-TW + 00.000 化朗 + 1,827.364 化朗 + -00.222 化朗 + bn-BD + ০০.০০০ ফার্লং + ১,৮২৭.৩৬৪ ফার্লং + -০০.২২২ ফার্লং + +measure-unit/length-furlong .##/@@@+ integer-width/##00 + es-MX + 00 fur + 1827.36 fur + -00.222 fur + zh-TW + 00 化朗 + 1,827.36 化朗 + -00.222 化朗 + bn-BD + ০০ ফার্লং + ১,৮২৭.৩৬ ফার্লং + -০০.২২২ ফার্লং + +measure-unit/length-furlong @@ integer-width/##00 + es-MX + 00.0 fur + 2000 fur + -00.22 fur + zh-TW + 00.0 化朗 + 2,000 化朗 + -00.22 化朗 + bn-BD + ০০.০ ফার্লং + ২,০০০ ফার্লং + -০০.২২ ফার্লং + +percent precision-integer scale/0.5 + es-MX + 0 % + 45,914 % + -0 % + zh-TW + 0% + 45,914% + -0% + bn-BD + ০% + ৪৫,৯১৪% + -০% + +percent .000 scale/0.5 + es-MX + 0.000 % + 45,913.682 % + -0.111 % + zh-TW + 0.000% + 45,913.682% + -0.111% + bn-BD + ০.০০০% + ৪৫,৯১৩.৬৮২% + -০.১১১% + +percent .##/@@@+ scale/0.5 + es-MX + 0 % + 45,913.68 % + -0.111 % + zh-TW + 0% + 45,913.68% + -0.111% + bn-BD + ০% + ৪৫,৯১৩.৬৮% + -০.১১১% + +percent @@ scale/0.5 + es-MX + 0.0 % + 46,000 % + -0.11 % + zh-TW + 0.0% + 46,000% + -0.11% + bn-BD + ০.০% + ৪৬,০০০% + -০.১১% + +currency/EUR precision-integer scale/0.5 + es-MX + EUR 0 + EUR 45,914 + -EUR 0 + zh-TW + €0 + €45,914 + -€0 + bn-BD + ০€ + ৪৫,৯১৪€ + -০€ + +currency/EUR .000 scale/0.5 + es-MX + EUR 0.000 + EUR 45,913.682 + -EUR 0.111 + zh-TW + €0.000 + €45,913.682 + -€0.111 + bn-BD + ০.০০০€ + ৪৫,৯১৩.৬৮২€ + -০.১১১€ + +currency/EUR .##/@@@+ scale/0.5 + es-MX + EUR 0 + EUR 45,913.68 + -EUR 0.111 + zh-TW + €0 + €45,913.68 + -€0.111 + bn-BD + ০€ + ৪৫,৯১৩.৬৮€ + -০.১১১€ + +currency/EUR @@ scale/0.5 + es-MX + EUR 0.0 + EUR 46,000 + -EUR 0.11 + zh-TW + €0.0 + €46,000 + -€0.11 + bn-BD + ০.০€ + ৪৬,০০০€ + -০.১১€ + +measure-unit/length-furlong precision-integer scale/0.5 + es-MX + 0 fur + 45,914 fur + -0 fur + zh-TW + 0 化朗 + 45,914 化朗 + -0 化朗 + bn-BD + ০ ফার্লং + ৪৫,৯১৪ ফার্লং + -০ ফার্লং + +measure-unit/length-furlong .000 scale/0.5 + es-MX + 0.000 fur + 45,913.682 fur + -0.111 fur + zh-TW + 0.000 化朗 + 45,913.682 化朗 + -0.111 化朗 + bn-BD + ০.০০০ ফার্লং + ৪৫,৯১৩.৬৮২ ফার্লং + -০.১১১ ফার্লং + +measure-unit/length-furlong .##/@@@+ scale/0.5 + es-MX + 0 fur + 45,913.68 fur + -0.111 fur + zh-TW + 0 化朗 + 45,913.68 化朗 + -0.111 化朗 + bn-BD + ০ ফার্লং + ৪৫,৯১৩.৬৮ ফার্লং + -০.১১১ ফার্লং + +measure-unit/length-furlong @@ scale/0.5 + es-MX + 0.0 fur + 46,000 fur + -0.11 fur + zh-TW + 0.0 化朗 + 46,000 化朗 + -0.11 化朗 + bn-BD + ০.০ ফার্লং + ৪৬,০০০ ফার্লং + -০.১১ ফার্লং + +percent precision-integer group-on-aligned + es-MX + 0 % + 91,827 % + -0 % + zh-TW + 0% + 91,827% + -0% + bn-BD + ০% + ৯১,৮২৭% + -০% + +percent .000 group-on-aligned + es-MX + 0.000 % + 91,827.364 % + -0.222 % + zh-TW + 0.000% + 91,827.364% + -0.222% + bn-BD + ০.০০০% + ৯১,৮২৭.৩৬৪% + -০.২২২% + +percent .##/@@@+ group-on-aligned + es-MX + 0 % + 91,827.36 % + -0.222 % + zh-TW + 0% + 91,827.36% + -0.222% + bn-BD + ০% + ৯১,৮২৭.৩৬% + -০.২২২% + +percent @@ group-on-aligned + es-MX + 0.0 % + 92,000 % + -0.22 % + zh-TW + 0.0% + 92,000% + -0.22% + bn-BD + ০.০% + ৯২,০০০% + -০.২২% + +currency/EUR precision-integer group-on-aligned + es-MX + EUR 0 + EUR 91,827 + -EUR 0 + zh-TW + €0 + €91,827 + -€0 + bn-BD + ০€ + ৯১,৮২৭€ + -০€ + +currency/EUR .000 group-on-aligned + es-MX + EUR 0.000 + EUR 91,827.364 + -EUR 0.222 + zh-TW + €0.000 + €91,827.364 + -€0.222 + bn-BD + ০.০০০€ + ৯১,৮২৭.৩৬৪€ + -০.২২২€ + +currency/EUR .##/@@@+ group-on-aligned + es-MX + EUR 0 + EUR 91,827.36 + -EUR 0.222 + zh-TW + €0 + €91,827.36 + -€0.222 + bn-BD + ০€ + ৯১,৮২৭.৩৬€ + -০.২২২€ + +currency/EUR @@ group-on-aligned + es-MX + EUR 0.0 + EUR 92,000 + -EUR 0.22 + zh-TW + €0.0 + €92,000 + -€0.22 + bn-BD + ০.০€ + ৯২,০০০€ + -০.২২€ + +measure-unit/length-furlong precision-integer group-on-aligned + es-MX + 0 fur + 91,827 fur + -0 fur + zh-TW + 0 化朗 + 91,827 化朗 + -0 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭ ফার্লং + -০ ফার্লং + +measure-unit/length-furlong .000 group-on-aligned + es-MX + 0.000 fur + 91,827.364 fur + -0.222 fur + zh-TW + 0.000 化朗 + 91,827.364 化朗 + -0.222 化朗 + bn-BD + ০.০০০ ফার্লং + ৯১,৮২৭.৩৬৪ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong .##/@@@+ group-on-aligned + es-MX + 0 fur + 91,827.36 fur + -0.222 fur + zh-TW + 0 化朗 + 91,827.36 化朗 + -0.222 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong @@ group-on-aligned + es-MX + 0.0 fur + 92,000 fur + -0.22 fur + zh-TW + 0.0 化朗 + 92,000 化朗 + -0.22 化朗 + bn-BD + ০.০ ফার্লং + ৯২,০০০ ফার্লং + -০.২২ ফার্লং + +percent precision-integer latin + es-MX + 0 % + 91,827 % + -0 % + zh-TW + 0% + 91,827% + -0% + bn-BD + 0% + 91,827% + -0% + +percent .000 latin + es-MX + 0.000 % + 91,827.364 % + -0.222 % + zh-TW + 0.000% + 91,827.364% + -0.222% + bn-BD + 0.000% + 91,827.364% + -0.222% + +percent .##/@@@+ latin + es-MX + 0 % + 91,827.36 % + -0.222 % + zh-TW + 0% + 91,827.36% + -0.222% + bn-BD + 0% + 91,827.36% + -0.222% + +percent @@ latin + es-MX + 0.0 % + 92,000 % + -0.22 % + zh-TW + 0.0% + 92,000% + -0.22% + bn-BD + 0.0% + 92,000% + -0.22% + +currency/EUR precision-integer latin + es-MX + EUR 0 + EUR 91,827 + -EUR 0 + zh-TW + €0 + €91,827 + -€0 + bn-BD + 0€ + 91,827€ + -0€ + +currency/EUR .000 latin + es-MX + EUR 0.000 + EUR 91,827.364 + -EUR 0.222 + zh-TW + €0.000 + €91,827.364 + -€0.222 + bn-BD + 0.000€ + 91,827.364€ + -0.222€ + +currency/EUR .##/@@@+ latin + es-MX + EUR 0 + EUR 91,827.36 + -EUR 0.222 + zh-TW + €0 + €91,827.36 + -€0.222 + bn-BD + 0€ + 91,827.36€ + -0.222€ + +currency/EUR @@ latin + es-MX + EUR 0.0 + EUR 92,000 + -EUR 0.22 + zh-TW + €0.0 + €92,000 + -€0.22 + bn-BD + 0.0€ + 92,000€ + -0.22€ + +measure-unit/length-furlong precision-integer latin + es-MX + 0 fur + 91,827 fur + -0 fur + zh-TW + 0 化朗 + 91,827 化朗 + -0 化朗 + bn-BD + 0 ফার্লং + 91,827 ফার্লং + -0 ফার্লং + +measure-unit/length-furlong .000 latin + es-MX + 0.000 fur + 91,827.364 fur + -0.222 fur + zh-TW + 0.000 化朗 + 91,827.364 化朗 + -0.222 化朗 + bn-BD + 0.000 ফার্লং + 91,827.364 ফার্লং + -0.222 ফার্লং + +measure-unit/length-furlong .##/@@@+ latin + es-MX + 0 fur + 91,827.36 fur + -0.222 fur + zh-TW + 0 化朗 + 91,827.36 化朗 + -0.222 化朗 + bn-BD + 0 ফার্লং + 91,827.36 ফার্লং + -0.222 ফার্লং + +measure-unit/length-furlong @@ latin + es-MX + 0.0 fur + 92,000 fur + -0.22 fur + zh-TW + 0.0 化朗 + 92,000 化朗 + -0.22 化朗 + bn-BD + 0.0 ফার্লং + 92,000 ফার্লং + -0.22 ফার্লং + +percent precision-integer sign-accounting-except-zero + es-MX + 0 % + +91,827 % + -0 % + zh-TW + 0% + +91,827% + -0% + bn-BD + ০% + +৯১,৮২৭% + -০% + +percent .000 sign-accounting-except-zero + es-MX + 0.000 % + +91,827.364 % + -0.222 % + zh-TW + 0.000% + +91,827.364% + -0.222% + bn-BD + ০.০০০% + +৯১,৮২৭.৩৬৪% + -০.২২২% + +percent .##/@@@+ sign-accounting-except-zero + es-MX + 0 % + +91,827.36 % + -0.222 % + zh-TW + 0% + +91,827.36% + -0.222% + bn-BD + ০% + +৯১,৮২৭.৩৬% + -০.২২২% + +percent @@ sign-accounting-except-zero + es-MX + 0.0 % + +92,000 % + -0.22 % + zh-TW + 0.0% + +92,000% + -0.22% + bn-BD + ০.০% + +৯২,০০০% + -০.২২% + +currency/EUR precision-integer sign-accounting-except-zero + es-MX + EUR 0 + +EUR 91,827 + -EUR 0 + zh-TW + €0 + +€91,827 + (€0) + bn-BD + ০€ + +৯১,৮২৭€ + (০ €) + +currency/EUR .000 sign-accounting-except-zero + es-MX + EUR 0.000 + +EUR 91,827.364 + -EUR 0.222 + zh-TW + €0.000 + +€91,827.364 + (€0.222) + bn-BD + ০.০০০€ + +৯১,৮২৭.৩৬৪€ + (০.২২২ €) + +currency/EUR .##/@@@+ sign-accounting-except-zero + es-MX + EUR 0 + +EUR 91,827.36 + -EUR 0.222 + zh-TW + €0 + +€91,827.36 + (€0.222) + bn-BD + ০€ + +৯১,৮২৭.৩৬€ + (০.২২২ €) + +currency/EUR @@ sign-accounting-except-zero + es-MX + EUR 0.0 + +EUR 92,000 + -EUR 0.22 + zh-TW + €0.0 + +€92,000 + (€0.22) + bn-BD + ০.০€ + +৯২,০০০€ + (০.২২ €) + +measure-unit/length-furlong precision-integer sign-accounting-except-zero + es-MX + 0 fur + +91,827 fur + -0 fur + zh-TW + 0 化朗 + +91,827 化朗 + -0 化朗 + bn-BD + ০ ফার্লং + +৯১,৮২৭ ফার্লং + -০ ফার্লং + +measure-unit/length-furlong .000 sign-accounting-except-zero + es-MX + 0.000 fur + +91,827.364 fur + -0.222 fur + zh-TW + 0.000 化朗 + +91,827.364 化朗 + -0.222 化朗 + bn-BD + ০.০০০ ফার্লং + +৯১,৮২৭.৩৬৪ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong .##/@@@+ sign-accounting-except-zero + es-MX + 0 fur + +91,827.36 fur + -0.222 fur + zh-TW + 0 化朗 + +91,827.36 化朗 + -0.222 化朗 + bn-BD + ০ ফার্লং + +৯১,৮২৭.৩৬ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong @@ sign-accounting-except-zero + es-MX + 0.0 fur + +92,000 fur + -0.22 fur + zh-TW + 0.0 化朗 + +92,000 化朗 + -0.22 化朗 + bn-BD + ০.০ ফার্লং + +৯২,০০০ ফার্লং + -০.২২ ফার্লং + +percent precision-integer decimal-always + es-MX + 0. % + 91,827. % + -0. % + zh-TW + 0.% + 91,827.% + -0.% + bn-BD + ০.% + ৯১,৮২৭.% + -০.% + +percent .000 decimal-always + es-MX + 0.000 % + 91,827.364 % + -0.222 % + zh-TW + 0.000% + 91,827.364% + -0.222% + bn-BD + ০.০০০% + ৯১,৮২৭.৩৬৪% + -০.২২২% + +percent .##/@@@+ decimal-always + es-MX + 0. % + 91,827.36 % + -0.222 % + zh-TW + 0.% + 91,827.36% + -0.222% + bn-BD + ০.% + ৯১,৮২৭.৩৬% + -০.২২২% + +percent @@ decimal-always + es-MX + 0.0 % + 92,000. % + -0.22 % + zh-TW + 0.0% + 92,000.% + -0.22% + bn-BD + ০.০% + ৯২,০০০.% + -০.২২% + +currency/EUR precision-integer decimal-always + es-MX + EUR 0. + EUR 91,827. + -EUR 0. + zh-TW + €0. + €91,827. + -€0. + bn-BD + ০.€ + ৯১,৮২৭.€ + -০.€ + +currency/EUR .000 decimal-always + es-MX + EUR 0.000 + EUR 91,827.364 + -EUR 0.222 + zh-TW + €0.000 + €91,827.364 + -€0.222 + bn-BD + ০.০০০€ + ৯১,৮২৭.৩৬৪€ + -০.২২২€ + +currency/EUR .##/@@@+ decimal-always + es-MX + EUR 0. + EUR 91,827.36 + -EUR 0.222 + zh-TW + €0. + €91,827.36 + -€0.222 + bn-BD + ০.€ + ৯১,৮২৭.৩৬€ + -০.২২২€ + +currency/EUR @@ decimal-always + es-MX + EUR 0.0 + EUR 92,000. + -EUR 0.22 + zh-TW + €0.0 + €92,000. + -€0.22 + bn-BD + ০.০€ + ৯২,০০০.€ + -০.২২€ + +measure-unit/length-furlong precision-integer decimal-always + es-MX + 0. fur + 91,827. fur + -0. fur + zh-TW + 0. 化朗 + 91,827. 化朗 + -0. 化朗 + bn-BD + ০. ফার্লং + ৯১,৮২৭. ফার্লং + -০. ফার্লং + +measure-unit/length-furlong .000 decimal-always + es-MX + 0.000 fur + 91,827.364 fur + -0.222 fur + zh-TW + 0.000 化朗 + 91,827.364 化朗 + -0.222 化朗 + bn-BD + ০.০০০ ফার্লং + ৯১,৮২৭.৩৬৪ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong .##/@@@+ decimal-always + es-MX + 0. fur + 91,827.36 fur + -0.222 fur + zh-TW + 0. 化朗 + 91,827.36 化朗 + -0.222 化朗 + bn-BD + ০. ফার্লং + ৯১,৮২৭.৩৬ ফার্লং + -০.২২২ ফার্লং + +measure-unit/length-furlong @@ decimal-always + es-MX + 0.0 fur + 92,000. fur + -0.22 fur + zh-TW + 0.0 化朗 + 92,000. 化朗 + -0.22 化朗 + bn-BD + ০.০ ফার্লং + ৯২,০০০. ফার্লং + -০.২২ ফার্লং + +percent rounding-mode-floor integer-width/##00 + es-MX + 00 % + 1827.3645 % + -00.22222 % + zh-TW + 00% + 1,827.3645% + -00.22222% + bn-BD + ০০% + ১,৮২৭.৩৬৪৫% + -০০.২২২২২% + +currency/EUR rounding-mode-floor integer-width/##00 + es-MX + EUR 00.00 + EUR 1827.36 + -EUR 00.23 + zh-TW + €00.00 + €1,827.36 + -€00.23 + bn-BD + ০০.০০€ + ১,৮২৭.৩৬€ + -০০.২৩€ + +measure-unit/length-furlong rounding-mode-floor integer-width/##00 + es-MX + 00 fur + 1827.3645 fur + -00.22222 fur + zh-TW + 00 化朗 + 1,827.3645 化朗 + -00.22222 化朗 + bn-BD + ০০ ফার্লং + ১,৮২৭.৩৬৪৫ ফার্লং + -০০.২২২২২ ফার্লং + +percent rounding-mode-floor scale/0.5 + es-MX + 0 % + 45,913.68225 % + -0.11111 % + zh-TW + 0% + 45,913.68225% + -0.11111% + bn-BD + ০% + ৪৫,৯১৩.৬৮২২৫% + -০.১১১১১% + +currency/EUR rounding-mode-floor scale/0.5 + es-MX + EUR 0.00 + EUR 45,913.68 + -EUR 0.12 + zh-TW + €0.00 + €45,913.68 + -€0.12 + bn-BD + ০.০০€ + ৪৫,৯১৩.৬৮€ + -০.১২€ + +measure-unit/length-furlong rounding-mode-floor scale/0.5 + es-MX + 0 fur + 45,913.68225 fur + -0.11111 fur + zh-TW + 0 化朗 + 45,913.68225 化朗 + -0.11111 化朗 + bn-BD + ০ ফার্লং + ৪৫,৯১৩.৬৮২২৫ ফার্লং + -০.১১১১১ ফার্লং + +percent rounding-mode-floor group-on-aligned + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + ০% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR rounding-mode-floor group-on-aligned + es-MX + EUR 0.00 + EUR 91,827.36 + -EUR 0.23 + zh-TW + €0.00 + €91,827.36 + -€0.23 + bn-BD + ০.০০€ + ৯১,৮২৭.৩৬€ + -০.২৩€ + +measure-unit/length-furlong rounding-mode-floor group-on-aligned + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০ ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent rounding-mode-floor latin + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + 0% + 91,827.3645% + -0.22222% + +currency/EUR rounding-mode-floor latin + es-MX + EUR 0.00 + EUR 91,827.36 + -EUR 0.23 + zh-TW + €0.00 + €91,827.36 + -€0.23 + bn-BD + 0.00€ + 91,827.36€ + -0.23€ + +measure-unit/length-furlong rounding-mode-floor latin + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + 0 ফার্লং + 91,827.3645 ফার্লং + -0.22222 ফার্লং + +percent rounding-mode-floor sign-accounting-except-zero + es-MX + 0 % + +91,827.3645 % + -0.22222 % + zh-TW + 0% + +91,827.3645% + -0.22222% + bn-BD + ০% + +৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR rounding-mode-floor sign-accounting-except-zero + es-MX + EUR 0.00 + +EUR 91,827.36 + -EUR 0.23 + zh-TW + €0.00 + +€91,827.36 + (€0.23) + bn-BD + ০.০০€ + +৯১,৮২৭.৩৬€ + (০.২৩ €) + +measure-unit/length-furlong rounding-mode-floor sign-accounting-except-zero + es-MX + 0 fur + +91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + +91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০ ফার্লং + +৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent rounding-mode-floor decimal-always + es-MX + 0. % + 91,827.3645 % + -0.22222 % + zh-TW + 0.% + 91,827.3645% + -0.22222% + bn-BD + ০.% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR rounding-mode-floor decimal-always + es-MX + EUR 0.00 + EUR 91,827.36 + -EUR 0.23 + zh-TW + €0.00 + €91,827.36 + -€0.23 + bn-BD + ০.০০€ + ৯১,৮২৭.৩৬€ + -০.২৩€ + +measure-unit/length-furlong rounding-mode-floor decimal-always + es-MX + 0. fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0. 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০. ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent integer-width/##00 scale/0.5 + es-MX + 00 % + 5913.68225 % + -00.11111 % + zh-TW + 00% + 5,913.68225% + -00.11111% + bn-BD + ০০% + ৫,৯১৩.৬৮২২৫% + -০০.১১১১১% + +currency/EUR integer-width/##00 scale/0.5 + es-MX + EUR 00.00 + EUR 5913.68 + -EUR 00.11 + zh-TW + €00.00 + €5,913.68 + -€00.11 + bn-BD + ০০.০০€ + ৫,৯১৩.৬৮€ + -০০.১১€ + +measure-unit/length-furlong integer-width/##00 scale/0.5 + es-MX + 00 fur + 5913.68225 fur + -00.11111 fur + zh-TW + 00 化朗 + 5,913.68225 化朗 + -00.11111 化朗 + bn-BD + ০০ ফার্লং + ৫,৯১৩.৬৮২২৫ ফার্লং + -০০.১১১১১ ফার্লং + +percent integer-width/##00 group-on-aligned + es-MX + 00 % + 1,827.3645 % + -00.22222 % + zh-TW + 00% + 1,827.3645% + -00.22222% + bn-BD + ০০% + ১,৮২৭.৩৬৪৫% + -০০.২২২২২% + +currency/EUR integer-width/##00 group-on-aligned + es-MX + EUR 00.00 + EUR 1,827.36 + -EUR 00.22 + zh-TW + €00.00 + €1,827.36 + -€00.22 + bn-BD + ০০.০০€ + ১,৮২৭.৩৬€ + -০০.২২€ + +measure-unit/length-furlong integer-width/##00 group-on-aligned + es-MX + 00 fur + 1,827.3645 fur + -00.22222 fur + zh-TW + 00 化朗 + 1,827.3645 化朗 + -00.22222 化朗 + bn-BD + ০০ ফার্লং + ১,৮২৭.৩৬৪৫ ফার্লং + -০০.২২২২২ ফার্লং + +percent integer-width/##00 latin + es-MX + 00 % + 1827.3645 % + -00.22222 % + zh-TW + 00% + 1,827.3645% + -00.22222% + bn-BD + 00% + 1,827.3645% + -00.22222% + +currency/EUR integer-width/##00 latin + es-MX + EUR 00.00 + EUR 1827.36 + -EUR 00.22 + zh-TW + €00.00 + €1,827.36 + -€00.22 + bn-BD + 00.00€ + 1,827.36€ + -00.22€ + +measure-unit/length-furlong integer-width/##00 latin + es-MX + 00 fur + 1827.3645 fur + -00.22222 fur + zh-TW + 00 化朗 + 1,827.3645 化朗 + -00.22222 化朗 + bn-BD + 00 ফার্লং + 1,827.3645 ফার্লং + -00.22222 ফার্লং + +percent integer-width/##00 sign-accounting-except-zero + es-MX + 00 % + +1827.3645 % + -00.22222 % + zh-TW + 00% + +1,827.3645% + -00.22222% + bn-BD + ০০% + +১,৮২৭.৩৬৪৫% + -০০.২২২২২% + +currency/EUR integer-width/##00 sign-accounting-except-zero + es-MX + EUR 00.00 + +EUR 1827.36 + -EUR 00.22 + zh-TW + €00.00 + +€1,827.36 + (€00.22) + bn-BD + ০০.০০€ + +১,৮২৭.৩৬€ + (০০.২২ €) + +measure-unit/length-furlong integer-width/##00 sign-accounting-except-zero + es-MX + 00 fur + +1827.3645 fur + -00.22222 fur + zh-TW + 00 化朗 + +1,827.3645 化朗 + -00.22222 化朗 + bn-BD + ০০ ফার্লং + +১,৮২৭.৩৬৪৫ ফার্লং + -০০.২২২২২ ফার্লং + +percent integer-width/##00 decimal-always + es-MX + 00. % + 1827.3645 % + -00.22222 % + zh-TW + 00.% + 1,827.3645% + -00.22222% + bn-BD + ০০.% + ১,৮২৭.৩৬৪৫% + -০০.২২২২২% + +currency/EUR integer-width/##00 decimal-always + es-MX + EUR 00.00 + EUR 1827.36 + -EUR 00.22 + zh-TW + €00.00 + €1,827.36 + -€00.22 + bn-BD + ০০.০০€ + ১,৮২৭.৩৬€ + -০০.২২€ + +measure-unit/length-furlong integer-width/##00 decimal-always + es-MX + 00. fur + 1827.3645 fur + -00.22222 fur + zh-TW + 00. 化朗 + 1,827.3645 化朗 + -00.22222 化朗 + bn-BD + ০০. ফার্লং + ১,৮২৭.৩৬৪৫ ফার্লং + -০০.২২২২২ ফার্লং + +percent scale/0.5 group-on-aligned + es-MX + 0 % + 45,913.68225 % + -0.11111 % + zh-TW + 0% + 45,913.68225% + -0.11111% + bn-BD + ০% + ৪৫,৯১৩.৬৮২২৫% + -০.১১১১১% + +currency/EUR scale/0.5 group-on-aligned + es-MX + EUR 0.00 + EUR 45,913.68 + -EUR 0.11 + zh-TW + €0.00 + €45,913.68 + -€0.11 + bn-BD + ০.০০€ + ৪৫,৯১৩.৬৮€ + -০.১১€ + +measure-unit/length-furlong scale/0.5 group-on-aligned + es-MX + 0 fur + 45,913.68225 fur + -0.11111 fur + zh-TW + 0 化朗 + 45,913.68225 化朗 + -0.11111 化朗 + bn-BD + ০ ফার্লং + ৪৫,৯১৩.৬৮২২৫ ফার্লং + -০.১১১১১ ফার্লং + +percent scale/0.5 latin + es-MX + 0 % + 45,913.68225 % + -0.11111 % + zh-TW + 0% + 45,913.68225% + -0.11111% + bn-BD + 0% + 45,913.68225% + -0.11111% + +currency/EUR scale/0.5 latin + es-MX + EUR 0.00 + EUR 45,913.68 + -EUR 0.11 + zh-TW + €0.00 + €45,913.68 + -€0.11 + bn-BD + 0.00€ + 45,913.68€ + -0.11€ + +measure-unit/length-furlong scale/0.5 latin + es-MX + 0 fur + 45,913.68225 fur + -0.11111 fur + zh-TW + 0 化朗 + 45,913.68225 化朗 + -0.11111 化朗 + bn-BD + 0 ফার্লং + 45,913.68225 ফার্লং + -0.11111 ফার্লং + +percent scale/0.5 sign-accounting-except-zero + es-MX + 0 % + +45,913.68225 % + -0.11111 % + zh-TW + 0% + +45,913.68225% + -0.11111% + bn-BD + ০% + +৪৫,৯১৩.৬৮২২৫% + -০.১১১১১% + +currency/EUR scale/0.5 sign-accounting-except-zero + es-MX + EUR 0.00 + +EUR 45,913.68 + -EUR 0.11 + zh-TW + €0.00 + +€45,913.68 + (€0.11) + bn-BD + ০.০০€ + +৪৫,৯১৩.৬৮€ + (০.১১ €) + +measure-unit/length-furlong scale/0.5 sign-accounting-except-zero + es-MX + 0 fur + +45,913.68225 fur + -0.11111 fur + zh-TW + 0 化朗 + +45,913.68225 化朗 + -0.11111 化朗 + bn-BD + ০ ফার্লং + +৪৫,৯১৩.৬৮২২৫ ফার্লং + -০.১১১১১ ফার্লং + +percent scale/0.5 decimal-always + es-MX + 0. % + 45,913.68225 % + -0.11111 % + zh-TW + 0.% + 45,913.68225% + -0.11111% + bn-BD + ০.% + ৪৫,৯১৩.৬৮২২৫% + -০.১১১১১% + +currency/EUR scale/0.5 decimal-always + es-MX + EUR 0.00 + EUR 45,913.68 + -EUR 0.11 + zh-TW + €0.00 + €45,913.68 + -€0.11 + bn-BD + ০.০০€ + ৪৫,৯১৩.৬৮€ + -০.১১€ + +measure-unit/length-furlong scale/0.5 decimal-always + es-MX + 0. fur + 45,913.68225 fur + -0.11111 fur + zh-TW + 0. 化朗 + 45,913.68225 化朗 + -0.11111 化朗 + bn-BD + ০. ফার্লং + ৪৫,৯১৩.৬৮২২৫ ফার্লং + -০.১১১১১ ফার্লং + +percent group-on-aligned latin + es-MX + 0 % + 91,827.3645 % + -0.22222 % + zh-TW + 0% + 91,827.3645% + -0.22222% + bn-BD + 0% + 91,827.3645% + -0.22222% + +currency/EUR group-on-aligned latin + es-MX + EUR 0.00 + EUR 91,827.36 + -EUR 0.22 + zh-TW + €0.00 + €91,827.36 + -€0.22 + bn-BD + 0.00€ + 91,827.36€ + -0.22€ + +measure-unit/length-furlong group-on-aligned latin + es-MX + 0 fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + 0 ফার্লং + 91,827.3645 ফার্লং + -0.22222 ফার্লং + +percent group-on-aligned sign-accounting-except-zero + es-MX + 0 % + +91,827.3645 % + -0.22222 % + zh-TW + 0% + +91,827.3645% + -0.22222% + bn-BD + ০% + +৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR group-on-aligned sign-accounting-except-zero + es-MX + EUR 0.00 + +EUR 91,827.36 + -EUR 0.22 + zh-TW + €0.00 + +€91,827.36 + (€0.22) + bn-BD + ০.০০€ + +৯১,৮২৭.৩৬€ + (০.২২ €) + +measure-unit/length-furlong group-on-aligned sign-accounting-except-zero + es-MX + 0 fur + +91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + +91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০ ফার্লং + +৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent group-on-aligned decimal-always + es-MX + 0. % + 91,827.3645 % + -0.22222 % + zh-TW + 0.% + 91,827.3645% + -0.22222% + bn-BD + ০.% + ৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR group-on-aligned decimal-always + es-MX + EUR 0.00 + EUR 91,827.36 + -EUR 0.22 + zh-TW + €0.00 + €91,827.36 + -€0.22 + bn-BD + ০.০০€ + ৯১,৮২৭.৩৬€ + -০.২২€ + +measure-unit/length-furlong group-on-aligned decimal-always + es-MX + 0. fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0. 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০. ফার্লং + ৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +percent latin sign-accounting-except-zero + es-MX + 0 % + +91,827.3645 % + -0.22222 % + zh-TW + 0% + +91,827.3645% + -0.22222% + bn-BD + 0% + +91,827.3645% + -0.22222% + +currency/EUR latin sign-accounting-except-zero + es-MX + EUR 0.00 + +EUR 91,827.36 + -EUR 0.22 + zh-TW + €0.00 + +€91,827.36 + (€0.22) + bn-BD + 0.00€ + +91,827.36€ + (0.22 €) + +measure-unit/length-furlong latin sign-accounting-except-zero + es-MX + 0 fur + +91,827.3645 fur + -0.22222 fur + zh-TW + 0 化朗 + +91,827.3645 化朗 + -0.22222 化朗 + bn-BD + 0 ফার্লং + +91,827.3645 ফার্লং + -0.22222 ফার্লং + +percent latin decimal-always + es-MX + 0. % + 91,827.3645 % + -0.22222 % + zh-TW + 0.% + 91,827.3645% + -0.22222% + bn-BD + 0.% + 91,827.3645% + -0.22222% + +currency/EUR latin decimal-always + es-MX + EUR 0.00 + EUR 91,827.36 + -EUR 0.22 + zh-TW + €0.00 + €91,827.36 + -€0.22 + bn-BD + 0.00€ + 91,827.36€ + -0.22€ + +measure-unit/length-furlong latin decimal-always + es-MX + 0. fur + 91,827.3645 fur + -0.22222 fur + zh-TW + 0. 化朗 + 91,827.3645 化朗 + -0.22222 化朗 + bn-BD + 0. ফার্লং + 91,827.3645 ফার্লং + -0.22222 ফার্লং + +percent sign-accounting-except-zero decimal-always + es-MX + 0. % + +91,827.3645 % + -0.22222 % + zh-TW + 0.% + +91,827.3645% + -0.22222% + bn-BD + ০.% + +৯১,৮২৭.৩৬৪৫% + -০.২২২২২% + +currency/EUR sign-accounting-except-zero decimal-always + es-MX + EUR 0.00 + +EUR 91,827.36 + -EUR 0.22 + zh-TW + €0.00 + +€91,827.36 + (€0.22) + bn-BD + ০.০০€ + +৯১,৮২৭.৩৬€ + (০.২২ €) + +measure-unit/length-furlong sign-accounting-except-zero decimal-always + es-MX + 0. fur + +91,827.3645 fur + -0.22222 fur + zh-TW + 0. 化朗 + +91,827.3645 化朗 + -0.22222 化朗 + bn-BD + ০. ফার্লং + +৯১,৮২৭.৩৬৪৫ ফার্লং + -০.২২২২২ ফার্লং + +unit-width-narrow precision-integer rounding-mode-floor + es-MX + 0 + 91,827 + -1 + zh-TW + 0 + 91,827 + -1 + bn-BD + ০ + ৯১,৮২৭ + -১ + +unit-width-narrow .000 rounding-mode-floor + es-MX + 0.000 + 91,827.364 + -0.223 + zh-TW + 0.000 + 91,827.364 + -0.223 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২৩ + +unit-width-narrow .##/@@@+ rounding-mode-floor + es-MX + 0 + 91,827.36 + -0.223 + zh-TW + 0 + 91,827.36 + -0.223 + bn-BD + ০ + ৯১,৮২৭.৩৬ + -০.২২৩ + +unit-width-narrow @@ rounding-mode-floor + es-MX + 0.0 + 91,000 + -0.23 + zh-TW + 0.0 + 91,000 + -0.23 + bn-BD + ০.০ + ৯১,০০০ + -০.২৩ + +unit-width-full-name precision-integer rounding-mode-floor + es-MX + 0 + 91,827 + -1 + zh-TW + 0 + 91,827 + -1 + bn-BD + ০ + ৯১,৮২৭ + -১ + +unit-width-full-name .000 rounding-mode-floor + es-MX + 0.000 + 91,827.364 + -0.223 + zh-TW + 0.000 + 91,827.364 + -0.223 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২৩ + +unit-width-full-name .##/@@@+ rounding-mode-floor + es-MX + 0 + 91,827.36 + -0.223 + zh-TW + 0 + 91,827.36 + -0.223 + bn-BD + ০ + ৯১,৮২৭.৩৬ + -০.২২৩ + +unit-width-full-name @@ rounding-mode-floor + es-MX + 0.0 + 91,000 + -0.23 + zh-TW + 0.0 + 91,000 + -0.23 + bn-BD + ০.০ + ৯১,০০০ + -০.২৩ + +unit-width-narrow precision-integer integer-width/##00 + es-MX + 00 + 1827 + -00 + zh-TW + 00 + 1,827 + -00 + bn-BD + ০০ + ১,৮২৭ + -০০ + +unit-width-narrow .000 integer-width/##00 + es-MX + 00.000 + 1827.364 + -00.222 + zh-TW + 00.000 + 1,827.364 + -00.222 + bn-BD + ০০.০০০ + ১,৮২৭.৩৬৪ + -০০.২২২ + +unit-width-narrow .##/@@@+ integer-width/##00 + es-MX + 00 + 1827.36 + -00.222 + zh-TW + 00 + 1,827.36 + -00.222 + bn-BD + ০০ + ১,৮২৭.৩৬ + -০০.২২২ + +unit-width-narrow @@ integer-width/##00 + es-MX + 00.0 + 2000 + -00.22 + zh-TW + 00.0 + 2,000 + -00.22 + bn-BD + ০০.০ + ২,০০০ + -০০.২২ + +unit-width-full-name precision-integer integer-width/##00 + es-MX + 00 + 1827 + -00 + zh-TW + 00 + 1,827 + -00 + bn-BD + ০০ + ১,৮২৭ + -০০ + +unit-width-full-name .000 integer-width/##00 + es-MX + 00.000 + 1827.364 + -00.222 + zh-TW + 00.000 + 1,827.364 + -00.222 + bn-BD + ০০.০০০ + ১,৮২৭.৩৬৪ + -০০.২২২ + +unit-width-full-name .##/@@@+ integer-width/##00 + es-MX + 00 + 1827.36 + -00.222 + zh-TW + 00 + 1,827.36 + -00.222 + bn-BD + ০০ + ১,৮২৭.৩৬ + -০০.২২২ + +unit-width-full-name @@ integer-width/##00 + es-MX + 00.0 + 2000 + -00.22 + zh-TW + 00.0 + 2,000 + -00.22 + bn-BD + ০০.০ + ২,০০০ + -০০.২২ + +unit-width-narrow precision-integer scale/0.5 + es-MX + 0 + 45,914 + -0 + zh-TW + 0 + 45,914 + -0 + bn-BD + ০ + ৪৫,৯১৪ + -০ + +unit-width-narrow .000 scale/0.5 + es-MX + 0.000 + 45,913.682 + -0.111 + zh-TW + 0.000 + 45,913.682 + -0.111 + bn-BD + ০.০০০ + ৪৫,৯১৩.৬৮২ + -০.১১১ + +unit-width-narrow .##/@@@+ scale/0.5 + es-MX + 0 + 45,913.68 + -0.111 + zh-TW + 0 + 45,913.68 + -0.111 + bn-BD + ০ + ৪৫,৯১৩.৬৮ + -০.১১১ + +unit-width-narrow @@ scale/0.5 + es-MX + 0.0 + 46,000 + -0.11 + zh-TW + 0.0 + 46,000 + -0.11 + bn-BD + ০.০ + ৪৬,০০০ + -০.১১ + +unit-width-full-name precision-integer scale/0.5 + es-MX + 0 + 45,914 + -0 + zh-TW + 0 + 45,914 + -0 + bn-BD + ০ + ৪৫,৯১৪ + -০ + +unit-width-full-name .000 scale/0.5 + es-MX + 0.000 + 45,913.682 + -0.111 + zh-TW + 0.000 + 45,913.682 + -0.111 + bn-BD + ০.০০০ + ৪৫,৯১৩.৬৮২ + -০.১১১ + +unit-width-full-name .##/@@@+ scale/0.5 + es-MX + 0 + 45,913.68 + -0.111 + zh-TW + 0 + 45,913.68 + -0.111 + bn-BD + ০ + ৪৫,৯১৩.৬৮ + -০.১১১ + +unit-width-full-name @@ scale/0.5 + es-MX + 0.0 + 46,000 + -0.11 + zh-TW + 0.0 + 46,000 + -0.11 + bn-BD + ০.০ + ৪৬,০০০ + -০.১১ + +unit-width-narrow precision-integer group-on-aligned + es-MX + 0 + 91,827 + -0 + zh-TW + 0 + 91,827 + -0 + bn-BD + ০ + ৯১,৮২৭ + -০ + +unit-width-narrow .000 group-on-aligned + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২২ + +unit-width-narrow .##/@@@+ group-on-aligned + es-MX + 0 + 91,827.36 + -0.222 + zh-TW + 0 + 91,827.36 + -0.222 + bn-BD + ০ + ৯১,৮২৭.৩৬ + -০.২২২ + +unit-width-narrow @@ group-on-aligned + es-MX + 0.0 + 92,000 + -0.22 + zh-TW + 0.0 + 92,000 + -0.22 + bn-BD + ০.০ + ৯২,০০০ + -০.২২ + +unit-width-full-name precision-integer group-on-aligned + es-MX + 0 + 91,827 + -0 + zh-TW + 0 + 91,827 + -0 + bn-BD + ০ + ৯১,৮২৭ + -০ + +unit-width-full-name .000 group-on-aligned + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২২ + +unit-width-full-name .##/@@@+ group-on-aligned + es-MX + 0 + 91,827.36 + -0.222 + zh-TW + 0 + 91,827.36 + -0.222 + bn-BD + ০ + ৯১,৮২৭.৩৬ + -০.২২২ + +unit-width-full-name @@ group-on-aligned + es-MX + 0.0 + 92,000 + -0.22 + zh-TW + 0.0 + 92,000 + -0.22 + bn-BD + ০.০ + ৯২,০০০ + -০.২২ + +unit-width-narrow precision-integer latin + es-MX + 0 + 91,827 + -0 + zh-TW + 0 + 91,827 + -0 + bn-BD + 0 + 91,827 + -0 + +unit-width-narrow .000 latin + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + 0.000 + 91,827.364 + -0.222 + +unit-width-narrow .##/@@@+ latin + es-MX + 0 + 91,827.36 + -0.222 + zh-TW + 0 + 91,827.36 + -0.222 + bn-BD + 0 + 91,827.36 + -0.222 + +unit-width-narrow @@ latin + es-MX + 0.0 + 92,000 + -0.22 + zh-TW + 0.0 + 92,000 + -0.22 + bn-BD + 0.0 + 92,000 + -0.22 + +unit-width-full-name precision-integer latin + es-MX + 0 + 91,827 + -0 + zh-TW + 0 + 91,827 + -0 + bn-BD + 0 + 91,827 + -0 + +unit-width-full-name .000 latin + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + 0.000 + 91,827.364 + -0.222 + +unit-width-full-name .##/@@@+ latin + es-MX + 0 + 91,827.36 + -0.222 + zh-TW + 0 + 91,827.36 + -0.222 + bn-BD + 0 + 91,827.36 + -0.222 + +unit-width-full-name @@ latin + es-MX + 0.0 + 92,000 + -0.22 + zh-TW + 0.0 + 92,000 + -0.22 + bn-BD + 0.0 + 92,000 + -0.22 + +unit-width-narrow precision-integer sign-accounting-except-zero + es-MX + 0 + +91,827 + -0 + zh-TW + 0 + +91,827 + -0 + bn-BD + ০ + +৯১,৮২৭ + -০ + +unit-width-narrow .000 sign-accounting-except-zero + es-MX + 0.000 + +91,827.364 + -0.222 + zh-TW + 0.000 + +91,827.364 + -0.222 + bn-BD + ০.০০০ + +৯১,৮২৭.৩৬৪ + -০.২২২ + +unit-width-narrow .##/@@@+ sign-accounting-except-zero + es-MX + 0 + +91,827.36 + -0.222 + zh-TW + 0 + +91,827.36 + -0.222 + bn-BD + ০ + +৯১,৮২৭.৩৬ + -০.২২২ + +unit-width-narrow @@ sign-accounting-except-zero + es-MX + 0.0 + +92,000 + -0.22 + zh-TW + 0.0 + +92,000 + -0.22 + bn-BD + ০.০ + +৯২,০০০ + -০.২২ + +unit-width-full-name precision-integer sign-accounting-except-zero + es-MX + 0 + +91,827 + -0 + zh-TW + 0 + +91,827 + -0 + bn-BD + ০ + +৯১,৮২৭ + -০ + +unit-width-full-name .000 sign-accounting-except-zero + es-MX + 0.000 + +91,827.364 + -0.222 + zh-TW + 0.000 + +91,827.364 + -0.222 + bn-BD + ০.০০০ + +৯১,৮২৭.৩৬৪ + -০.২২২ + +unit-width-full-name .##/@@@+ sign-accounting-except-zero + es-MX + 0 + +91,827.36 + -0.222 + zh-TW + 0 + +91,827.36 + -0.222 + bn-BD + ০ + +৯১,৮২৭.৩৬ + -০.২২২ + +unit-width-full-name @@ sign-accounting-except-zero + es-MX + 0.0 + +92,000 + -0.22 + zh-TW + 0.0 + +92,000 + -0.22 + bn-BD + ০.০ + +৯২,০০০ + -০.২২ + +unit-width-narrow precision-integer decimal-always + es-MX + 0. + 91,827. + -0. + zh-TW + 0. + 91,827. + -0. + bn-BD + ০. + ৯১,৮২৭. + -০. + +unit-width-narrow .000 decimal-always + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২২ + +unit-width-narrow .##/@@@+ decimal-always + es-MX + 0. + 91,827.36 + -0.222 + zh-TW + 0. + 91,827.36 + -0.222 + bn-BD + ০. + ৯১,৮২৭.৩৬ + -০.২২২ + +unit-width-narrow @@ decimal-always + es-MX + 0.0 + 92,000. + -0.22 + zh-TW + 0.0 + 92,000. + -0.22 + bn-BD + ০.০ + ৯২,০০০. + -০.২২ + +unit-width-full-name precision-integer decimal-always + es-MX + 0. + 91,827. + -0. + zh-TW + 0. + 91,827. + -0. + bn-BD + ০. + ৯১,৮২৭. + -০. + +unit-width-full-name .000 decimal-always + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২২ + +unit-width-full-name .##/@@@+ decimal-always + es-MX + 0. + 91,827.36 + -0.222 + zh-TW + 0. + 91,827.36 + -0.222 + bn-BD + ০. + ৯১,৮২৭.৩৬ + -০.২২২ + +unit-width-full-name @@ decimal-always + es-MX + 0.0 + 92,000. + -0.22 + zh-TW + 0.0 + 92,000. + -0.22 + bn-BD + ০.০ + ৯২,০০০. + -০.২২ + +unit-width-narrow rounding-mode-floor integer-width/##00 + es-MX + 00 + 1827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + ০০ + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-full-name rounding-mode-floor integer-width/##00 + es-MX + 00 + 1827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + ০০ + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-narrow rounding-mode-floor scale/0.5 + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + ০ + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-full-name rounding-mode-floor scale/0.5 + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + ০ + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-narrow rounding-mode-floor group-on-aligned + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + ০ + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-full-name rounding-mode-floor group-on-aligned + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + ০ + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-narrow rounding-mode-floor latin + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + 0 + 91,827.3645 + -0.22222 + +unit-width-full-name rounding-mode-floor latin + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + 0 + 91,827.3645 + -0.22222 + +unit-width-narrow rounding-mode-floor sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + ০ + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-full-name rounding-mode-floor sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + ০ + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-narrow rounding-mode-floor decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + ০. + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-full-name rounding-mode-floor decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + ০. + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-narrow integer-width/##00 scale/0.5 + es-MX + 00 + 5913.68225 + -00.11111 + zh-TW + 00 + 5,913.68225 + -00.11111 + bn-BD + ০০ + ৫,৯১৩.৬৮২২৫ + -০০.১১১১১ + +unit-width-full-name integer-width/##00 scale/0.5 + es-MX + 00 + 5913.68225 + -00.11111 + zh-TW + 00 + 5,913.68225 + -00.11111 + bn-BD + ০০ + ৫,৯১৩.৬৮২২৫ + -০০.১১১১১ + +unit-width-narrow integer-width/##00 group-on-aligned + es-MX + 00 + 1,827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + ০০ + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-full-name integer-width/##00 group-on-aligned + es-MX + 00 + 1,827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + ০০ + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-narrow integer-width/##00 latin + es-MX + 00 + 1827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + 00 + 1,827.3645 + -00.22222 + +unit-width-full-name integer-width/##00 latin + es-MX + 00 + 1827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + 00 + 1,827.3645 + -00.22222 + +unit-width-narrow integer-width/##00 sign-accounting-except-zero + es-MX + 00 + +1827.3645 + -00.22222 + zh-TW + 00 + +1,827.3645 + -00.22222 + bn-BD + ০০ + +১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-full-name integer-width/##00 sign-accounting-except-zero + es-MX + 00 + +1827.3645 + -00.22222 + zh-TW + 00 + +1,827.3645 + -00.22222 + bn-BD + ০০ + +১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-narrow integer-width/##00 decimal-always + es-MX + 00. + 1827.3645 + -00.22222 + zh-TW + 00. + 1,827.3645 + -00.22222 + bn-BD + ০০. + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-full-name integer-width/##00 decimal-always + es-MX + 00. + 1827.3645 + -00.22222 + zh-TW + 00. + 1,827.3645 + -00.22222 + bn-BD + ০০. + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +unit-width-narrow scale/0.5 group-on-aligned + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + ০ + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-full-name scale/0.5 group-on-aligned + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + ০ + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-narrow scale/0.5 latin + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + 0 + 45,913.68225 + -0.11111 + +unit-width-full-name scale/0.5 latin + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + 0 + 45,913.68225 + -0.11111 + +unit-width-narrow scale/0.5 sign-accounting-except-zero + es-MX + 0 + +45,913.68225 + -0.11111 + zh-TW + 0 + +45,913.68225 + -0.11111 + bn-BD + ০ + +৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-full-name scale/0.5 sign-accounting-except-zero + es-MX + 0 + +45,913.68225 + -0.11111 + zh-TW + 0 + +45,913.68225 + -0.11111 + bn-BD + ০ + +৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-narrow scale/0.5 decimal-always + es-MX + 0. + 45,913.68225 + -0.11111 + zh-TW + 0. + 45,913.68225 + -0.11111 + bn-BD + ০. + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-full-name scale/0.5 decimal-always + es-MX + 0. + 45,913.68225 + -0.11111 + zh-TW + 0. + 45,913.68225 + -0.11111 + bn-BD + ০. + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +unit-width-narrow group-on-aligned latin + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + 0 + 91,827.3645 + -0.22222 + +unit-width-full-name group-on-aligned latin + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + 0 + 91,827.3645 + -0.22222 + +unit-width-narrow group-on-aligned sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + ০ + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-full-name group-on-aligned sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + ০ + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-narrow group-on-aligned decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + ০. + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-full-name group-on-aligned decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + ০. + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-narrow latin sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + 0 + +91,827.3645 + -0.22222 + +unit-width-full-name latin sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + 0 + +91,827.3645 + -0.22222 + +unit-width-narrow latin decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + 0. + 91,827.3645 + -0.22222 + +unit-width-full-name latin decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + 0. + 91,827.3645 + -0.22222 + +unit-width-narrow sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827.3645 + -0.22222 + zh-TW + 0. + +91,827.3645 + -0.22222 + bn-BD + ০. + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +unit-width-full-name sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827.3645 + -0.22222 + zh-TW + 0. + +91,827.3645 + -0.22222 + bn-BD + ০. + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +precision-integer rounding-mode-floor integer-width/##00 + es-MX + 00 + 1827 + -01 + zh-TW + 00 + 1,827 + -01 + bn-BD + ০০ + ১,৮২৭ + -০১ + +.000 rounding-mode-floor integer-width/##00 + es-MX + 00.000 + 1827.364 + -00.223 + zh-TW + 00.000 + 1,827.364 + -00.223 + bn-BD + ০০.০০০ + ১,৮২৭.৩৬৪ + -০০.২২৩ + +.##/@@@+ rounding-mode-floor integer-width/##00 + es-MX + 00 + 1827.36 + -00.223 + zh-TW + 00 + 1,827.36 + -00.223 + bn-BD + ০০ + ১,৮২৭.৩৬ + -০০.২২৩ + +@@ rounding-mode-floor integer-width/##00 + es-MX + 00.0 + 1000 + -00.23 + zh-TW + 00.0 + 1,000 + -00.23 + bn-BD + ০০.০ + ১,০০০ + -০০.২৩ + +precision-integer rounding-mode-floor scale/0.5 + es-MX + 0 + 45,913 + -1 + zh-TW + 0 + 45,913 + -1 + bn-BD + ০ + ৪৫,৯১৩ + -১ + +.000 rounding-mode-floor scale/0.5 + es-MX + 0.000 + 45,913.682 + -0.112 + zh-TW + 0.000 + 45,913.682 + -0.112 + bn-BD + ০.০০০ + ৪৫,৯১৩.৬৮২ + -০.১১২ + +.##/@@@+ rounding-mode-floor scale/0.5 + es-MX + 0 + 45,913.68 + -0.112 + zh-TW + 0 + 45,913.68 + -0.112 + bn-BD + ০ + ৪৫,৯১৩.৬৮ + -০.১১২ + +@@ rounding-mode-floor scale/0.5 + es-MX + 0.0 + 45,000 + -0.12 + zh-TW + 0.0 + 45,000 + -0.12 + bn-BD + ০.০ + ৪৫,০০০ + -০.১২ + +precision-integer rounding-mode-floor group-on-aligned + es-MX + 0 + 91,827 + -1 + zh-TW + 0 + 91,827 + -1 + bn-BD + ০ + ৯১,৮২৭ + -১ + +.000 rounding-mode-floor group-on-aligned + es-MX + 0.000 + 91,827.364 + -0.223 + zh-TW + 0.000 + 91,827.364 + -0.223 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২৩ + +.##/@@@+ rounding-mode-floor group-on-aligned + es-MX + 0 + 91,827.36 + -0.223 + zh-TW + 0 + 91,827.36 + -0.223 + bn-BD + ০ + ৯১,৮২৭.৩৬ + -০.২২৩ + +@@ rounding-mode-floor group-on-aligned + es-MX + 0.0 + 91,000 + -0.23 + zh-TW + 0.0 + 91,000 + -0.23 + bn-BD + ০.০ + ৯১,০০০ + -০.২৩ + +precision-integer rounding-mode-floor latin + es-MX + 0 + 91,827 + -1 + zh-TW + 0 + 91,827 + -1 + bn-BD + 0 + 91,827 + -1 + +.000 rounding-mode-floor latin + es-MX + 0.000 + 91,827.364 + -0.223 + zh-TW + 0.000 + 91,827.364 + -0.223 + bn-BD + 0.000 + 91,827.364 + -0.223 + +.##/@@@+ rounding-mode-floor latin + es-MX + 0 + 91,827.36 + -0.223 + zh-TW + 0 + 91,827.36 + -0.223 + bn-BD + 0 + 91,827.36 + -0.223 + +@@ rounding-mode-floor latin + es-MX + 0.0 + 91,000 + -0.23 + zh-TW + 0.0 + 91,000 + -0.23 + bn-BD + 0.0 + 91,000 + -0.23 + +precision-integer rounding-mode-floor sign-accounting-except-zero + es-MX + 0 + +91,827 + -1 + zh-TW + 0 + +91,827 + -1 + bn-BD + ০ + +৯১,৮২৭ + -১ + +.000 rounding-mode-floor sign-accounting-except-zero + es-MX + 0.000 + +91,827.364 + -0.223 + zh-TW + 0.000 + +91,827.364 + -0.223 + bn-BD + ০.০০০ + +৯১,৮২৭.৩৬৪ + -০.২২৩ + +.##/@@@+ rounding-mode-floor sign-accounting-except-zero + es-MX + 0 + +91,827.36 + -0.223 + zh-TW + 0 + +91,827.36 + -0.223 + bn-BD + ০ + +৯১,৮২৭.৩৬ + -০.২২৩ + +@@ rounding-mode-floor sign-accounting-except-zero + es-MX + 0.0 + +91,000 + -0.23 + zh-TW + 0.0 + +91,000 + -0.23 + bn-BD + ০.০ + +৯১,০০০ + -০.২৩ + +precision-integer rounding-mode-floor decimal-always + es-MX + 0. + 91,827. + -1. + zh-TW + 0. + 91,827. + -1. + bn-BD + ০. + ৯১,৮২৭. + -১. + +.000 rounding-mode-floor decimal-always + es-MX + 0.000 + 91,827.364 + -0.223 + zh-TW + 0.000 + 91,827.364 + -0.223 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২৩ + +.##/@@@+ rounding-mode-floor decimal-always + es-MX + 0. + 91,827.36 + -0.223 + zh-TW + 0. + 91,827.36 + -0.223 + bn-BD + ০. + ৯১,৮২৭.৩৬ + -০.২২৩ + +@@ rounding-mode-floor decimal-always + es-MX + 0.0 + 91,000. + -0.23 + zh-TW + 0.0 + 91,000. + -0.23 + bn-BD + ০.০ + ৯১,০০০. + -০.২৩ + +precision-integer integer-width/##00 scale/0.5 + es-MX + 00 + 5914 + -00 + zh-TW + 00 + 5,914 + -00 + bn-BD + ০০ + ৫,৯১৪ + -০০ + +.000 integer-width/##00 scale/0.5 + es-MX + 00.000 + 5913.682 + -00.111 + zh-TW + 00.000 + 5,913.682 + -00.111 + bn-BD + ০০.০০০ + ৫,৯১৩.৬৮২ + -০০.১১১ + +.##/@@@+ integer-width/##00 scale/0.5 + es-MX + 00 + 5913.68 + -00.111 + zh-TW + 00 + 5,913.68 + -00.111 + bn-BD + ০০ + ৫,৯১৩.৬৮ + -০০.১১১ + +@@ integer-width/##00 scale/0.5 + es-MX + 00.0 + 6000 + -00.11 + zh-TW + 00.0 + 6,000 + -00.11 + bn-BD + ০০.০ + ৬,০০০ + -০০.১১ + +precision-integer integer-width/##00 group-on-aligned + es-MX + 00 + 1,827 + -00 + zh-TW + 00 + 1,827 + -00 + bn-BD + ০০ + ১,৮২৭ + -০০ + +.000 integer-width/##00 group-on-aligned + es-MX + 00.000 + 1,827.364 + -00.222 + zh-TW + 00.000 + 1,827.364 + -00.222 + bn-BD + ০০.০০০ + ১,৮২৭.৩৬৪ + -০০.২২২ + +.##/@@@+ integer-width/##00 group-on-aligned + es-MX + 00 + 1,827.36 + -00.222 + zh-TW + 00 + 1,827.36 + -00.222 + bn-BD + ০০ + ১,৮২৭.৩৬ + -০০.২২২ + +@@ integer-width/##00 group-on-aligned + es-MX + 00.0 + 2,000 + -00.22 + zh-TW + 00.0 + 2,000 + -00.22 + bn-BD + ০০.০ + ২,০০০ + -০০.২২ + +precision-integer integer-width/##00 latin + es-MX + 00 + 1827 + -00 + zh-TW + 00 + 1,827 + -00 + bn-BD + 00 + 1,827 + -00 + +.000 integer-width/##00 latin + es-MX + 00.000 + 1827.364 + -00.222 + zh-TW + 00.000 + 1,827.364 + -00.222 + bn-BD + 00.000 + 1,827.364 + -00.222 + +.##/@@@+ integer-width/##00 latin + es-MX + 00 + 1827.36 + -00.222 + zh-TW + 00 + 1,827.36 + -00.222 + bn-BD + 00 + 1,827.36 + -00.222 + +@@ integer-width/##00 latin + es-MX + 00.0 + 2000 + -00.22 + zh-TW + 00.0 + 2,000 + -00.22 + bn-BD + 00.0 + 2,000 + -00.22 + +precision-integer integer-width/##00 sign-accounting-except-zero + es-MX + 00 + +1827 + -00 + zh-TW + 00 + +1,827 + -00 + bn-BD + ০০ + +১,৮২৭ + -০০ + +.000 integer-width/##00 sign-accounting-except-zero + es-MX + 00.000 + +1827.364 + -00.222 + zh-TW + 00.000 + +1,827.364 + -00.222 + bn-BD + ০০.০০০ + +১,৮২৭.৩৬৪ + -০০.২২২ + +.##/@@@+ integer-width/##00 sign-accounting-except-zero + es-MX + 00 + +1827.36 + -00.222 + zh-TW + 00 + +1,827.36 + -00.222 + bn-BD + ০০ + +১,৮২৭.৩৬ + -০০.২২২ + +@@ integer-width/##00 sign-accounting-except-zero + es-MX + 00.0 + +2000 + -00.22 + zh-TW + 00.0 + +2,000 + -00.22 + bn-BD + ০০.০ + +২,০০০ + -০০.২২ + +precision-integer integer-width/##00 decimal-always + es-MX + 00. + 1827. + -00. + zh-TW + 00. + 1,827. + -00. + bn-BD + ০০. + ১,৮২৭. + -০০. + +.000 integer-width/##00 decimal-always + es-MX + 00.000 + 1827.364 + -00.222 + zh-TW + 00.000 + 1,827.364 + -00.222 + bn-BD + ০০.০০০ + ১,৮২৭.৩৬৪ + -০০.২২২ + +.##/@@@+ integer-width/##00 decimal-always + es-MX + 00. + 1827.36 + -00.222 + zh-TW + 00. + 1,827.36 + -00.222 + bn-BD + ০০. + ১,৮২৭.৩৬ + -০০.২২২ + +@@ integer-width/##00 decimal-always + es-MX + 00.0 + 2000. + -00.22 + zh-TW + 00.0 + 2,000. + -00.22 + bn-BD + ০০.০ + ২,০০০. + -০০.২২ + +precision-integer scale/0.5 group-on-aligned + es-MX + 0 + 45,914 + -0 + zh-TW + 0 + 45,914 + -0 + bn-BD + ০ + ৪৫,৯১৪ + -০ + +.000 scale/0.5 group-on-aligned + es-MX + 0.000 + 45,913.682 + -0.111 + zh-TW + 0.000 + 45,913.682 + -0.111 + bn-BD + ০.০০০ + ৪৫,৯১৩.৬৮২ + -০.১১১ + +.##/@@@+ scale/0.5 group-on-aligned + es-MX + 0 + 45,913.68 + -0.111 + zh-TW + 0 + 45,913.68 + -0.111 + bn-BD + ০ + ৪৫,৯১৩.৬৮ + -০.১১১ + +@@ scale/0.5 group-on-aligned + es-MX + 0.0 + 46,000 + -0.11 + zh-TW + 0.0 + 46,000 + -0.11 + bn-BD + ০.০ + ৪৬,০০০ + -০.১১ + +precision-integer scale/0.5 latin + es-MX + 0 + 45,914 + -0 + zh-TW + 0 + 45,914 + -0 + bn-BD + 0 + 45,914 + -0 + +.000 scale/0.5 latin + es-MX + 0.000 + 45,913.682 + -0.111 + zh-TW + 0.000 + 45,913.682 + -0.111 + bn-BD + 0.000 + 45,913.682 + -0.111 + +.##/@@@+ scale/0.5 latin + es-MX + 0 + 45,913.68 + -0.111 + zh-TW + 0 + 45,913.68 + -0.111 + bn-BD + 0 + 45,913.68 + -0.111 + +@@ scale/0.5 latin + es-MX + 0.0 + 46,000 + -0.11 + zh-TW + 0.0 + 46,000 + -0.11 + bn-BD + 0.0 + 46,000 + -0.11 + +precision-integer scale/0.5 sign-accounting-except-zero + es-MX + 0 + +45,914 + -0 + zh-TW + 0 + +45,914 + -0 + bn-BD + ০ + +৪৫,৯১৪ + -০ + +.000 scale/0.5 sign-accounting-except-zero + es-MX + 0.000 + +45,913.682 + -0.111 + zh-TW + 0.000 + +45,913.682 + -0.111 + bn-BD + ০.০০০ + +৪৫,৯১৩.৬৮২ + -০.১১১ + +.##/@@@+ scale/0.5 sign-accounting-except-zero + es-MX + 0 + +45,913.68 + -0.111 + zh-TW + 0 + +45,913.68 + -0.111 + bn-BD + ০ + +৪৫,৯১৩.৬৮ + -০.১১১ + +@@ scale/0.5 sign-accounting-except-zero + es-MX + 0.0 + +46,000 + -0.11 + zh-TW + 0.0 + +46,000 + -0.11 + bn-BD + ০.০ + +৪৬,০০০ + -০.১১ + +precision-integer scale/0.5 decimal-always + es-MX + 0. + 45,914. + -0. + zh-TW + 0. + 45,914. + -0. + bn-BD + ০. + ৪৫,৯১৪. + -০. + +.000 scale/0.5 decimal-always + es-MX + 0.000 + 45,913.682 + -0.111 + zh-TW + 0.000 + 45,913.682 + -0.111 + bn-BD + ০.০০০ + ৪৫,৯১৩.৬৮২ + -০.১১১ + +.##/@@@+ scale/0.5 decimal-always + es-MX + 0. + 45,913.68 + -0.111 + zh-TW + 0. + 45,913.68 + -0.111 + bn-BD + ০. + ৪৫,৯১৩.৬৮ + -০.১১১ + +@@ scale/0.5 decimal-always + es-MX + 0.0 + 46,000. + -0.11 + zh-TW + 0.0 + 46,000. + -0.11 + bn-BD + ০.০ + ৪৬,০০০. + -০.১১ + +precision-integer group-on-aligned latin + es-MX + 0 + 91,827 + -0 + zh-TW + 0 + 91,827 + -0 + bn-BD + 0 + 91,827 + -0 + +.000 group-on-aligned latin + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + 0.000 + 91,827.364 + -0.222 + +.##/@@@+ group-on-aligned latin + es-MX + 0 + 91,827.36 + -0.222 + zh-TW + 0 + 91,827.36 + -0.222 + bn-BD + 0 + 91,827.36 + -0.222 + +@@ group-on-aligned latin + es-MX + 0.0 + 92,000 + -0.22 + zh-TW + 0.0 + 92,000 + -0.22 + bn-BD + 0.0 + 92,000 + -0.22 + +precision-integer group-on-aligned sign-accounting-except-zero + es-MX + 0 + +91,827 + -0 + zh-TW + 0 + +91,827 + -0 + bn-BD + ০ + +৯১,৮২৭ + -০ + +.000 group-on-aligned sign-accounting-except-zero + es-MX + 0.000 + +91,827.364 + -0.222 + zh-TW + 0.000 + +91,827.364 + -0.222 + bn-BD + ০.০০০ + +৯১,৮২৭.৩৬৪ + -০.২২২ + +.##/@@@+ group-on-aligned sign-accounting-except-zero + es-MX + 0 + +91,827.36 + -0.222 + zh-TW + 0 + +91,827.36 + -0.222 + bn-BD + ০ + +৯১,৮২৭.৩৬ + -০.২২২ + +@@ group-on-aligned sign-accounting-except-zero + es-MX + 0.0 + +92,000 + -0.22 + zh-TW + 0.0 + +92,000 + -0.22 + bn-BD + ০.০ + +৯২,০০০ + -০.২২ + +precision-integer group-on-aligned decimal-always + es-MX + 0. + 91,827. + -0. + zh-TW + 0. + 91,827. + -0. + bn-BD + ০. + ৯১,৮২৭. + -০. + +.000 group-on-aligned decimal-always + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + ০.০০০ + ৯১,৮২৭.৩৬৪ + -০.২২২ + +.##/@@@+ group-on-aligned decimal-always + es-MX + 0. + 91,827.36 + -0.222 + zh-TW + 0. + 91,827.36 + -0.222 + bn-BD + ০. + ৯১,৮২৭.৩৬ + -০.২২২ + +@@ group-on-aligned decimal-always + es-MX + 0.0 + 92,000. + -0.22 + zh-TW + 0.0 + 92,000. + -0.22 + bn-BD + ০.০ + ৯২,০০০. + -০.২২ + +precision-integer latin sign-accounting-except-zero + es-MX + 0 + +91,827 + -0 + zh-TW + 0 + +91,827 + -0 + bn-BD + 0 + +91,827 + -0 + +.000 latin sign-accounting-except-zero + es-MX + 0.000 + +91,827.364 + -0.222 + zh-TW + 0.000 + +91,827.364 + -0.222 + bn-BD + 0.000 + +91,827.364 + -0.222 + +.##/@@@+ latin sign-accounting-except-zero + es-MX + 0 + +91,827.36 + -0.222 + zh-TW + 0 + +91,827.36 + -0.222 + bn-BD + 0 + +91,827.36 + -0.222 + +@@ latin sign-accounting-except-zero + es-MX + 0.0 + +92,000 + -0.22 + zh-TW + 0.0 + +92,000 + -0.22 + bn-BD + 0.0 + +92,000 + -0.22 + +precision-integer latin decimal-always + es-MX + 0. + 91,827. + -0. + zh-TW + 0. + 91,827. + -0. + bn-BD + 0. + 91,827. + -0. + +.000 latin decimal-always + es-MX + 0.000 + 91,827.364 + -0.222 + zh-TW + 0.000 + 91,827.364 + -0.222 + bn-BD + 0.000 + 91,827.364 + -0.222 + +.##/@@@+ latin decimal-always + es-MX + 0. + 91,827.36 + -0.222 + zh-TW + 0. + 91,827.36 + -0.222 + bn-BD + 0. + 91,827.36 + -0.222 + +@@ latin decimal-always + es-MX + 0.0 + 92,000. + -0.22 + zh-TW + 0.0 + 92,000. + -0.22 + bn-BD + 0.0 + 92,000. + -0.22 + +precision-integer sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827. + -0. + zh-TW + 0. + +91,827. + -0. + bn-BD + ০. + +৯১,৮২৭. + -০. + +.000 sign-accounting-except-zero decimal-always + es-MX + 0.000 + +91,827.364 + -0.222 + zh-TW + 0.000 + +91,827.364 + -0.222 + bn-BD + ০.০০০ + +৯১,৮২৭.৩৬৪ + -০.২২২ + +.##/@@@+ sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827.36 + -0.222 + zh-TW + 0. + +91,827.36 + -0.222 + bn-BD + ০. + +৯১,৮২৭.৩৬ + -০.২২২ + +@@ sign-accounting-except-zero decimal-always + es-MX + 0.0 + +92,000. + -0.22 + zh-TW + 0.0 + +92,000. + -0.22 + bn-BD + ০.০ + +৯২,০০০. + -০.২২ + +rounding-mode-floor integer-width/##00 scale/0.5 + es-MX + 00 + 5913.68225 + -00.11111 + zh-TW + 00 + 5,913.68225 + -00.11111 + bn-BD + ০০ + ৫,৯১৩.৬৮২২৫ + -০০.১১১১১ + +rounding-mode-floor integer-width/##00 group-on-aligned + es-MX + 00 + 1,827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + ০০ + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +rounding-mode-floor integer-width/##00 latin + es-MX + 00 + 1827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + 00 + 1,827.3645 + -00.22222 + +rounding-mode-floor integer-width/##00 sign-accounting-except-zero + es-MX + 00 + +1827.3645 + -00.22222 + zh-TW + 00 + +1,827.3645 + -00.22222 + bn-BD + ০০ + +১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +rounding-mode-floor integer-width/##00 decimal-always + es-MX + 00. + 1827.3645 + -00.22222 + zh-TW + 00. + 1,827.3645 + -00.22222 + bn-BD + ০০. + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +rounding-mode-floor scale/0.5 group-on-aligned + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + ০ + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +rounding-mode-floor scale/0.5 latin + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + 0 + 45,913.68225 + -0.11111 + +rounding-mode-floor scale/0.5 sign-accounting-except-zero + es-MX + 0 + +45,913.68225 + -0.11111 + zh-TW + 0 + +45,913.68225 + -0.11111 + bn-BD + ০ + +৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +rounding-mode-floor scale/0.5 decimal-always + es-MX + 0. + 45,913.68225 + -0.11111 + zh-TW + 0. + 45,913.68225 + -0.11111 + bn-BD + ০. + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +rounding-mode-floor group-on-aligned latin + es-MX + 0 + 91,827.3645 + -0.22222 + zh-TW + 0 + 91,827.3645 + -0.22222 + bn-BD + 0 + 91,827.3645 + -0.22222 + +rounding-mode-floor group-on-aligned sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + ০ + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +rounding-mode-floor group-on-aligned decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + ০. + ৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +rounding-mode-floor latin sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + 0 + +91,827.3645 + -0.22222 + +rounding-mode-floor latin decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + 0. + 91,827.3645 + -0.22222 + +rounding-mode-floor sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827.3645 + -0.22222 + zh-TW + 0. + +91,827.3645 + -0.22222 + bn-BD + ০. + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +integer-width/##00 scale/0.5 group-on-aligned + es-MX + 00 + 5,913.68225 + -00.11111 + zh-TW + 00 + 5,913.68225 + -00.11111 + bn-BD + ০০ + ৫,৯১৩.৬৮২২৫ + -০০.১১১১১ + +integer-width/##00 scale/0.5 latin + es-MX + 00 + 5913.68225 + -00.11111 + zh-TW + 00 + 5,913.68225 + -00.11111 + bn-BD + 00 + 5,913.68225 + -00.11111 + +integer-width/##00 scale/0.5 sign-accounting-except-zero + es-MX + 00 + +5913.68225 + -00.11111 + zh-TW + 00 + +5,913.68225 + -00.11111 + bn-BD + ০০ + +৫,৯১৩.৬৮২২৫ + -০০.১১১১১ + +integer-width/##00 scale/0.5 decimal-always + es-MX + 00. + 5913.68225 + -00.11111 + zh-TW + 00. + 5,913.68225 + -00.11111 + bn-BD + ০০. + ৫,৯১৩.৬৮২২৫ + -০০.১১১১১ + +integer-width/##00 group-on-aligned latin + es-MX + 00 + 1,827.3645 + -00.22222 + zh-TW + 00 + 1,827.3645 + -00.22222 + bn-BD + 00 + 1,827.3645 + -00.22222 + +integer-width/##00 group-on-aligned sign-accounting-except-zero + es-MX + 00 + +1,827.3645 + -00.22222 + zh-TW + 00 + +1,827.3645 + -00.22222 + bn-BD + ০০ + +১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +integer-width/##00 group-on-aligned decimal-always + es-MX + 00. + 1,827.3645 + -00.22222 + zh-TW + 00. + 1,827.3645 + -00.22222 + bn-BD + ০০. + ১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +integer-width/##00 latin sign-accounting-except-zero + es-MX + 00 + +1827.3645 + -00.22222 + zh-TW + 00 + +1,827.3645 + -00.22222 + bn-BD + 00 + +1,827.3645 + -00.22222 + +integer-width/##00 latin decimal-always + es-MX + 00. + 1827.3645 + -00.22222 + zh-TW + 00. + 1,827.3645 + -00.22222 + bn-BD + 00. + 1,827.3645 + -00.22222 + +integer-width/##00 sign-accounting-except-zero decimal-always + es-MX + 00. + +1827.3645 + -00.22222 + zh-TW + 00. + +1,827.3645 + -00.22222 + bn-BD + ০০. + +১,৮২৭.৩৬৪৫ + -০০.২২২২২ + +scale/0.5 group-on-aligned latin + es-MX + 0 + 45,913.68225 + -0.11111 + zh-TW + 0 + 45,913.68225 + -0.11111 + bn-BD + 0 + 45,913.68225 + -0.11111 + +scale/0.5 group-on-aligned sign-accounting-except-zero + es-MX + 0 + +45,913.68225 + -0.11111 + zh-TW + 0 + +45,913.68225 + -0.11111 + bn-BD + ০ + +৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +scale/0.5 group-on-aligned decimal-always + es-MX + 0. + 45,913.68225 + -0.11111 + zh-TW + 0. + 45,913.68225 + -0.11111 + bn-BD + ০. + ৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +scale/0.5 latin sign-accounting-except-zero + es-MX + 0 + +45,913.68225 + -0.11111 + zh-TW + 0 + +45,913.68225 + -0.11111 + bn-BD + 0 + +45,913.68225 + -0.11111 + +scale/0.5 latin decimal-always + es-MX + 0. + 45,913.68225 + -0.11111 + zh-TW + 0. + 45,913.68225 + -0.11111 + bn-BD + 0. + 45,913.68225 + -0.11111 + +scale/0.5 sign-accounting-except-zero decimal-always + es-MX + 0. + +45,913.68225 + -0.11111 + zh-TW + 0. + +45,913.68225 + -0.11111 + bn-BD + ০. + +৪৫,৯১৩.৬৮২২৫ + -০.১১১১১ + +group-on-aligned latin sign-accounting-except-zero + es-MX + 0 + +91,827.3645 + -0.22222 + zh-TW + 0 + +91,827.3645 + -0.22222 + bn-BD + 0 + +91,827.3645 + -0.22222 + +group-on-aligned latin decimal-always + es-MX + 0. + 91,827.3645 + -0.22222 + zh-TW + 0. + 91,827.3645 + -0.22222 + bn-BD + 0. + 91,827.3645 + -0.22222 + +group-on-aligned sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827.3645 + -0.22222 + zh-TW + 0. + +91,827.3645 + -0.22222 + bn-BD + ০. + +৯১,৮২৭.৩৬৪৫ + -০.২২২২২ + +latin sign-accounting-except-zero decimal-always + es-MX + 0. + +91,827.3645 + -0.22222 + zh-TW + 0. + +91,827.3645 + -0.22222 + bn-BD + 0. + +91,827.3645 + -0.22222 + diff -Nru icu-64.2/source/test/testdata/rbbitst.txt icu-65.1/source/test/testdata/rbbitst.txt --- icu-64.2/source/test/testdata/rbbitst.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/rbbitst.txt 2019-10-03 11:16:41.000000000 +0000 @@ -164,6 +164,498 @@ # #•\u0e40\u0e01•\u0e44\u0301\u0e23\u0302\u0303•\u0e40•\u0e40\u0e02•\u0e02• • +# +# ICU-13637 and CLDR-10994 - Indic Grapheme Cluster Boundary changes to support aksaras +# New rule: LinkingConsonant ExtCccZwj* Virama ExtCccZwj* × LinkingConsonant +# Sample Chars: LinkingConsonant: \u0915 +# Virama: \u094d [also Extend] +# ExtCccZWJ: \u0308 +# Extend but not ExtCCCZWJ \u093A + +•\u0915\u094d\u0915• +•\u0915\u0308\u0308\u094d\u0308\u0308\u0915• +•\u0915\u0308\u0308\u094d\u0308\u0308•\u0041• +•\u0915\u0308\u0308\u094d\u093A\u093A•\u0915• + +# +# From cldr/common/testData/segmentation/graphemeCluster/TestSegmenter-Bengali.txt +# + +# ব্যক্তিত্বের ; +•ব্য•ক্তি•ত্বে•র• +# আত্মবিশ্বাস ; +•আ•ত্ম•বি•শ্বা•স• +# ব্যাক্টেরিয়া ; +•ব্যা•ক্টে•রি•য়া• +# সমস্যার ; +•স•ম•স্যা•র• +# মিশ্রণ ; +•মি•শ্র•ণ• +# দুর্গন্ধ ; +•দু•র্গ•ন্ধ• +# পরীক্ষার ; +•প•রী•ক্ষা•র• +# কোলেস্টেরল ; +•কো•লে•স্টে•র•ল• +# ব্যায়ামকে ; +•ব্যা•য়া•ম•কে• +# সপ্তাহে ; +•স•প্তা•হে• +# পরীক্ষার ; +•প•রী•ক্ষা•র• +# চর্বিজাতীয় ; +•চ•র্বি•জা•তী•য়• +# নিয়ণ্ত্রণ ; +•নি•য়•ণ্ত্র•ণ• +# অবশ্যই ; +•অ•ব•শ্য•ই• +# নয়াদিল্লির ; +•ন•য়া•দি•ল্লি•র• +# সমীক্ষাটা ; +•স•মী•ক্ষা•টা• +# #ভূমিকম্পের ; +# •ভূ•মি•ক•ম্পের• # line 17 in TestSegmenter-Bengali.txt +# কেন্দ্রীয় ; +•কে•ন্দ্রী•য়• +# উস্কানিই ; +•উ•স্কা•নি•ই• +# সমীক্ষকরা ; +•স•মী•ক্ষ•ক•রা• +# মুহূর্তে ; +•মু•হূ•র্তে• +# সম্পর্কে ; +•স•ম্প•র্কে• +# পৌষসংক্রান্তির ; +•পৌ•ষ•সং•ক্রা•ন্তি•র• +# মুখ্যমন্ত্রী ; +•মু•খ্য•ম•ন্ত্রী• + +# +# from cldr/common/testData/segmentation/graphemeCluster/TestSegmenter-Devanagari.txt +# + +# संदिग्ध ; +•सं•दि•ग्ध• +# सुरक्षा ; +•सु•र•क्षा• +# टक्कर ; +•ट•क्क•र• +# सत्र ; +•स•त्र• +# दक्षिण ; +•द•क्षि•ण• +# मिश्रणाने ; +•मि•श्र•णा•ने• +# दुर्घटनाग्रस्त ; +•दु•र्घ•ट•ना•ग्र•स्त• +# मुहूर्त ; +•मु•हू•र्त• +# शर्करायुक्त ; +•श•र्क•रा•यु•क्त• +# अंतरराष्ट्रीय ; +•अं•त•र•रा•ष्ट्री•य• +# राष्ट्रपति ; +•रा•ष्ट्र•प•ति• +# फ्रांस ; +•फ्रां•स• +# ट्रैक्टर ; +•ट्रै•क्ट•र• +# सिट्रोनेलाचे ; +•सि•ट्रो•ने•ला•चे• +# टुक्रालाई ; +•टु•क्रा•ला•ई• +# इकट्ठा ; +•इ•क•ट्ठा• +# शास्त्र ; +•शा•स्त्र• +# स्त्री ; +•स्त्री• +# लक्ष्य ; +•ल•क्ष्य• +# तीक्ष्ण ; +•ती•क्ष्ण• +# Words ; +•W•o•r•d•s• +# त्रिवेदी ; +•त्रि•वे•दी• +# कृत्रिम ; +•कृ•त्रि•म• +# मात्रामा ; +•मा•त्रा•मा• +# सिद्धार्थनगर ; +•सि•द्धा•र्थ•न•ग•र• +# श्रद्धालुओं ; +•श्र•द्धा•लु•ओं• +# वृद्धिसँग ; +•वृ•द्धि•सँ•ग• +# अंतःज्ञानी ; +•अं•तः•ज्ञा•नी•• +# गन्नदी॑धिम ; +•ग•न्न•दी॑•धि•म• +# प्प्रप॑द्ये॒ ; +•प्प्र•प॑•द्ये॒• +# मनस्तापः ; +•म•न•स्ता•पः• +# हविष्करोमि ; +•ह•वि•ष्क•रो•मि• +# अहर्पतिः ; +•अ•ह•र्प•तिः• +# गच्छति ; +•ग•च्छ•ति• +# अयम् ; +•अ•य•म्• +# शिवश्चोदति ; +•शि•व•श्चो•द•ति• +# मनष्टालयति ; +•म•न•ष्टा•ल•य•ति• +# अश्वष्ठक्कस्य ; +•अ•श्व•ष्ठ•क्क•स्य• +# दुष्पुत्रः ; +•दु•ष्पु•त्रः• +# द्विःपक्वम् ; +•द्विः•प•क्व•म्• +# द्विष्कामः ; +•द्वि•ष्का•मः• +# भर्तुर्भोगः ; +•भ•र्तु•र्भो•गः• +# शॆत्युल ; +•शॆ•त्यु•ल•• +# महारॆन्य ; +•म•हा•रॆ•न्य• +# सॆक्युल ; +•सॆ•क्यु•ल• +# ल्यॊदुर ; +•ल्यॊ•दु•र• +# फयॊक ; +•फ•यॊ•क• +# मॊहन्युव ; +•मॊ•ह•न्यु•व• +# अन्यर ; +•अ•न्य•र• +# ख्वजि ; +•ख्व•जि• +# खॅरिन्य ; +•खॅ•रि•न्य• +# उच्छ्वास ; +•उ•च्छ्वा•स• +# व्यक्तिमत्व ; +•व्य•क्ति•म•त्व• +# दातांच्यामध्ये ; +•दा•तां•च्या•म•ध्ये• +# दुर्गंधी ; +•दु•र्गं•धी• +# दुर्गंधीपासूनसुद्धा ; +•दु•र्गं•धी•पा•सू•न•सु•द्धा• +# नित्यकर्मामध्ये ; +•नि•त्य•क•र्मा•म•ध्ये• +# आजारांपासूनसुद्धा ; +•आ•जा•रां•पा•सू•न•सु•द्धा• +# भाज्यांमध्ये ; +•भा•ज्यां•म•ध्ये• +# उच्छ्वासाच्या ; +•उ•च्छ्वा•सा•च्या• +# सुकिल्लीं ; +•सु•कि•ल्लीं• +# स्लिपां ; +•स्लि•पां• +# मिसळिल्ल्यान ; +•मि•स•ळि•ल्ल्या•न• +# रोंप्यांची ; +•रों•प्यां•ची• +# वर्सांतल्यान ; +•व•र्सां•त•ल्या•न• +# रोंप्याच्या ; +•रों•प्या•च्या• +# नाशिल्ल्यान ; +•ना•शि•ल्ल्या•न• +# जिल्ल्याच्या ; +•जि•ल्ल्या•च्या• +# कुरुक्षेत्रांतल्या ; +•कु•रु•क्षे•त्रां•त•ल्या• +# भाज्ज्यांची ; +•भा•ज्ज्यां•ची• +# सिट्रोनेलाका ; +•सि•ट्रो•ने•ला•का• +# गरिनुपर्छ ; +•ग•रि•नु•प•र्छ• +# सामान्यतः ; +•सा•मा•न्य•तः• +# वृद्धिसँग ; +•वृ•द्धि•सँ•ग• +# रिपोर्टनि ; +•रि•पो•र्ट•नि• +# टोस्टर्ज़ ; +•टो•स्ट•र्ज़• +# वक्तव्य ; +•व•क्त•व्य• +# प्रक्रिया ; +•प्र•क्रि•या• +# निर्दिष्ट ; +•नि•र्दि•ष्ट• +# अस्वीकृत ; +•अ•स्वी•कृ•त• +# प्रयोक्ता ; +•प्र•यो•क्ता• +# प्रकार्यक ; +•प्र•का•र्य•क• +# ट्रेक्टरु ; +•ट्रे•क्ट•रु• +# स्थानधारक ; +•स्था•न•धा•र•क• +# प्रकार्यक ; +•प्र•का•र्य•क• +# अनुच्छेदसँ ; +•अ•नु•च्छे•द•सँ• +# गर्मीपदु ; +•ग•र्मी•प•दु• +# शास्त्रु ; +•शा•स्त्रु• +# इन्द्री ; +•इ•न्द्री• +# श्रधालू ; +•श्र•धा•लू• +# आस्तिकु ; +•आ•स्ति•कु• +# सकार्थो ; +•स•का•र्थो• +# सन्ॿंधु ; +•स•न्ॿं•धु• +# मनुक्खो ; +•म•नु•क्खो• +# हानिफ्राय ; +•हा•नि•फ्रा•य• +# दैथाइहरग्रा ; +•दै•था•इ•ह•र•ग्रा• +# बोसोरब्रै ; +•बो•सो•र•ब्रै• +# रांखान्थियारि ; +•रां•खा•न्थि•या•रि• +# खान्थियाव ; +•खा•न्थि•या•व• +# स्लिप्स ; +•स्लि•प्स• + +# +# cldr/common/testData/segmentation/graphemeCluster/TestSegmenter-Gujarati.txt +# + +# અંગ્રેજી ; +•અં•ગ્રે•જી• +# શબ્દકોશ ; +•શ•બ્દ•કો•શ• +# બાપ્તિસ્મા ; +•બા•પ્તિ•સ્મા• +# મિસ્ત્રી ; +•મિ•સ્ત્રી• +# સિક્કા ; +•સિ•ક્કા• +#6 ; એકત્રીસમું ; એ÷કત્રી÷સ÷મું + +# સ્વસ્થાને ; +•સ્વ•સ્થા•ને• +# પ્રશ્નાર્થ ; +•પ્ર•શ્ના•ર્થ• +# વર્તમાનકૃદંત ; +•વ•ર્ત•મા•ન•કૃ•દં•ત• +# વાક્યની ; +•વા•ક્ય•ની• +# સાર્વજનિક ; +•સા•ર્વ•જ•નિ•ક• +# સમાપ્તિ ; +•સ•મા•પ્તિ• +# પધાર્યા ; +•પ•ધા•ર્યા• +# વ્યક્તિત્વને ; +•વ્ય•ક્તિ•ત્વ•ને• +# આત્મવિશ્વાસ ; +•આ•ત્મ•વિ•શ્વા•સ• +# વ્યાયામથી ; +•વ્યા•યા•મ•થી• +# યુક્ત ; +•યુ•ક્ત• +# #18 ; પુરુષોત્તમ ; +•પ•રુ•ષો•ત્ત•મ• +# કેન્દ્રીય ; +•કે•ન્દ્રી•ય• +# ક્ષત્રિય ; +•ક્ષ•ત્રિ•ય• +# ફોર્મ્યુલા ; +•ફો•ર્મ્યુ•લા• +# કેન્દ્રમાં ; +•કે•ન્દ્ર•માં• +# સ્પ્રિંગ ; +•સ્પ્રિં•ગ• +# પ્રારંભ ; +•પ્રા•રં•ભ• +# વિદ્યાર્થીઓ ; +•વિ•દ્યા•ર્થી•ઓ• +# સ્વાર્થની ; +•સ્વા•ર્થ•ની• +# લોન્ગયરબ્યેન ; +•લો•ન્ગ•ય•ર•બ્યે•ન• +# સ્થાનિક ; +•સ્થા•નિ•ક• +# બિલ્ડિંગની ; +•બિ•લ્ડિં•ગ•ની• +# ઉત્પાદક ; +•ઉ•ત્પા•દ•ક• +# ઝૂકાવ્યું ; +•ઝૂ•કા•વ્યું• +# પ્રપૌત્ર ; +•પ્ર•પૌ•ત્ર• + + +# +# cldr/common/testData/segmentation/graphemeCluster/TestSegmenter-Malayalam.txt +# + +# സ്ഥാനമൊഴിയുക ; +•സ്ഥാ•ന•മൊ•ഴി•യു•ക• +# വ്യക്തി ; +•വ്യ•ക്തി• +# കൗമാരക്കാരി ; +•കൗ•മാ•ര•ക്കാ•രി• +# കല്യാണം ; +•ക•ല്യാ•ണം• +# റദ്ദാക്കിയ ; +•റ•ദ്ദാ•ക്കി•യ• +# വ്യാപിക്കുക ; +•വ്യാ•പി•ക്കു•ക• +# സ്തുതി ; +•സ്തു•തി• +# ഭക്ഷ്യസുരക്ഷ ; +•ഭ•ക്ഷ്യ•സു•ര•ക്ഷ• +# പൂഴ്ത്തിവെക്കുക ; +•പൂ•ഴ്ത്തി•വെ•ക്കു•ക• +# നിശ്ചയിച്ച ; +•നി•ശ്ച•യി•ച്ച• +# പ്രശ്നം ; +•പ്ര•ശ്നം• +# സംസ്ഥാനം ; +•സം•സ്ഥാ•നം• +# പ്രോത്സാഹം ; +•പ്രോ•ത്സാ•ഹം• +# ഉദ്യോഗസ്ഥ ; +•ഉ•ദ്യോ•ഗ•സ്ഥ• +# സ്ഥാപനം ; +•സ്ഥാ•പ•നം• +# അത്ഭുതം ; +•അ•ത്ഭു•തം• +# പ്രഖ്യാപനം ; +•പ്ര•ഖ്യാ•പ•നം• + +# +# cldr/common/testData/segmentation/graphemeCluster/TestSegmenter-Odia.txt +# + +# ଅସ୍ବରାନ୍ତ ; +•ଅ•ସ୍ବ•ରା•ନ୍ତ• +# ଅକର୍ମଣ୍ୟତା ; +•ଅ•କ•ର୍ମ•ଣ୍ୟ•ତା• +# ଅକର୍ମା ; +•ଅ•କ•ର୍ମା• +# ଆକର୍ଣ୍ଣ ; +•ଆ•କ•ର୍ଣ୍ଣ• +# ଆକସ୍ମିକୀ ; +•ଆ•କ•ସ୍ମି•କୀ• +# ଇଞ୍ଚମନୌତୀ ; +•ଇ•ଞ୍ଚ•ମ•ନୌ•ତୀ• +# ଅଗତ୍ୟା ; +•ଅ•ଗ•ତ୍ୟା• +# ଇନ୍ଦ୍ରଧ୍ବଜ ; +•ଇ•ନ୍ଦ୍ର•ଧ୍ବ•ଜ• +# ଊରୁତ୍ରାଣ ; +•ଊ•ରୁ•ତ୍ରା•ଣ• +# ଐଶ୍ବର୍ଯ୍ୟ ; +•ଐ•ଶ୍ବ•ର୍ଯ୍ୟ• +# ଅଗତ୍ୟା ; +•ଅ•ଗ•ତ୍ୟା• +# ଔପନ୍ୟାସିକ ; +•ଔ•ପ•ନ୍ୟା•ସି•କ• +# ଔଷ୍ଠ୍ୟ ; +•ଔ•ଷ୍ଠ୍ୟ• +# ଯଜୁର୍ବେଦୀ ; +•ଯ•ଜୁ•ର୍ବେ•ଦୀ• +# ପକ୍ଷ୍ମ ; +•ପ•କ୍ଷ୍ମ• +# ପଞ୍ଚଭୌତିକ ; +•ପ•ଞ୍ଚ•ଭୌ•ତି•କ• +# ତନ୍ତ୍ରିକାତନ୍ତ୍ର ; +•ତ•ନ୍ତ୍ରି•କା•ତ•ନ୍ତ୍ର• +# ସ୍ନାୟୁତନ୍ତ୍ର ; +•ସ୍ନା•ୟୁ•ତ•ନ୍ତ୍ର• +# ତପ୍ତକୁଣ୍ଡ ; +•ତ•ପ୍ତ•କୁ•ଣ୍ଡ• +# ଚଣ୍ଡୋଦରୀ ; +•ଚ•ଣ୍ଡୋ•ଦ•ରୀ• +# ଝଙ୍କାର ; +•ଝ•ଙ୍କା•ର• +# କଙ୍କପୃଷ୍ଠୀ ; +•କ•ଙ୍କ•ପୃ•ଷ୍ଠୀ• +# ଖଣ୍ଡନୀୟ ; +•ଖ•ଣ୍ଡ•ନୀ•ୟ• +# ଖମ୍ଭାବତୀ ; +•ଖ•ମ୍ଭା•ବ•ତୀ• +# ଘାଣେନ୍ଦ୍ରିୟ ; +•ଘା•ଣେ•ନ୍ଦ୍ରି•ୟ• +# ଘୁଞ୍ଚାଇବା ; +•ଘୁ•ଞ୍ଚା•ଇ•ବା• + +# +# cldr/common/testData/segmentation/graphemeCluster/TestSegmenter-Telugu.txt +# + +# అదృశ్యం ; +•అ•దృ•శ్యం• +# ఉద్యోగాలు ; +•ఉ•ద్యో•గా•లు• +# ఉన్నాయన్న ; +•ఉ•న్నా•య•న్న• +# కార్యదర్శి ; +•కా•ర్య•ద•ర్శి• +# సామర్థ్యం ; +•సా•మ•ర్థ్యం• +# అభిప్రాయం ; +•అ•భి•ప్రా•యం• +# రాష్ట్రస్థాయి ; +•రా•ష్ట్ర•స్థా•యి• +# నిర్లక్ష్యం ; +•ని•ర్ల•క్ష్యం• +# వ్యాజ్యాలన్నీ ; +•వ్యా•జ్యా•ల•న్నీ• +# న్యాయవ్యవస్థ ; +•న్యా•య•వ్య•వ•స్థ• +# వ్యాఖ్యలు ; +•వ్యా•ఖ్య•లు• +# నేతృత్వం ; +•నే•తృ•త్వం• +# ఉద్రిక్తత ; +•ఉ•ద్రి•క్త•త• +# వ్యాఖ్యలు ; +•వ్యా•ఖ్య•లు• +# అత్యున్నత ; +•అ•త్యు•న్న•త• +# మనస్పర్ధలు ; +•మ•న•స్ప•ర్ధ•లు• +# కార్యక్రమం ; +•కా•ర్య•క్ర•మం• +# గుప్పిస్తున్నారు ; +•గు•ప్పి•స్తు•న్నా•రు• +# నటిస్తున్నారు ; +•న•టి•స్తు•న్నా•రు• +# ద్వితీయార్ధం ; +•ద్వి•తీ•యా•ర్ధం• +# జీర్ణవ్యవస్థ ; +•జీ•ర్ణ•వ్య•వ•స్థ• +# ఉత్సాహం ; +•ఉ•త్సా•హం• +# హృద్రోగాలు ; +•హృ•ద్రో•గా•లు• +# పాల్గొనాల్సింది ; +•పా•ల్గొ•నా•ల్సిం•ది• +# మార్గదర్శకాలు ; +•మా•ర్గ•ద•ర్శ•కా•లు• + ######################################################################################## # diff -Nru icu-64.2/source/test/testdata/regextst.txt icu-65.1/source/test/testdata/regextst.txt --- icu-64.2/source/test/testdata/regextst.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/regextst.txt 2019-10-03 11:16:41.000000000 +0000 @@ -89,6 +89,28 @@ "abc(?!def)" b "<0>abcxyz" # +# Nested Lookahead / Behind +# +"one(?=(?:(?!).)*)" "<0>one stuff" +"one(?=(?:(?!).)*)" "one " + +# More nesting lookaround: pattern matches "qq" when not preceded by 'a' and followed by 'z' +"(?qqc" +"(?qqc" +"(?A<0>jk<2>B" +"(?=(?<=(\p{Lu})(?=..(\p{Lu})))).." "ajkB" +"(?=(?<=(\p{Lu})(?=..(\p{Lu})))).." "Ajkb" + +# Nested lookaround cases from bug ICU-20564 +"(?<=(?<=((?=)){0}+))" "<0>abc" +"(?<=c(?<=c((?=c)){1}+))" "c<0><1>cc" + +# # Anchoring Bounds # "^def$" "abc<0>defghi" # anchoring (default) bounds @@ -1439,12 +1461,30 @@ "[^\u0000-\U0010ffff]" "a" "[^[^\u0000-\U0010ffff]]" "<0>a" +"This is a string with (?:one |two |three )endings" "<0>This is a string with two endings" -# Random debugging, Temporary +# Bug ICU-20544. Similar to 20385, above. Assertion failure with a negative look-behind assertion containing +# a set with no contents. Look-behind pattern includes more than just the empty set. + +"(?abc" # note: first 'ⰿ' is \u2c3f, hence empty set. +"(?abc" +"(?<=[^[^]]†)" "abc" # Problem also exists w positive look-behind + +# Bug ICU-20391. Crash in computation of minimum match length with nested look-around patterns. # +"(?<=(?<=((?=)){0}+)" E "aaa" +"(?<=(?<=((?=)){0}+))" "<0>" +"(?<=c(?<=b((?=a)){1}+))" "aaa" +"abc(?=de(?=f))...g" "<0>abcdefg" +"abc(?=de(?=f))...g" "abcdxfg" +# Bug ICU-20618 Assertion failure with nested look-around expressions. +# +"(?<=(?<=b?(?=a)))" "hello, world." +# Random debugging, Temporary +# # # Regexps from http://www.regexlib.com diff -Nru icu-64.2/source/test/testdata/root.txt icu-65.1/source/test/testdata/root.txt --- icu-64.2/source/test/testdata/root.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/root.txt 2019-10-03 11:16:41.000000000 +0000 @@ -13,8 +13,8 @@ root { Version { 44.0 } - ExpectCLDRVersionAtLeast { 35.0 } // 'base' cldr version. Allow up to version =.=.* of this - CurrentCLDRVersion { 35.0 } // Current CLDR version as of the test update. Warn if not an exact match. + ExpectCLDRVersionAtLeast { 36.0 } // 'base' cldr version. Allow up to version =.=.* of this + CurrentCLDRVersion { 36.0 } // Current CLDR version as of the test update. Warn if not an exact match. ShortLanguage { xxx } diff -Nru icu-64.2/source/test/testdata/structLocale.txt icu-65.1/source/test/testdata/structLocale.txt --- icu-64.2/source/test/testdata/structLocale.txt 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/structLocale.txt 2019-10-03 11:16:41.000000000 +0000 @@ -5806,6 +5806,7 @@ mn{""} mnc{""} mni{""} + mo{""} moh{""} mos{""} mr{""} @@ -6059,6 +6060,10 @@ Languages%long{ zh{""} } + Languages%menu{ + yue{""} + zh{""} + } Languages%secondary{ crh{""} fa{""} diff -Nru icu-64.2/source/test/testdata/testdata.mak icu-65.1/source/test/testdata/testdata.mak --- icu-64.2/source/test/testdata/testdata.mak 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/testdata.mak 2019-10-03 11:16:41.000000000 +0000 @@ -34,8 +34,8 @@ "$(TESTDATAOUT)\testdata.dat" : @echo Building test data - set PYTHONPATH=$(ICUSRCDATA);%PYTHONPATH% - py -3 -B -m buildtool \ + set PYTHONPATH=$(ICUP)\source\python;%PYTHONPATH% + py -3 -B -m icutools.databuilder \ --mode windows-exec \ --tool_dir "$(ICUTOOLS)" \ --tool_cfg "$(CFG)" \ diff -Nru icu-64.2/source/test/testdata/tstfiles.mk icu-65.1/source/test/testdata/tstfiles.mk --- icu-64.2/source/test/testdata/tstfiles.mk 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/test/testdata/tstfiles.mk 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -# Copyright (C) 2016 and later: Unicode, Inc. and others. -# License & terms of use: http://www.unicode.org/copyright.html -# Copyright (C) 2007-2014, International Business Machines Corporation and others. All Rights Reserved. -# -# TEST_RES_SOURCE defines data driven tests and other resource files to be included with -# the testdata package. For ordinary resource bundles, they only need to be referenced here. -# -# Not everything has been moved to this file yet, as this is a new facility. -# - -TEST_RES_SOURCE=calendar.txt format.txt - diff -Nru icu-64.2/source/tools/ctestfw/ctest.c icu-65.1/source/tools/ctestfw/ctest.c --- icu-64.2/source/tools/ctestfw/ctest.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/ctestfw/ctest.c 2019-10-03 11:16:41.000000000 +0000 @@ -891,18 +891,22 @@ static int traceFnNestingDepth = 0; U_CDECL_BEGIN static void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) { + (void)context; // suppress compiler warnings about unused variable char buf[500]; - utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber)); buf[sizeof(buf)-1]=0; + utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber)); + buf[sizeof(buf)-1]=0; fputs(buf, stdout); traceFnNestingDepth++; } -static void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) { char buf[500]; - +static void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) { + (void)context; // suppress compiler warnings about unused variable + char buf[500]; if (traceFnNestingDepth>0) { traceFnNestingDepth--; } - utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber)); buf[sizeof(buf)-1]=0; + utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber)); + buf[sizeof(buf)-1]=0; fputs(buf, stdout); utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args); buf[sizeof(buf)-1]=0; @@ -912,6 +916,10 @@ static void U_CALLCONV TraceData(const void *context, int32_t fnNumber, int32_t level, const char *fmt, va_list args) { + // suppress compiler warnings about unused variables + (void)context; + (void)fnNumber; + (void)level; char buf[500]; utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args); buf[sizeof(buf)-1]=0; @@ -920,6 +928,7 @@ } static void *U_CALLCONV ctest_libMalloc(const void *context, size_t size) { + (void)context; // suppress compiler warnings about unused variable /*if (VERBOSITY) { printf("Allocated %ld\n", (long)size); }*/ @@ -929,6 +938,7 @@ return malloc(size); } static void *U_CALLCONV ctest_libRealloc(const void *context, void *mem, size_t size) { + (void)context; // suppress compiler warnings about unused variable /*if (VERBOSITY) { printf("Reallocated %ld\n", (long)size); }*/ @@ -939,6 +949,7 @@ return realloc(mem, size); } static void U_CALLCONV ctest_libFree(const void *context, void *mem) { + (void)context; // suppress compiler warnings about unused variable free(mem); } diff -Nru icu-64.2/source/tools/ctestfw/ctestfw.vcxproj icu-65.1/source/tools/ctestfw/ctestfw.vcxproj --- icu-64.2/source/tools/ctestfw/ctestfw.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/ctestfw/ctestfw.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,128 +33,59 @@ <_ProjectFileVersion>10.0.30319.1 - .\..\..\..\lib\ - .\x86\Release\ - false - .\..\..\..\lib\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false + + $(OutDir)/icutest.tlb + ..\..\..\include;..\..\common;..\toolutil;%(AdditionalIncludeDirectories) T_CTEST_IMPLEMENTATION;%(PreprocessorDefinitions) true Level3 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\..\..\..\lib\icutest.tlb - - - true - MultiThreadedDLL - true - .\x86\Release/icutest.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Default + $(OutDir)/icutest.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/icutest.pdb - ..\..\..\bin\icutest64.dll - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\..\lib\icutest.pdb - UseLinkTimeCodeGeneration - false - - - .\..\..\..\lib\icutest.lib + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - .\..\..\..\lib\icutestd.tlb - + + - MultiThreadedDebugDLL - .\x86\Debug/icutest.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - EditAndContinue - Default + MultiThreadedDebugDLL - ..\..\..\bin\icutest64d.dll + ..\..\..\$(IcuBinOutputDir)\icutest65d.exe + .\..\..\..\$(IcuLibOutputDir)\icutestd.pdb + .\..\..\..\$(IcuLibOutputDir)\icutestd.lib icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\..\..\..\lib\icutestd.pdb - false - - - .\..\..\..\lib\icutestd.lib - - - .\..\..\..\lib64\icutest.tlb - + + - true MultiThreadedDLL true - .\x64\Release/icutest.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default - ..\..\..\bin64\icutest64.dll + ..\..\..\$(IcuBinOutputDir)\icutest65.exe + .\..\..\..\$(IcuLibOutputDir)\icutest.pdb + .\..\..\..\$(IcuLibOutputDir)\icutest.lib icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\..\lib64\icutest.pdb - UseLinkTimeCodeGeneration - .\..\..\..\lib64\icutest.lib - - - - - .\..\..\..\lib64\icutestd.tlb - - - MultiThreadedDebugDLL - .\x64\Debug/icutest.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - ProgramDatabase - Default - - - ..\..\..\bin64\icutest64d.dll - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\..\..\..\lib64\icutestd.pdb - .\..\..\..\lib64\icutestd.lib diff -Nru icu-64.2/source/tools/genbrk/genbrk.cpp icu-65.1/source/tools/genbrk/genbrk.cpp --- icu-64.2/source/tools/genbrk/genbrk.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genbrk/genbrk.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -262,7 +262,7 @@ if (status != U_BUFFER_OVERFLOW_ERROR) { fprintf(stderr, "ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status)); exit(status); - }; + } status = U_ZERO_ERROR; UChar *ruleSourceU = new UChar[destCap+1]; @@ -275,7 +275,7 @@ if (U_FAILURE(status)) { fprintf(stderr, "ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status)); exit(status); - }; + } ucnv_close(conv); @@ -296,7 +296,7 @@ fprintf(stderr, "createRuleBasedBreakIterator: ICU Error \"%s\" at line %d, column %d\n", u_errorName(status), (int)parseError.line, (int)parseError.offset); exit(status); - }; + } // diff -Nru icu-64.2/source/tools/genbrk/genbrk.vcxproj icu-65.1/source/tools/genbrk/genbrk.vcxproj --- icu-64.2/source/tools/genbrk/genbrk.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genbrk/genbrk.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,195 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - .\x86\Release/genbrk.tlb + $(OutDir)/genbrk.tlb - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - false - true - .\x86\Release/genbrk.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + false + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)/genbrk.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/genbrk.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/genbrk.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/genbrk.pdb Console - false - - + $(OutDir)/genbrk.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/genbrk.tlb - + + + - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - false - true - .\x86\Debug/genbrk.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/genbrk.exe - true icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/genbrk.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/genbrk.tlb - + + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - false - true - .\x64\Release/genbrk.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/genbrk.exe - true icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/genbrk.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/genbrk.tlb - - - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - false - true - .\x64\Debug/genbrk.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/genbrk.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/genbrk.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/genccode/genccode.c icu-65.1/source/tools/genccode/genccode.c --- icu-64.2/source/tools/genccode/genccode.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genccode/genccode.c 2019-10-03 11:16:41.000000000 +0000 @@ -63,6 +63,7 @@ kOptHelpH = 0, kOptHelpQuestionMark, kOptDestDir, + kOptQuiet, kOptName, kOptEntryPoint, #ifdef CAN_GENERATE_OBJECTS @@ -77,6 +78,7 @@ /*0*/UOPTION_HELP_H, UOPTION_HELP_QUESTION_MARK, UOPTION_DESTDIR, + UOPTION_QUIET, UOPTION_DEF("name", 'n', UOPT_REQUIRES_ARG), UOPTION_DEF("entrypoint", 'e', UOPT_REQUIRES_ARG), #ifdef CAN_GENERATE_OBJECTS @@ -116,6 +118,7 @@ "options:\n" "\t-h or -? or --help this usage text\n" "\t-d or --destdir destination directory, followed by the path\n" + "\t-q or --quiet do not display warnings and progress\n" "\t-n or --name symbol prefix, followed by the prefix\n" "\t-e or --entrypoint entry point name, followed by the name (_dat will be appended)\n" "\t-r or --revision Specify a version\n" @@ -159,6 +162,9 @@ writeCode = CALL_WRITECCODE; /* TODO: remove writeCode=&writeCCode; */ } + if (options[kOptQuiet].doesOccur) { + verbose = FALSE; + } while(--argc) { filename=getLongPathname(argv[argc]); if (verbose) { @@ -170,13 +176,15 @@ writeCCode(filename, options[kOptDestDir].value, options[kOptName].doesOccur ? options[kOptName].value : NULL, options[kOptFilename].doesOccur ? options[kOptFilename].value : NULL, - NULL); + NULL, + 0); break; case CALL_WRITEASSEMBLY: writeAssemblyCode(filename, options[kOptDestDir].value, options[kOptEntryPoint].doesOccur ? options[kOptEntryPoint].value : NULL, options[kOptFilename].doesOccur ? options[kOptFilename].value : NULL, - NULL); + NULL, + 0); break; #ifdef CAN_GENERATE_OBJECTS case CALL_WRITEOBJECT: @@ -184,7 +192,8 @@ options[kOptEntryPoint].doesOccur ? options[kOptEntryPoint].value : NULL, options[kOptMatchArch].doesOccur ? options[kOptMatchArch].value : NULL, options[kOptFilename].doesOccur ? options[kOptFilename].value : NULL, - NULL); + NULL, + 0); break; #endif default: diff -Nru icu-64.2/source/tools/genccode/genccode.vcxproj icu-65.1/source/tools/genccode/genccode.vcxproj --- icu-64.2/source/tools/genccode/genccode.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genccode/genccode.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,191 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - .\x86\Release/genccode.tlb + $(OutDir)/genccode.tlb - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - true - .\x86\Release/genccode.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + false + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)/genccode.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/genccode.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/genccode.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/genccode.pdb Console - false - - + $(OutDir)/genccode.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/genccode.tlb - + + + - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - .\x86\Debug/genccode.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/genccode.exe - true icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/genccode.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/genccode.tlb - + + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - true - .\x64\Release/genccode.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/genccode.exe - true icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/genccode.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/genccode.tlb - - - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - .\x64\Debug/genccode.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/genccode.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/genccode.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/gencfu/gencfu.cpp icu-65.1/source/tools/gencfu/gencfu.cpp --- icu-64.2/source/tools/gencfu/gencfu.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gencfu/gencfu.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -236,7 +236,7 @@ fprintf(stderr, "gencfu: uspoof_openFromSource error \"%s\" at file %s, line %d, column %d\n", u_errorName(status), confFileName, (int)parseError.line, (int)parseError.offset); exit(status); - }; + } // diff -Nru icu-64.2/source/tools/gencfu/gencfu.vcxproj icu-65.1/source/tools/gencfu/gencfu.vcxproj --- icu-64.2/source/tools/gencfu/gencfu.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gencfu/gencfu.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,175 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Debug\ - .\x86\Debug\ - true - .\x86\Release\ - .\x86\Release\ - false - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + + + $(OutDir)\gencfu.tlb + - Disabled - ..\..\common;..\..\i18n;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - false - EnableFastChecks - MultiThreadedDebugDLL - true - false - - - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true Level3 - EditAndContinue Default - /utf-8 %(AdditionalOptions) - true + false + ..\..\common;..\..\i18n;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)\gencfu.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\gencfu.pdb - .\x86\Debug\gencfu.exe - true - icuucd.lib;icuind.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true Console + $(OutDir)\gencfu.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) + + + - ..\..\common;..\..\i18n;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - false - MultiThreadedDLL - true - false - true - - - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - Level3 - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true + true + MultiThreadedDebugDLL - .\x86\Release\gencfu.exe - true - true - icuuc.lib;icuin.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - Console - false - - + icuucd.lib;icuind.lib;icutud.lib;%(AdditionalDependencies) - - - copy "$(TargetPath)" ..\..\..\bin64%3b - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/gencfu.tlb - + + - ..\..\common;..\..\i18n;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - false - true - .\x64\Release/gencfu.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/gencfu.exe - true icuuc.lib;icuin.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/gencfu.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64%3b - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/gencfu.tlb - - - Disabled - ..\..\common;..\..\i18n;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - false - true - .\x64\Debug/gencfu.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/gencfu.exe - true - icuucd.lib;icuind.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/gencfu.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/gencmn/gencmn.vcxproj icu-65.1/source/tools/gencmn/gencmn.vcxproj --- icu-64.2/source/tools/gencmn/gencmn.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gencmn/gencmn.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,195 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - .\x86\Release/gencmn.tlb + $(OutDir)/gencmn.tlb - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - true - true - .\x86\Release/gencmn.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + true + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)/gencmn.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/gencmn.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/gencmn.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/gencmn.pdb Console - false - - + $(OutDir)/gencmn.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/gencmn.tlb - + + + - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x86\Debug/gencmn.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/gencmn.exe - true icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/gencmn.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/gencmn.tlb - + + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - true - true - .\x64\Release/gencmn.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/gencmn.exe - true icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/gencmn.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/gencmn.tlb - - - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x64\Debug/gencmn.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/gencmn.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/gencmn.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/gencnval/gencnval.c icu-65.1/source/tools/gencnval/gencnval.c --- icu-64.2/source/tools/gencnval/gencnval.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gencnval/gencnval.c 2019-10-03 11:16:41.000000000 +0000 @@ -582,6 +582,7 @@ static void addOfficialTaggedStandards(char *line, int32_t lineLen) { + (void) lineLen; // suppress compiler warnings about unused variable char *atag; char *endTagExp; char *tag; diff -Nru icu-64.2/source/tools/gencnval/gencnval.vcxproj icu-65.1/source/tools/gencnval/gencnval.vcxproj --- icu-64.2/source/tools/gencnval/gencnval.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gencnval/gencnval.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,195 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - .\x86\Release/gencnval.tlb + $(OutDir)/gencnval.tlb - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - false - true - .\x86\Release/gencnval.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + false + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)/gencnval.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/gencnval.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/gencnval.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/gencnval.pdb Console - false - - + $(OutDir)/gencnval.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/gencnval.tlb - + + + - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - false - true - .\x86\Debug/gencnval.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/gencnval.exe - true icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/gencnval.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/gencnval.tlb - + + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - false - true - .\x64\Release/gencnval.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/gencnval.exe - true icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/gencnval.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/gencnval.tlb - - - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - false - true - .\x64\Debug/gencnval.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/gencnval.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/gencnval.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/gendict/gendict.vcxproj icu-65.1/source/tools/gendict/gendict.vcxproj --- icu-64.2/source/tools/gendict/gendict.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gendict/gendict.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,195 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - .\x86\Release/gendict.tlb + $(OutDir)\gendict.tlb - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - true - true - .\x86\Release/gendict.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + true + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)\gendict.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\gendict.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/gendict.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/gendict.pdb Console - false - - + $(OutDir)\gendict.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/gendict.tlb - + + + - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x86\Debug/gendict.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/gendict.exe - true icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/gendict.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/gendict.tlb - + + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - true - true - .\x64\Release/gendict.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/gendict.exe - true icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/gendict.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/gendict.tlb - - - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x64\Debug/gendict.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/gendict.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/gendict.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/gennorm2/gennorm2.vcxproj icu-65.1/source/tools/gennorm2/gennorm2.vcxproj --- icu-64.2/source/tools/gennorm2/gennorm2.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gennorm2/gennorm2.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -32,145 +32,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + + + $(OutDir)\gennorm2.tlb + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - false Level3 - - - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - - - MaxSpeed - true - MultiThreadedDLL - true - .\x86\Release\gennorm2.pch - .\x86\Release\ - .\x86\Release\ - .\x86\Release\ - ProgramDatabase Default + false + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)\gennorm2.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\gennorm2.pdb - .\x86\Release\gennorm2.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release\gennorm2.pdb - true Console - true - true - MachineX86 - false - false + $(OutDir)\gennorm2.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) + + + - true - MultiThreadedDebugDLL - .\x86\Debug\gennorm2.pch - .\x86\Debug\ - .\x86\Debug\ - .\x86\Debug\ true - EditAndContinue - Default + MultiThreadedDebugDLL - .\x86\Debug\gennorm2.exe icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug\gennorm2.pdb - Console - false - false - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - + + - MaxSpeed - true MultiThreadedDLL true - .\x64\Release\gennorm2.pch - .\x64\Release\ - .\x64\Release\ - .\x64\Release\ - ProgramDatabase - Default - .\x64\Release\gennorm2.exe icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release\gennorm2.pdb - true - Console - true - false - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - true - MultiThreadedDebugDLL - .\x64\Debug\gennorm2.pch - .\x64\Debug\ - .\x64\Debug\ - .\x64\Debug\ - true - EditAndContinue - Default - - - .\x64\Debug\gennorm2.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug\gennorm2.pdb - Console - false - false diff -Nru icu-64.2/source/tools/genrb/derb.cpp icu-65.1/source/tools/genrb/derb.cpp --- icu-64.2/source/tools/genrb/derb.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/derb.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -631,7 +631,7 @@ if (!(enc = ucnv_getStandardName(encoding, "MIME", &err))) { err = U_ZERO_ERROR; if (!(enc = ucnv_getStandardName(encoding, "IANA", &err))) { - ; + // do nothing } } diff -Nru icu-64.2/source/tools/genrb/derb.vcxproj icu-65.1/source/tools/genrb/derb.vcxproj --- icu-64.2/source/tools/genrb/derb.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/derb.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,207 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release_derb\ - .\x86\Release_derb\ - false - .\x86\Debug_derb\ - .\x86\Debug_derb\ - true - .\x64\Release_derb\ - .\x64\Release_derb\ - false - .\x64\Debug_derb\ - .\x64\Debug_derb\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\x86\Release_derb/derb.tlb + $(OutDir)/derb.tlb - ..\..\i18n;..\..\common;..\toolutil;..\..\io;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - true - true - .\x86\Release_derb/derb.pch - .\x86\Release_derb/ - .\x86\Release_derb/ - .\x86\Release_derb/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + true + ..\..\i18n;..\..\common;..\toolutil;..\..\io;%(AdditionalIncludeDirectories) + $(OutDir)/derb.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/derb.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release_derb/derb.exe - true - icuuc.lib;icuin.lib;icuio.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release_derb/derb.pdb Console - false - - + $(OutDir)/derb.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\x86\Debug_derb/derb.tlb - + + + - Disabled - ..\..\i18n;..\..\common;..\toolutil;..\..\io;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks + true MultiThreadedDebugDLL - true - true - true - .\x86\Debug_derb/derb.pch - .\x86\Debug_derb/ - .\x86\Debug_derb/ - .\x86\Debug_derb/ - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug_derb/derb.exe - true icuucd.lib;icuind.lib;icuiod.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug_derb/derb.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - .\x64\Release_derb/derb.tlb - + + - ..\..\i18n;..\..\common;..\toolutil;..\..\io;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - true - true - .\x64\Release_derb/derb.pch - .\x64\Release_derb/ - .\x64\Release_derb/ - .\x64\Release_derb/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release_derb/derb.exe - true icuuc.lib;icuin.lib;icuio.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release_derb/derb.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - .\x64\Debug_derb/derb.tlb - - - Disabled - ..\..\i18n;..\..\common;..\toolutil;..\..\io;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x64\Debug_derb/derb.pch - .\x64\Debug_derb/ - .\x64\Debug_derb/ - .\x64\Debug_derb/ - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug_derb/derb.exe - true - icuucd.lib;icuind.lib;icuiod.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug_derb/derb.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/genrb/filterrb.cpp icu-65.1/source/tools/genrb/filterrb.cpp --- icu-64.2/source/tools/genrb/filterrb.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/filterrb.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -23,6 +23,9 @@ status = U_PARSE_ERROR; return; } + if (path.length() == 1) { + return; + } size_t i; size_t j = 0; while (true) { diff -Nru icu-64.2/source/tools/genrb/genrb.cpp icu-65.1/source/tools/genrb/genrb.cpp --- icu-64.2/source/tools/genrb/genrb.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/genrb.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -205,10 +205,10 @@ "\t-c or --copyright include copyright notice\n"); fprintf(stderr, "\t-e or --encoding encoding of source files\n" - "\t-d of --destdir destination directory, followed by the path, defaults to %s\n" - "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n" + "\t-d or --destdir destination directory, followed by the path, defaults to '%s'\n" + "\t-s or --sourcedir source directory for files followed by path, defaults to '%s'\n" "\t-i or --icudatadir directory for locating any needed intermediate data files,\n" - "\t followed by path, defaults to %s\n", + "\t followed by path, defaults to '%s'\n", u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory()); fprintf(stderr, "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n" @@ -240,7 +240,7 @@ "\t (--writePoolBundle and --usePoolBundle cannot be combined)\n"); fprintf(stderr, "\t --filterDir Input directory where filter files are available.\n" - "\t For more on filter files, see Python buildtool.\n"); + "\t For more on filter files, see ICU Data Build Tool.\n"); return illegalArg ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; } diff -Nru icu-64.2/source/tools/genrb/genrb.vcxproj icu-65.1/source/tools/genrb/genrb.vcxproj --- icu-64.2/source/tools/genrb/genrb.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/genrb.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,195 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - WINVER=0x0601;_WIN32_WINNT=0x0601;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - - .\x86\Release/genrb.tlb + $(OutDir)/genrb.tlb - ..\..\..\include;..\..\common;..\toolutil;..\..\i18n;%(AdditionalIncludeDirectories) - true - MultiThreadedDLL - true - true - .\x86\Release/genrb.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + true + ..\..\..\include;..\..\common;..\toolutil;..\..\i18n;%(AdditionalIncludeDirectories) + $(OutDir)/genrb.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/genrb.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/genrb.exe - true - icuuc.lib;icuin.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/genrb.pdb Console - false - - + $(OutDir)/genrb.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/genrb.tlb - + + + - Disabled - ..\..\..\include;..\..\common;..\toolutil;..\..\i18n;%(AdditionalIncludeDirectories) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x86\Debug/genrb.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/genrb.exe - true icuucd.lib;icuind.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/genrb.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/genrb.tlb - + + - ..\..\..\include;..\..\common;..\toolutil;..\..\i18n;%(AdditionalIncludeDirectories) - true MultiThreadedDLL - true - true - .\x64\Release/genrb.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true + true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/genrb.exe - true icuuc.lib;icuin.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/genrb.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/genrb.tlb - - - Disabled - ..\..\..\include;..\..\common;..\toolutil;..\..\i18n;%(AdditionalIncludeDirectories) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x64\Debug/genrb.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/genrb.exe - true - icuucd.lib;icuind.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/genrb.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/genrb/parse.cpp icu-65.1/source/tools/genrb/parse.cpp --- icu-64.2/source/tools/genrb/parse.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/parse.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -274,11 +274,11 @@ } } -static char *getInvariantString(ParseState* state, uint32_t *line, struct UString *comment, UErrorCode *status) +static char *getInvariantString(ParseState* state, uint32_t *line, struct UString *comment, + int32_t &stringLength, UErrorCode *status) { struct UString *tokenValue; char *result; - uint32_t count; expect(state, TOK_STRING, &tokenValue, comment, line, status); @@ -287,14 +287,13 @@ return NULL; } - count = u_strlen(tokenValue->fChars); - if(!uprv_isInvariantUString(tokenValue->fChars, count)) { + if(!uprv_isInvariantUString(tokenValue->fChars, tokenValue->fLength)) { *status = U_INVALID_FORMAT_ERROR; error(*line, "invariant characters required for table keys, binary data, etc."); return NULL; } - result = static_cast(uprv_malloc(count+1)); + result = static_cast(uprv_malloc(tokenValue->fLength+1)); if (result == NULL) { @@ -302,7 +301,8 @@ return NULL; } - u_UCharsToChars(tokenValue->fChars, result, count+1); + u_UCharsToChars(tokenValue->fChars, result, tokenValue->fLength+1); + stringLength = tokenValue->fLength; return result; } @@ -1371,7 +1371,6 @@ int32_t value; UBool readToken = FALSE; char *stopstring; - uint32_t len; struct UString memberComments; IntVectorResource *result = intvector_open(state->bundle, tag, comment, status); @@ -1404,7 +1403,8 @@ return result; } - string = getInvariantString(state, NULL, NULL, status); + int32_t stringLength; + string = getInvariantString(state, NULL, NULL, stringLength, status); if (U_FAILURE(*status)) { @@ -1414,9 +1414,9 @@ /* For handling illegal char in the Intvector */ value = uprv_strtoul(string, &stopstring, 0);/* make intvector support decimal,hexdigit,octal digit ranging from -2^31-2^32-1*/ - len=(uint32_t)(stopstring-string); + int32_t len = (int32_t)(stopstring-string); - if(len==uprv_strlen(string)) + if(len==stringLength) { result->add(value, *status); uprv_free(string); @@ -1454,7 +1454,8 @@ parseBinary(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status) { uint32_t line; - LocalMemory string(getInvariantString(state, &line, NULL, status)); + int32_t stringLength; + LocalMemory string(getInvariantString(state, &line, NULL, stringLength, status)); if (string.isNull() || U_FAILURE(*status)) { return NULL; @@ -1470,46 +1471,45 @@ printf(" binary %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline); } - uint32_t count = (uint32_t)uprv_strlen(string.getAlias()); - if (count > 0){ - if((count % 2)==0){ - LocalMemory value; - if (value.allocateInsteadAndCopy(count) == NULL) - { - *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - - char toConv[3] = {'\0', '\0', '\0'}; - for (uint32_t i = 0; i < count; i += 2) - { - toConv[0] = string[i]; - toConv[1] = string[i + 1]; + LocalMemory value; + int32_t count = 0; + if (stringLength > 0 && value.allocateInsteadAndCopy(stringLength) == NULL) + { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } - char *stopstring; - value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16); - uint32_t len=(uint32_t)(stopstring-toConv); + char toConv[3] = {'\0', '\0', '\0'}; + for (int32_t i = 0; i < stringLength;) + { + // Skip spaces (which may have been line endings). + char c0 = string[i++]; + if (c0 == ' ') { continue; } + if (i == stringLength) { + *status=U_INVALID_CHAR_FOUND; + error(line, "Encountered invalid binary value (odd number of hex digits)"); + return NULL; + } + toConv[0] = c0; + toConv[1] = string[i++]; - if(len!=2) - { - *status=U_INVALID_CHAR_FOUND; - return NULL; - } - } + char *stopstring; + value[count++] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16); + uint32_t len=(uint32_t)(stopstring-toConv); - return bin_open(state->bundle, tag, count >> 1, value.getAlias(), NULL, comment, status); - } - else + if(len!=2) { - *status = U_INVALID_CHAR_FOUND; - error(line, "Encountered invalid binary value (length is odd)"); + *status=U_INVALID_CHAR_FOUND; + error(line, "Encountered invalid binary value (not all pairs of hex digits)"); return NULL; } } - else - { + + if (count == 0) { warning(startline, "Encountered empty binary value"); return bin_open(state->bundle, tag, 0, NULL, "", comment, status); + } else { + return bin_open(state->bundle, tag, count, value.getAlias(), NULL, comment, status); } } @@ -1520,9 +1520,9 @@ int32_t value; char *string; char *stopstring; - uint32_t len; - string = getInvariantString(state, NULL, NULL, status); + int32_t stringLength; + string = getInvariantString(state, NULL, NULL, stringLength, status); if (string == NULL || U_FAILURE(*status)) { @@ -1541,7 +1541,7 @@ printf(" integer %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline); } - if (uprv_strlen(string) <= 0) + if (stringLength == 0) { warning(startline, "Encountered empty integer. Default value is 0."); } @@ -1549,8 +1549,8 @@ /* Allow integer support for hexdecimal, octal digit and decimal*/ /* and handle illegal char in the integer*/ value = uprv_strtoul(string, &stopstring, 0); - len=(uint32_t)(stopstring-string); - if(len==uprv_strlen(string)) + int32_t len = (int32_t)(stopstring-string); + if(len==stringLength) { result = int_open(state->bundle, tag, value, comment, status); } @@ -1567,7 +1567,8 @@ parseImport(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status) { uint32_t line; - LocalMemory filename(getInvariantString(state, &line, NULL, status)); + int32_t stringLength; + LocalMemory filename(getInvariantString(state, &line, NULL, stringLength, status)); if (U_FAILURE(*status)) { return NULL; @@ -1628,12 +1629,11 @@ UCHARBUF *ucbuf; char *fullname = NULL; - int32_t count = 0; const char* cp = NULL; const UChar* uBuffer = NULL; - filename = getInvariantString(state, &line, NULL, status); - count = (int32_t)uprv_strlen(filename); + int32_t stringLength; + filename = getInvariantString(state, &line, NULL, stringLength, status); if (U_FAILURE(*status)) { @@ -1652,7 +1652,7 @@ printf(" include %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline); } - fullname = (char *) uprv_malloc(state->inputdirLength + count + 2); + fullname = (char *) uprv_malloc(state->inputdirLength + stringLength + 2); /* test for NULL */ if(fullname == NULL) { diff -Nru icu-64.2/source/tools/genrb/reslist.cpp icu-65.1/source/tools/genrb/reslist.cpp --- icu-64.2/source/tools/genrb/reslist.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/reslist.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -1371,7 +1371,7 @@ } int32_t keysCount = fUsePoolBundle->fKeysCount + fKeysCount; - if (U_FAILURE(errorCode) || fKeysCount == 0 || fKeyMap != NULL) { + if (U_FAILURE(errorCode) || fKeyMap != NULL) { return; } map = (KeyMapEntry *)uprv_malloc(keysCount * sizeof(KeyMapEntry)); diff -Nru icu-64.2/source/tools/genrb/rle.c icu-65.1/source/tools/genrb/rle.c --- icu-64.2/source/tools/genrb/rle.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/genrb/rle.c 2019-10-03 11:16:41.000000000 +0000 @@ -91,14 +91,14 @@ return buffer; } -#define APPEND( buffer, bufLimit, value, num, status){ \ +#define APPEND( buffer, bufLimit, value, num, status) UPRV_BLOCK_MACRO_BEGIN { \ if(buffer <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - + + - .\x86\Release/gensprep.tlb + $(OutDir)\gensprep.tlb - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - false - true - .\x86\Release/gensprep.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + false + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)\gensprep.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\gensprep.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/gensprep.exe - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/gensprep.pdb Console - false - - + $(OutDir)\gensprep.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Debug/gensprep.tlb - + + + - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks + true MultiThreadedDebugDLL - true - false - true - .\x86\Debug/gensprep.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/gensprep.exe - true icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/gensprep.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Release/gensprep.tlb - + + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - false - true - .\x64\Release/gensprep.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/gensprep.exe - true icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/gensprep.pdb - Console - MachineX64 - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - X64 - .\x64\Debug/gensprep.tlb - - - Disabled - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - false - true - .\x64\Debug/gensprep.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/gensprep.exe - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/gensprep.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/gensprep/store.c icu-65.1/source/tools/gensprep/store.c --- icu-64.2/source/tools/gensprep/store.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gensprep/store.c 2019-10-03 11:16:41.000000000 +0000 @@ -464,7 +464,8 @@ extern void -storeRange(uint32_t start, uint32_t end, UStringPrepType type,UErrorCode* status){ +storeRange(uint32_t start, uint32_t end, UStringPrepType type, UErrorCode* status){ + (void)status; // suppress compiler warnings about unused variable uint16_t trieWord = 0; if((int)(_SPREP_TYPE_THRESHOLD + type) > 0xFFFF){ diff -Nru icu-64.2/source/tools/gentest/gentest.vcxproj icu-65.1/source/tools/gentest/gentest.vcxproj --- icu-64.2/source/tools/gentest/gentest.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/gentest/gentest.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -34,175 +34,55 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Release\ - .\x86\Release\ - false - .\x86\Debug\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + + - .\x86\Release/gentest.tlb + $(OutDir)/gentest.tlb - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - true - true - .\x86\Release/gentest.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + true + ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) + $(OutDir)/gentest.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/gentest.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Release/gentest.exe - true - icuuc.lib;icutest.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/gentest.pdb Console - false - - + $(OutDir)/gentest.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) + $(OutDir)/gentest.pdb - - - .\x86\Debug/gentest.tlb - + + - Disabled - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x86\Debug/gentest.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x86\Debug/gentest.exe - true icuucd.lib;icutestd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/gentest.pdb - Console - false - - - - - X64 - .\x64\Release/gentest.tlb - + + - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true MultiThreadedDLL true - true - true - .\x64\Release/gentest.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - .\x64\Release/gentest.exe - true icuuc.lib;icutest.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/gentest.pdb - Console - MachineX64 - - - - - X64 - .\x64\Debug/gentest.tlb - - - Disabled - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x64\Debug/gentest.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - .\x64\Debug/gentest.exe - true - icuucd.lib;icutestd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\x64\Debug/gentest.pdb - Console - MachineX64 diff -Nru icu-64.2/source/tools/icuinfo/icuinfo.vcxproj icu-65.1/source/tools/icuinfo/icuinfo.vcxproj --- icu-64.2/source/tools/icuinfo/icuinfo.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/icuinfo/icuinfo.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,125 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - x86\Release\ - x86\Release\ - false - x86\Debug\ - x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + + + $(OutDir)\icuinfo.tlb + - ..\..\common;..\..\i18n;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - true Level4 - - - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - - - MultiThreadedDLL - true - x86\Release/icuinfo.pch - x86\Release/ - x86\Release/ - x86\Release/ Default + false + ..\..\common;..\..\i18n;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) + $(OutDir)\icuinfo.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\icuinfo.pdb - $(OutDir)icuinfo.exe - icuuc.lib;icuin.lib;icutu.lib;icutest.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - x86\Release/icuinfo.pdb Console - false - - + $(OutDir)\icuinfo.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) + + + - MultiThreadedDebugDLL - Debug/icuinfo.pch - Debug/ - Debug/ - Debug/ true - EditAndContinue - Default + MultiThreadedDebugDLL - $(OutDir)icuinfo.exe icuucd.lib;icuind.lib;icutud.lib;icutestd.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - $(OutDir)icuinfo.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - + + MultiThreadedDLL true - x64\Release/icuinfo.pch - x64\Release/ - x64\Release/ - x64\Release/ - Default - $(OutDir)icuinfo.exe icuuc.lib;icuin.lib;icutu.lib;icutest.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - x64\Release/icuinfo.pdb - Console - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - MultiThreadedDebugDLL - Debug/icuinfo.pch - Debug/ - Debug/ - Debug/ - true - ProgramDatabase - Default - - - $(OutDir)icuinfo.exe - icuucd.lib;icuind.lib;icutud.lib;icutestd.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - $(OutDir)icuinfo.pdb - Console diff -Nru icu-64.2/source/tools/icuinfo/testplug.vcxproj icu-65.1/source/tools/icuinfo/testplug.vcxproj --- icu-64.2/source/tools/icuinfo/testplug.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/icuinfo/testplug.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,195 +33,61 @@ <_ProjectFileVersion>10.0.30319.1 - .\..\..\..\lib\ - .\x86\Release-testplug\ - false - .\..\..\..\lib\ - .\x86\Debug-testplug\ - true - .\x64\Release-testplug\ - .\x64\Release-testplug\ - false - .\x64\Debug-testplug\ - .\x64\Debug-testplug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + + - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\..\..\..\lib\testplug.tlb + $(OutDir)\testplug.tlb - true ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;T_CTEST_IMPLEMENTATION;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true + T_CTEST_IMPLEMENTATION;%(PreprocessorDefinitions) true - true - .\x86\Release-testplug/testplug.pch - .\x86\Release-testplug/ - .\x86\Release-testplug/ - .\x86\Release-testplug/ Level3 - true Default - /utf-8 %(AdditionalOptions) - true + ProgramDatabase + $(OutDir)\testplug.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\testplug.pdb - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - ..\..\..\bin\testplug.dll - true - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\..\..\..\lib\testplug.pdb - true - UseLinkTimeCodeGeneration - false - - - .\..\..\..\lib\testplug.lib + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\..\..\..\lib\testplugd.tlb - + + - Disabled - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;T_CTEST_IMPLEMENTATION;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x86\Debug-testplug/testplug.pch - .\x86\Debug-testplug/ - .\x86\Debug-testplug/ - .\x86\Debug-testplug/ true - Level3 - true - EditAndContinue - Default - /utf-8 %(AdditionalOptions) - true + MultiThreadedDebugDLL - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - ..\..\..\bin\testplug.dll - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) true - .\..\..\..\lib\testplugd.pdb - false - - - .\..\..\..\lib\testplugd.lib + ..\..\..\$(IcuBinOutputDir)\testplugd.dll + ..\..\..\$(IcuLibOutputDir)\testplugd.pdb + ..\..\..\$(IcuLibOutputDir)\testplugd.lib + icuucd.lib;icutud.lib;%(AdditionalDependencies) - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - .\..\..\..\lib64\testplug.tlb - + + - true - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;T_CTEST_IMPLEMENTATION;%(PreprocessorDefinitions) - true MultiThreadedDLL true - true - true - .\x64\Release-testplug/testplug.pch - .\x64\Release-testplug/ - .\x64\Release-testplug/ - .\x64\Release-testplug/ - Level3 - true - Default - /utf-8 %(AdditionalOptions) - true - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - ..\..\..\bin64\testplug.dll - true + ..\..\..\$(IcuBinOutputDir)\testplug.dll + ..\..\..\$(IcuLibOutputDir)\testplug.pdb + ..\..\..\$(IcuLibOutputDir)\testplug.lib icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\..\lib64\testplug.pdb - true - UseLinkTimeCodeGeneration - .\..\..\..\lib64\testplug.lib - MachineX64 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - .\..\..\..\lib64\testplugd.tlb - - - Disabled - ..\..\..\include;..\..\common;..\toolutil;..\ctestfw;%(AdditionalIncludeDirectories) - WINVER=0x0601;_WIN32_WINNT=0x0601;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;T_CTEST_IMPLEMENTATION;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - true - true - true - .\x64\Debug-testplug/testplug.pch - .\x64\Debug-testplug/ - .\x64\Debug-testplug/ - .\x64\Debug-testplug/ - true - Level3 - true - ProgramDatabase - Default - /utf-8 %(AdditionalOptions) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - ..\..\..\bin64\testplug.dll - true - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - true - .\..\..\..\lib64\testplugd.pdb - .\..\..\..\lib64\testplugd.lib - MachineX64 diff -Nru icu-64.2/source/tools/icupkg/icupkg.vcxproj icu-65.1/source/tools/icupkg/icupkg.vcxproj --- icu-64.2/source/tools/icupkg/icupkg.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/icupkg/icupkg.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,126 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - x86\Release\ - x86\Release\ - false - x86\Debug\ - x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + + + $(OutDir)\icupkg.tlb + - ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - true Level4 - - - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - - - MultiThreadedDLL - true - x86\Release/icupkg.pch - x86\Release/ - x86\Release/ - x86\Release/ Default + true + ..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)\icupkg.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)\icupkg.pdb - $(OutDir)icupkg.exe - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - x86\Release/icupkg.pdb Console - false - - + $(OutDir)\icupkg.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) + + + - MultiThreadedDebugDLL - Debug/icupkg.pch - Debug/ - Debug/ - Debug/ true - EditAndContinue - Default + MultiThreadedDebugDLL - $(OutDir)icupkg.exe icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - $(OutDir)icupkg.pdb - Console - false - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - + + MultiThreadedDLL true - x64\Release/icupkg.pch - x64\Release/ - x64\Release/ - x64\Release/ - Default - $(OutDir)icupkg.exe icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - x64\Release/icupkg.pdb - Console - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - MultiThreadedDebugDLL - Debug/icupkg.pch - Debug/ - Debug/ - Debug/ - true - ProgramDatabase - Default - - - $(OutDir)icupkg.exe - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - $(OutDir)icupkg.pdb - Console diff -Nru icu-64.2/source/tools/makeconv/gencnvex.c icu-65.1/source/tools/makeconv/gencnvex.c --- icu-64.2/source/tools/makeconv/gencnvex.c 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/makeconv/gencnvex.c 2019-10-03 11:16:41.000000000 +0000 @@ -107,12 +107,17 @@ static UBool CnvExtIsValid(NewConverter *cnvData, const uint8_t *bytes, int32_t length) { + // suppress compiler warnings about unused variables + (void)cnvData; + (void)bytes; + (void)length; return FALSE; } static uint32_t CnvExtWrite(NewConverter *cnvData, const UConverterStaticData *staticData, UNewDataMemory *pData, int32_t tableType) { + (void) staticData; // suppress compiler warnings about unused variable CnvExtData *extData=(CnvExtData *)cnvData; int32_t length, top, headerSize; @@ -121,7 +126,7 @@ if(tableType&TABLE_BASE) { headerSize=0; } else { - _MBCSHeader header={ { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0 }; + _MBCSHeader header={ { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* write the header and base table name for an extension-only table */ length=(int32_t)uprv_strlen(extData->ucm->baseName)+1; diff -Nru icu-64.2/source/tools/makeconv/makeconv.vcxproj icu-65.1/source/tools/makeconv/makeconv.vcxproj --- icu-64.2/source/tools/makeconv/makeconv.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/makeconv/makeconv.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,135 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Debug\ - .\x86\Debug\ - true - .\x86\Release\ - .\x86\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + - - ..\..\..\include;..\..\common;..\toolutil;%(AdditionalIncludeDirectories) - false - Level3 - - - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - - .\x86\Debug/makeconv.tlb + $(OutDir)/makeconv.tlb - MultiThreadedDebugDLL - .\x86\Debug/makeconv.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true - EditAndContinue + Level3 Default + false + ..\..\..\include;..\..\common;..\toolutil;%(AdditionalIncludeDirectories) + $(OutDir)/makeconv.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/makeconv.pdb - .\x86\Debug/makeconv.exe - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Debug/makeconv.pdb Console - false - - + $(OutDir)/makeconv.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Release/makeconv.tlb - - - MultiThreadedDLL - .\x86\Release/makeconv.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - Default - - - .\x86\Release/makeconv.exe - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/makeconv.pdb - Console - false - - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - .\x64\Debug/makeconv.tlb - + + - MultiThreadedDebugDLL - .\x64\Debug/makeconv.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ true - ProgramDatabase - Default + MultiThreadedDebugDLL - .\x64\Debug/makeconv.exe icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Debug/makeconv.pdb - Console - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - .\x64\Release/makeconv.tlb - + + MultiThreadedDLL - .\x64\Release/makeconv.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default + true - .\x64\Release/makeconv.exe icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/makeconv.pdb - Console diff -Nru icu-64.2/source/tools/pkgdata/pkgdata.cpp icu-65.1/source/tools/pkgdata/pkgdata.cpp --- icu-64.2/source/tools/pkgdata/pkgdata.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/pkgdata/pkgdata.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -122,8 +122,9 @@ QUIET, WITHOUT_ASSEMBLY, PDS_BUILD, - UWP_BUILD, - UWP_ARM_BUILD + WIN_UWP_BUILD, + WIN_DLL_ARCH, + WIN_DYNAMICBASE }; /* This sets the modes that are available */ @@ -167,7 +168,8 @@ /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG), /*21*/ UOPTION_DEF("zos-pds-build", 'z', UOPT_NO_ARG), /*22*/ UOPTION_DEF("windows-uwp-build", 'u', UOPT_NO_ARG), - /*23*/ UOPTION_DEF("windows-uwp-arm-build", 'a', UOPT_NO_ARG) + /*23*/ UOPTION_DEF("windows-DLL-arch", 'a', UOPT_REQUIRES_ARG), + /*24*/ UOPTION_DEF("windows-dynamicbase", 'b', UOPT_NO_ARG), }; /* This enum and the following char array should be kept in sync. */ @@ -258,7 +260,8 @@ "Build the data without assembly code", "Build PDS dataset (zOS build only)", "Build for Universal Windows Platform (Windows build only)", - "Set DLL machine type for UWP to target windows ARM (Windows UWP build only)" + "Specify the DLL machine architecture for LINK.exe (Windows build only)", + "Ignored. Enable DYNAMICBASE on the DLL. This is now the default. (Windows build only)", }; const char *progname = "PKGDATA"; @@ -468,6 +471,10 @@ #endif } + if (options[WIN_DYNAMICBASE].doesOccur) { + fprintf(stdout, "Note: Ignoring option -b (windows-dynamicbase).\n"); + } + /* OK options are set up. Now the file lists. */ tail = NULL; for( n=1; n3) && checkAssemblyHeaderName(genccodeAssembly+3)) { - writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath); + writeAssemblyCode( + datFileNamePath, + o->tmpDir, + o->entryName, + NULL, + gencFilePath, + sizeof(gencFilePath)); result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath); if (result != 0) { @@ -753,7 +766,14 @@ /* Try to detect the arch type, use NULL if unsuccessful */ char optMatchArch[10] = { 0 }; pkg_createOptMatchArch(optMatchArch); - writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, (optMatchArch[0] == 0 ? NULL : optMatchArch), NULL, gencFilePath); + writeObjectCode( + datFileNamePath, + o->tmpDir, + o->entryName, + (optMatchArch[0] == 0 ? NULL : optMatchArch), + NULL, + gencFilePath, + sizeof(gencFilePath)); pkg_destroyOptMatchArch(optMatchArch); #if U_PLATFORM_IS_LINUX_BASED result = pkg_generateLibraryFile(targetDir, mode, gencFilePath); @@ -1685,7 +1705,13 @@ printf("# Generating %s \n", gencmnFile); } - writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile); + writeCCode( + file, + o->tmpDir, + dataName[0] != 0 ? dataName : o->shortName, + newName[0] != 0 ? newName : NULL, + gencmnFile, + sizeof(gencmnFile)); #ifdef USE_SINGLE_CCODE_FILE sprintf(cmd, "#include \"%s\"\n", gencmnFile); @@ -1758,14 +1784,12 @@ #ifdef WINDOWS_WITH_MSVC #define LINK_CMD "link.exe /nologo /release /out:" -#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO /implib:" -#ifdef _WIN64 -#define LINK_EXTRA_UWP_FLAGS "/NXCOMPAT /DYNAMICBASE /APPCONTAINER " -#else -#define LINK_EXTRA_UWP_FLAGS "/NXCOMPAT /SAFESEH /DYNAMICBASE /APPCONTAINER /MACHINE:X86" -#endif -#define LINK_EXTRA_UWP_FLAGS_ARM "/NXCOMPAT /DYNAMICBASE /APPCONTAINER /MACHINE:ARM" -#define LINK_EXTRA_NO_UWP_FLAGS "/base:0x4ad00000 " +#define LINK_FLAGS "/NXCOMPAT /DYNAMICBASE /DLL /NOENTRY /MANIFEST:NO /implib:" + +#define LINK_EXTRA_UWP_FLAGS "/APPCONTAINER " +#define LINK_EXTRA_UWP_FLAGS_X86_ONLY "/SAFESEH " + +#define LINK_EXTRA_FLAGS_MACHINE "/MACHINE:" #define LIB_CMD "LIB.exe /nologo /out:" #define LIB_FILE "icudt.lib" #define LIB_EXT UDATA_LIB_SUFFIX @@ -1845,23 +1869,23 @@ return 0; } - char *extraFlags = ""; + char extraFlags[SMALL_BUFFER_MAX_SIZE] = ""; #ifdef WINDOWS_WITH_MSVC - if (options[UWP_BUILD].doesOccur) - { - if (options[UWP_ARM_BUILD].doesOccur) - { - extraFlags = LINK_EXTRA_UWP_FLAGS_ARM; - } - else - { - extraFlags = LINK_EXTRA_UWP_FLAGS; + if (options[WIN_UWP_BUILD].doesOccur) { + uprv_strcat(extraFlags, LINK_EXTRA_UWP_FLAGS); + + if (options[WIN_DLL_ARCH].doesOccur) { + if (uprv_strcmp(options[WIN_DLL_ARCH].value, "X86") == 0) { + uprv_strcat(extraFlags, LINK_EXTRA_UWP_FLAGS_X86_ONLY); + } } } - else - { - extraFlags = LINK_EXTRA_NO_UWP_FLAGS; + + if (options[WIN_DLL_ARCH].doesOccur) { + uprv_strcat(extraFlags, LINK_EXTRA_FLAGS_MACHINE); + uprv_strcat(extraFlags, options[WIN_DLL_ARCH].value); } + #endif sprintf(cmd, "%s\"%s\" %s %s\"%s\" \"%s\" %s", LINK_CMD, diff -Nru icu-64.2/source/tools/pkgdata/pkgdata.vcxproj icu-65.1/source/tools/pkgdata/pkgdata.vcxproj --- icu-64.2/source/tools/pkgdata/pkgdata.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/pkgdata/pkgdata.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,151 +33,58 @@ <_ProjectFileVersion>10.0.30319.1 - .\x86\Debug\ - .\x86\Debug\ - true - .\x86\Release\ - .\x86\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false - + - - ../../../include;../../common;../toolutil;%(AdditionalIncludeDirectories) - true - Level3 - - - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) - - .\x86\Debug/pkgdata.tlb + $(OutDir)/pkgdata.tlb - MultiThreadedDebugDLL - .\x86\Debug/pkgdata.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - true - EditAndContinue + Level3 Default + true + ../../../include;../../common;../toolutil;%(AdditionalIncludeDirectories) + $(OutDir)/pkgdata.pch + $(OutDir)/ + $(OutDir)/ + $(OutDir)/pkgdata.pdb - - 0x0411 - - .\x86\Debug/pkgdata.exe - icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - true - .\x86\Debug/pkgdata.pdb Console - false - - + $(OutDir)/pkgdata.exe + ..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories) - - - copy "$(TargetPath)" ..\..\..\bin - - ..\..\..\bin\$(TargetFileName);%(Outputs) + copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir) + ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs) - - .\x86\Release/pkgdata.tlb - - - MultiThreadedDLL - true - .\x86\Release/pkgdata.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - Default - - - 0x0411 - - - .\x86\Release/pkgdata.exe - icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) - .\x86\Release/pkgdata.pdb - Console - false - - - - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - .\x64\Debug/pkgdata.tlb - + + - MultiThreadedDebugDLL - .\x64\Debug/pkgdata.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ true - ProgramDatabase - Default + MultiThreadedDebugDLL - - 0x0411 - - .\x64\Debug/pkgdata.exe icuucd.lib;icutud.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Debug/pkgdata.pdb - Console - - - copy "$(TargetPath)" ..\..\..\bin64 - - ..\..\..\bin64\$(TargetFileName);%(Outputs) - - - .\x64\Release/pkgdata.tlb - + + MultiThreadedDLL true - .\x64\Release/pkgdata.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - true - Default - - 0x0411 - - .\x64\Release/pkgdata.exe icuuc.lib;icutu.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\x64\Release/pkgdata.pdb - Console diff -Nru icu-64.2/source/tools/toolutil/filetools.cpp icu-65.1/source/tools/toolutil/filetools.cpp --- icu-64.2/source/tools/toolutil/filetools.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/filetools.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -65,7 +65,7 @@ if (U_FAILURE(status)) { fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, u_errorName(status)); return FALSE; - }; + } if ((subDirp = opendir(newpath.data())) != NULL) { /* If this new path is a directory, make a recursive call with the newpath. */ diff -Nru icu-64.2/source/tools/toolutil/pkg_genc.cpp icu-65.1/source/tools/toolutil/pkg_genc.cpp --- icu-64.2/source/tools/toolutil/pkg_genc.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/pkg_genc.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -48,6 +48,8 @@ #include "uoptions.h" #include "pkg_genc.h" #include "filetools.h" +#include "charstr.h" +#include "unicode/errorcode.h" #define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU)) @@ -56,7 +58,15 @@ /* prototypes --------------------------------------------------------------- */ static void -getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename); +getOutFilename( + const char *inFilename, + const char *destdir, + char *outFilename, + int32_t outFilenameCapacity, + char *entryName, + int32_t entryNameCapacity, + const char *newSuffix, + const char *optFilename); static uint32_t write8(FileStream *out, uint8_t byte, uint32_t column); @@ -259,13 +269,21 @@ } U_CAPI void U_EXPORT2 -writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) { +writeAssemblyCode( + const char *filename, + const char *destdir, + const char *optEntryPoint, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity) { uint32_t column = MAX_COLUMN; - char entry[64]; - uint32_t buffer[1024]; - char *bufferStr = (char *)buffer; + char entry[96]; + union { + uint32_t uint32s[1024]; + char chars[4096]; + } buffer; FileStream *in, *out; - size_t i, length; + size_t i, length, count; in=T_FileStream_open(filename, "rb"); if(in==NULL) { @@ -273,15 +291,27 @@ exit(U_FILE_ACCESS_ERROR); } - getOutFilename(filename, destdir, bufferStr, entry, ".S", optFilename); - out=T_FileStream_open(bufferStr, "w"); + getOutFilename( + filename, + destdir, + buffer.chars, + sizeof(buffer.chars), + entry, + sizeof(entry), + ".S", + optFilename); + out=T_FileStream_open(buffer.chars, "w"); if(out==NULL) { - fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr); + fprintf(stderr, "genccode: unable to open output file %s\n", buffer.chars); exit(U_FILE_ACCESS_ERROR); } if (outFilePath != NULL) { - uprv_strcpy(outFilePath, bufferStr); + if (uprv_strlen(buffer.chars) >= outFilePathCapacity) { + fprintf(stderr, "genccode: filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + uprv_strcpy(outFilePath, buffer.chars); } #if defined (WINDOWS_WITH_GNUC) && U_PLATFORM != U_PF_CYGWIN @@ -302,29 +332,42 @@ } } - sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header, + count = snprintf( + buffer.chars, sizeof(buffer.chars), + assemblyHeader[assemblyHeaderIndex].header, entry, entry, entry, entry, entry, entry, entry, entry); - T_FileStream_writeLine(out, bufferStr); + if (count >= sizeof(buffer.chars)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + T_FileStream_writeLine(out, buffer.chars); T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine); for(;;) { - memset(buffer, 0, sizeof(buffer)); - length=T_FileStream_read(in, buffer, sizeof(buffer)); + memset(buffer.uint32s, 0, sizeof(buffer.uint32s)); + length=T_FileStream_read(in, buffer.uint32s, sizeof(buffer.uint32s)); if(length==0) { break; } - for(i=0; i<(length/sizeof(buffer[0])); i++) { - column = write32(out, buffer[i], column); + for(i=0; i<(length/sizeof(buffer.uint32s[0])); i++) { + // TODO: What if the last read sees length not as a multiple of 4? + column = write32(out, buffer.uint32s[i], column); } } T_FileStream_writeLine(out, "\n"); - sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer, + count = snprintf( + buffer.chars, sizeof(buffer.chars), + assemblyHeader[assemblyHeaderIndex].footer, entry, entry, entry, entry, entry, entry, entry, entry); - T_FileStream_writeLine(out, bufferStr); + if (count >= sizeof(buffer.chars)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + T_FileStream_writeLine(out, buffer.chars); if(T_FileStream_error(in)) { fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); @@ -341,11 +384,17 @@ } U_CAPI void U_EXPORT2 -writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) { +writeCCode( + const char *filename, + const char *destdir, + const char *optName, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity) { uint32_t column = MAX_COLUMN; - char buffer[4096], entry[64]; + char buffer[4096], entry[96]; FileStream *in, *out; - size_t i, length; + size_t i, length, count; in=T_FileStream_open(filename, "rb"); if(in==NULL) { @@ -354,16 +403,35 @@ } if(optName != NULL) { /* prepend 'icudt28_' */ - strcpy(entry, optName); - strcat(entry, "_"); + // +2 includes the _ and the NUL + if (uprv_strlen(optName) + 2 > sizeof(entry)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + strcpy(entry, optName); + strcat(entry, "_"); } else { - entry[0] = 0; + entry[0] = 0; } - getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename); + getOutFilename( + filename, + destdir, + buffer, + sizeof(buffer), + entry + uprv_strlen(entry), + sizeof(entry) - uprv_strlen(entry), + ".c", + optFilename); + if (outFilePath != NULL) { + if (uprv_strlen(buffer) >= outFilePathCapacity) { + fprintf(stderr, "genccode: filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } uprv_strcpy(outFilePath, buffer); } + out=T_FileStream_open(buffer, "w"); if(out==NULL) { fprintf(stderr, "genccode: unable to open output file %s\n", buffer); @@ -391,7 +459,7 @@ magic numbers we must still use the initial double. [grhoten 4/24/2003] */ - sprintf(buffer, + count = snprintf(buffer, sizeof(buffer), "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" @@ -403,6 +471,10 @@ " const char *bytes; \n" "} %s={ 0.0, \n", entry); + if (count >= sizeof(buffer)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } T_FileStream_writeLine(out, buffer); for(;;) { @@ -418,7 +490,7 @@ T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n"); #else /* Function renaming shouldn't be done in data */ - sprintf(buffer, + count = snprintf(buffer, sizeof(buffer), "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" @@ -430,6 +502,10 @@ " uint8_t bytes[%ld]; \n" "} %s={ 0.0, {\n", (long)T_FileStream_size(in), entry); + if (count >= sizeof(buffer)) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } T_FileStream_writeLine(out, buffer); for(;;) { @@ -583,66 +659,84 @@ #endif static void -getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) { +getOutFilename( + const char *inFilename, + const char *destdir, + char *outFilename, + int32_t outFilenameCapacity, + char *entryName, + int32_t entryNameCapacity, + const char *newSuffix, + const char *optFilename) { const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.'); + icu::CharString outFilenameBuilder; + icu::CharString entryNameBuilder; + icu::ErrorCode status; + /* copy path */ if(destdir!=NULL && *destdir!=0) { - do { - *outFilename++=*destdir++; - } while(*destdir!=0); - if(*(outFilename-1)!=U_FILE_SEP_CHAR) { - *outFilename++=U_FILE_SEP_CHAR; - } - inFilename=basename; + outFilenameBuilder.append(destdir, status); + outFilenameBuilder.ensureEndsWithFileSeparator(status); } else { - while(inFilename= outFilenameCapacity) { + fprintf(stderr, "genccode: output filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + + if (entryNameBuilder.length() >= entryNameCapacity) { + fprintf(stderr, "genccode: entry name too long (long filename?)\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } + + uprv_strcpy(outFilename, outFilenameBuilder.data()); + uprv_strcpy(entryName, entryNameBuilder.data()); } #ifdef CAN_GENERATE_OBJECTS @@ -777,7 +871,14 @@ } U_CAPI void U_EXPORT2 -writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) { +writeObjectCode( + const char *filename, + const char *destdir, + const char *optEntryPoint, + const char *optMatchArch, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity) { /* common variables */ char buffer[4096], entry[96]={ 0 }; FileStream *in, *out; @@ -1061,8 +1162,21 @@ } size=T_FileStream_size(in); - getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename); + getOutFilename( + filename, + destdir, + buffer, + sizeof(buffer), + entry + entryOffset, + sizeof(entry) - entryOffset, + newSuffix, + optFilename); + if (outFilePath != NULL) { + if (uprv_strlen(buffer) >= outFilePathCapacity) { + fprintf(stderr, "genccode: filename too long\n"); + exit(U_ILLEGAL_ARGUMENT_ERROR); + } uprv_strcpy(outFilePath, buffer); } diff -Nru icu-64.2/source/tools/toolutil/pkg_genc.h icu-65.1/source/tools/toolutil/pkg_genc.h --- icu-64.2/source/tools/toolutil/pkg_genc.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/pkg_genc.h 2019-10-03 11:16:41.000000000 +0000 @@ -75,12 +75,31 @@ checkAssemblyHeaderName(const char* optAssembly); U_INTERNAL void U_EXPORT2 -writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath); +writeCCode( + const char *filename, + const char *destdir, + const char *optName, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity); U_INTERNAL void U_EXPORT2 -writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath); +writeAssemblyCode( + const char *filename, + const char *destdir, + const char *optEntryPoint, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity); U_INTERNAL void U_EXPORT2 -writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath); +writeObjectCode( + const char *filename, + const char *destdir, + const char *optEntryPoint, + const char *optMatchArch, + const char *optFilename, + char *outFilePath, + size_t outFilePathCapacity); #endif diff -Nru icu-64.2/source/tools/toolutil/pkgitems.cpp icu-65.1/source/tools/toolutil/pkgitems.cpp --- icu-64.2/source/tools/toolutil/pkgitems.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/pkgitems.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -305,7 +305,8 @@ break; } int32_t length; - const UChar *alias=res_getString(pResData, res, &length); + // No tracing: build tool + const UChar *alias=res_getStringNoTrace(pResData, res, &length); checkAlias(itemName, res, alias, length, useResSuffix, check, context, pErrorCode); } break; diff -Nru icu-64.2/source/tools/toolutil/toolutil.cpp icu-65.1/source/tools/toolutil/toolutil.cpp --- icu-64.2/source/tools/toolutil/toolutil.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/toolutil.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -243,7 +243,7 @@ char name[64]; int32_t capacity, maxCapacity, size, idx; void *array; - UAlignedMemory staticArray[1]; + alignas(max_align_t) char staticArray[1]; }; U_CAPI UToolMemory * U_EXPORT2 diff -Nru icu-64.2/source/tools/toolutil/toolutil.vcxproj icu-65.1/source/tools/toolutil/toolutil.vcxproj --- icu-64.2/source/tools/toolutil/toolutil.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/toolutil.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -33,18 +33,14 @@ <_ProjectFileVersion>10.0.30319.1 - .\..\..\..\lib\ - .\x86\Release\ - false - .\..\..\..\lib\ - .\x86\Debug\ - true - .\x64\Release\ - .\x64\Release\ - false - .\x64\Debug\ - .\x64\Debug\ - true + .\$(Platform)\$(Configuration)\ + .\$(Platform)\$(Configuration)\ + + .\x86\$(Configuration)\ + .\x86\$(Configuration)\ + + true + false @@ -53,30 +49,49 @@ U_TOOLUTIL_IMPLEMENTATION;%(PreprocessorDefinitions) false Level3 + Default - - - .\..\..\..\lib\icutu.tlb - + + + + true + MultiThreadedDebugDLL + EditAndContinue + + + icuucd.lib;icuind.lib;%(AdditionalDependencies) + + + + - true MultiThreadedDLL true - .\x86\Release/toolutil.pch - .\x86\Release/ - .\x86\Release/ - .\x86\Release/ - Default - ..\..\..\bin\icutu64.dll icuuc.lib;icuin.lib;%(AdditionalDependencies) + + + + + + .\x86\$(Configuration)/toolutil.pch + .\x86\$(Configuration)/ + .\x86\$(Configuration)/ + .\x86\$(Configuration)/ + + ..\..\..\lib;%(AdditionalLibraryDirectories) + + + + + .\..\..\..\lib\icutu.tlb + + + ..\..\..\bin\icutu65.dll .\..\..\..\lib\icutu.pdb - UseLinkTimeCodeGeneration - 0x4ac00000 - false ..\..\..\lib\icutu.lib @@ -86,48 +101,36 @@ .\..\..\..\lib\icutud.tlb - - MultiThreadedDebugDLL - .\x86\Debug/toolutil.pch - .\x86\Debug/ - .\x86\Debug/ - .\x86\Debug/ - EditAndContinue - Default - - ..\..\..\bin\icutu64d.dll - icuucd.lib;icuind.lib;%(AdditionalDependencies) - ..\..\..\lib;%(AdditionalLibraryDirectories) + ..\..\..\bin\icutu65d.dll .\..\..\..\lib\icutud.pdb - 0x4ac00000 - false ..\..\..\lib\icutud.lib + + + + .\x64\$(Configuration)/toolutil.pch + .\x64\$(Configuration)/ + .\x64\$(Configuration)/ + .\x64\$(Configuration)/ + + + ..\..\..\lib64;%(AdditionalLibraryDirectories) + + .\..\..\..\lib64\icutu.tlb true - MultiThreadedDLL - true - .\x64\Release/toolutil.pch - .\x64\Release/ - .\x64\Release/ - .\x64\Release/ - Default - ..\..\..\bin64\icutu64.dll - icuuc.lib;icuin.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) + ..\..\..\bin64\icutu65.dll .\..\..\..\lib64\icutu.pdb - UseLinkTimeCodeGeneration - 0x4ac00000 ..\..\..\lib64\icutu.lib @@ -135,22 +138,78 @@ .\..\..\..\lib64\icutud.tlb + + ..\..\..\bin64\icutu65d.dll + .\..\..\..\lib64\icutud.pdb + ..\..\..\lib64\icutud.lib + + + + + .\ARM\$(Configuration)/toolutil.pch + .\ARM\$(Configuration)/ + .\ARM\$(Configuration)/ + .\ARM\$(Configuration)/ + + + .\..\..\..\libARM;%(AdditionalLibraryDirectories) + + + + + ..\..\..\libARM\icutu.tlb + + + ..\..\..\binARM\icutu65.dll + .\..\..\..\libARM\icutu.pdb + ..\..\..\libARM\icutu.lib + + + + + .\..\..\..\libARM\icutud.tlb + - MultiThreadedDebugDLL - .\x64\Debug/toolutil.pch - .\x64\Debug/ - .\x64\Debug/ - .\x64\Debug/ ProgramDatabase - Default - ..\..\..\bin64\icutu64d.dll - icuucd.lib;icuind.lib;%(AdditionalDependencies) - ..\..\..\lib64;%(AdditionalLibraryDirectories) - .\..\..\..\lib64\icutud.pdb - 0x4ac00000 - ..\..\..\lib64\icutud.lib + ..\..\..\binARM\icutu65d.dll + .\..\..\..\libARM\icutud.pdb + ..\..\..\libARM\icutud.lib + + + + + .\ARM64\$(Configuration)/toolutil.pch + .\ARM64\$(Configuration)/ + .\ARM64\$(Configuration)/ + .\ARM64\$(Configuration)/ + + + .\..\..\..\libARM64;%(AdditionalLibraryDirectories) + + + + + .\..\..\..\libARM64\icutu.tlb + + + ..\..\..\binARM64\icutu65.dll + .\..\..\..\libARM64\icutu.pdb + ..\..\..\libARM64\icutu.lib + + + + + .\..\..\..\libARM64\icutud.tlb + + + ProgramDatabase + + + ..\..\..\binARM64\icutu65d.dll + .\..\..\..\libARM64\icutud.pdb + ..\..\..\libARM64\icutud.lib diff -Nru icu-64.2/source/tools/toolutil/ucbuf.h icu-65.1/source/tools/toolutil/ucbuf.h --- icu-64.2/source/tools/toolutil/ucbuf.h 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/ucbuf.h 2019-10-03 11:16:41.000000000 +0000 @@ -32,11 +32,11 @@ /** * End of file value */ -#define U_EOF 0xFFFFFFFF +#define U_EOF ((int32_t)0xFFFFFFFF) /** * Error value if a sequence cannot be unescaped */ -#define U_ERR 0xFFFFFFFE +#define U_ERR ((int32_t)0xFFFFFFFE) typedef struct ULine ULine; diff -Nru icu-64.2/source/tools/toolutil/xmlparser.cpp icu-65.1/source/tools/toolutil/xmlparser.cpp --- icu-64.2/source/tools/toolutil/xmlparser.cpp 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/toolutil/xmlparser.cpp 2019-10-03 11:16:41.000000000 +0000 @@ -313,7 +313,7 @@ // reached end of file, convert once more to flush the converter flush=TRUE; } - }; + } exit: ucnv_close(cnv); diff -Nru icu-64.2/source/tools/tzcode/icuzdump.vcxproj icu-65.1/source/tools/tzcode/icuzdump.vcxproj --- icu-64.2/source/tools/tzcode/icuzdump.vcxproj 2019-04-17 19:42:15.000000000 +0000 +++ icu-65.1/source/tools/tzcode/icuzdump.vcxproj 2019-10-03 11:16:41.000000000 +0000 @@ -77,7 +77,6 @@ true .\x86\Debug/icuzdump.pdb Console - false NotSet @@ -97,7 +96,6 @@ Console true true - false MachineX86