Skip to content

ICU: Update TestNumberFormatter tests to be compatible with ICU62+ and Darwin #2535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions CoreFoundation/Locale.subproj/CFNumberFormatter.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,13 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR
}

if (kCFNumberFormatterNoStyle == style) {
#if U_ICU_VERSION_MAJOR_NUM < 62
// ICU62+ is stricter about patterns matching attribute settings and setting UNUM_MAX_INTEGER_DIGITS = 42 would result in a pattern of 42x '#' not 1x '#' as is set here.
UChar ubuff[1];
status = U_ZERO_ERROR;
ubuff[0] = '#';

__cficu_unum_applyPattern(memory->_nf, false, ubuff, 1, NULL, &status);
__cficu_unum_setAttribute(memory->_nf, UNUM_MAX_INTEGER_DIGITS, 42);
__cficu_unum_setAttribute(memory->_nf, UNUM_MAX_FRACTION_DIGITS, 0);
#endif
}
//Prior to Gala, CFLocaleCreateCopy() always just retained. This caused problems because CFLocaleGetValue(locale, kCFLocaleCalendarKey) would create a calendar, then set its locale to self, leading to a retain cycle
//Since we're not in that situation here, and this is a frequently used path, we retain as we used to
Expand Down
39 changes: 27 additions & 12 deletions Foundation/NumberFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,12 @@ open class NumberFormatter : Formatter {

private func _setFormatterAttributes(_ formatter: CFNumberFormatter) {
if numberStyle == .currency {
let symbol = _currencySymbol ?? _currencyCode ?? locale.currencySymbol ?? locale.currencyCode
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterCurrencySymbol, value: symbol?._cfObject)
let symbol = _currencySymbol ?? locale.currencySymbol
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterCurrencySymbol, value: symbol?._cfObject)

if let code = _currencyCode, code.count == 3 {
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterCurrencyCode, value: code._cfObject)
}
}
if numberStyle == .currencyISOCode {
let code = _currencyCode ?? _currencySymbol ?? locale.currencyCode ?? locale.currencySymbol
Expand Down Expand Up @@ -152,10 +156,8 @@ open class NumberFormatter : Formatter {
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterRoundingMode, value: _roundingMode.rawValue._bridgeToObjectiveC()._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterRoundingIncrement, value: _roundingIncrement?._cfObject)

var width: Int = 0
CFNumberGetValue(_formatWidth._bridgeToObjectiveC()._cfObject, kCFNumberLongType, &width)
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterFormatWidth, value: _formatWidth._bridgeToObjectiveC()._cfObject)
if width > 0 {
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterFormatWidth, value: _formatWidth?._bridgeToObjectiveC()._cfObject)
if self.formatWidth > 0 {
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterPaddingCharacter, value: _paddingCharacter?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterPaddingPosition, value: _paddingPosition.rawValue._bridgeToObjectiveC()._cfObject)
} else {
Expand Down Expand Up @@ -192,10 +194,10 @@ open class NumberFormatter : Formatter {
// to indicate to use the default value (if nil) or the caller-supplied value (if not nil).
private func defaultMinimumIntegerDigits() -> Int {
switch numberStyle {
case .none, .ordinal, .spellOut, .currencyPlural, .scientific:
case .ordinal, .spellOut, .currencyPlural:
return 0

case .currency, .currencyISOCode, .currencyAccounting, .decimal, .percent:
case .none, .currency, .currencyISOCode, .currencyAccounting, .decimal, .percent, .scientific:
return 1
}
}
Expand Down Expand Up @@ -245,14 +247,14 @@ open class NumberFormatter : Formatter {
return 0

case .currency, .none, .currencyISOCode, .currencyAccounting, .decimal, .percent, .scientific:
return 1
return -1
}
}

private func defaultMaximumSignificantDigits() -> Int {
switch numberStyle {
case .none, .currency, .currencyISOCode, .currencyAccounting, .decimal, .percent, .scientific:
return 6
return -1

case .ordinal, .spellOut, .currencyPlural:
return 0
Expand Down Expand Up @@ -286,6 +288,16 @@ open class NumberFormatter : Formatter {
}
}

private func defaultFormatWidth() -> Int {
switch numberStyle {
case .ordinal, .ordinal, .spellOut, .currencyPlural:
return 0

case .none, .decimal, .currency, .percent, .scientific, .currencyISOCode, .currencyAccounting:
return -1
}
}

private var _numberStyle: Style = .none
open var numberStyle: Style {
get {
Expand Down Expand Up @@ -683,10 +695,10 @@ open class NumberFormatter : Formatter {
}
}

private var _formatWidth: Int = 0
private var _formatWidth: Int?
open var formatWidth: Int {
get {
return _formatWidth
return _formatWidth ?? defaultFormatWidth()
}
set {
_reset()
Expand Down Expand Up @@ -849,6 +861,9 @@ open class NumberFormatter : Formatter {
_reset()
_usesSignificantDigits = true
_minimumSignificantDigits = newValue
if _maximumSignificantDigits == nil && newValue > defaultMinimumSignificantDigits() {
_maximumSignificantDigits = (newValue < 1000) ? 999 : newValue
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion TestFoundation/TestNSNumber.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1152,8 +1152,8 @@ class TestNSNumber : XCTestCase {
// Currently disabled as the latest ICU (62+) which uses Google's dobule-conversion library currently converts Double.leastNonzeroMagnitude to 0
// although the ICU61 version correctly converted it to 5E-324 - Test left in to check for the bug being fixed in the future.
//XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).description(withLocale: Locale(identifier: "en_GB")), "5E-324")
XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).description(withLocale: Locale(identifier: "en_GB")), "0E+00")
XCTAssertEqual(NSNumber(value: 2 * Double.leastNonzeroMagnitude).description(withLocale: Locale(identifier: "en_GB")), "1E-323")

XCTAssertEqual(NSNumber(value: Double.greatestFiniteMagnitude).description(withLocale: Locale(identifier: "en_GB")), "1.797693134862316E+308")

// de_DE Locale
Expand Down Expand Up @@ -1200,6 +1200,7 @@ class TestNSNumber : XCTestCase {
// Currently disabled as the latest ICU (62+) which uses Google's dobule-conversion library currently converts Double.leastNonzeroMagnitude to 0
// although the ICU61 version correctly converted it to 5E-324 - Test left in to check for the bug being fixed in the future.
//XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).description(withLocale: Locale(identifier: "de_DE")), "5E-324")
XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).description(withLocale: Locale(identifier: "de_DE")), "0E+00")
XCTAssertEqual(NSNumber(value: 2 * Double.leastNonzeroMagnitude).description(withLocale: Locale(identifier: "de_DE")), "1E-323")
XCTAssertEqual(NSNumber(value: Double.greatestFiniteMagnitude).description(withLocale: Locale(identifier: "de_DE")), "1,797693134862316E+308")
}
Expand Down
Loading