Skip to content

Commit 5cdc5c4

Browse files
committed
Revert "SR-1464: NSNumber.description is not compatible between OS X and linux"
This reverts commit d99a2f6. See discussion in #1929 for details.
1 parent edba71c commit 5cdc5c4

File tree

4 files changed

+42
-246
lines changed

4 files changed

+42
-246
lines changed

CoreFoundation/String.subproj/CFString.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5996,7 +5996,7 @@ enum {
59965996
CFFormatDummyPointerType = 42 /* special case for %n */
59975997
};
59985998

5999-
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
5999+
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
60006000
/* Only come in here if spec->type is CFFormatLongType or CFFormatDoubleType. Pass in 0 for width or precision if not specified. Returns false if couldn't do the format (with the assumption the caller falls back to unlocalized).
60016001
*/
60026002
static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLocaleRef locale, const CFPrintValue *values, const CFFormatSpec *spec, SInt32 width, SInt32 precision, Boolean hasPrecision) {
@@ -6980,7 +6980,7 @@ static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFString
69806980
switch (specs[curSpec].type) {
69816981
case CFFormatLongType:
69826982
case CFFormatDoubleType:
6983-
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
6983+
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
69846984
if (localizedFormatting && (specs[curSpec].flags & kCFStringFormatLocalizable)) { // We have a locale, so we do localized formatting
69856985
if (__CFStringFormatLocalizedNumber(outputString, (CFLocaleRef)formatOptions, values, &specs[curSpec], width, precision, hasPrecision)) break;
69866986
}

Foundation/NSNumber.swift

Lines changed: 23 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ open class NSNumber : NSValue {
915915
}
916916

917917
open var stringValue: String {
918-
return self.description
918+
return description(withLocale: nil)
919919
}
920920

921921
/// Create an instance initialized to `value`.
@@ -958,86 +958,39 @@ open class NSNumber : NSValue {
958958
}
959959
}
960960

961-
open func description(withLocale locale: Locale?) -> String {
962-
guard let locale = locale else { return self.description }
963-
switch _CFNumberGetType2(_cfObject) {
964-
case kCFNumberSInt8Type, kCFNumberCharType:
965-
return String(format: "%d", locale: locale, self.int8Value)
966-
967-
case kCFNumberSInt16Type, kCFNumberShortType:
968-
return String(format: "%hi", locale: locale, self.int16Value)
969-
970-
case kCFNumberSInt32Type:
971-
return String(format: "%d", locale: locale, self.int32Value)
961+
private static let _numberFormatterForNilLocale: CFNumberFormatter = {
962+
let formatter: CFNumberFormatter
963+
formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
964+
CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObjectiveC())
965+
return formatter
966+
}()
972967

973-
case kCFNumberIntType, kCFNumberLongType, kCFNumberNSIntegerType, kCFNumberCFIndexType:
974-
return String(format: "%ld", locale: locale, self.intValue)
975-
976-
case kCFNumberSInt64Type, kCFNumberLongLongType:
977-
return String(format: "%lld", locale: locale, self.int64Value)
978-
979-
case kCFNumberSInt128Type:
980-
let value = self.int128Value
981-
if value.high == 0 {
982-
return value.low.description // BUG: "%llu" doesnt work correctly and treats number as signed
983-
} else {
984-
// BUG: Note the locale is actually ignored here as this is converted using CFNumber.c:emit128()
985-
return String(format: "%@", locale: locale, unsafeBitCast(_cfObject, to: UnsafePointer<CFNumber>.self))
986-
}
987-
988-
case kCFNumberFloatType, kCFNumberFloat32Type:
989-
return String(format: "%0.7g", locale: locale, self.floatValue)
990-
991-
case kCFNumberFloat64Type, kCFNumberDoubleType:
992-
return String(format: "%0.16g", locale: locale, self.doubleValue)
968+
open func description(withLocale locale: Locale?) -> String {
969+
// CFNumberFormatterCreateStringWithNumber() does not like numbers of type
970+
// SInt128Type, as it loses the type when looking it up and treats it as
971+
// an SInt64Type, so special case them.
972+
if _CFNumberGetType2(_cfObject) == kCFNumberSInt128Type {
973+
return String(format: "%@", unsafeBitCast(_cfObject, to: UnsafePointer<CFNumber>.self))
974+
}
993975

994-
case kCFNumberCGFloatType:
995-
if Int.max == Int32.max {
996-
return String(format: "%0.7g", locale: locale, self.floatValue)
997-
} else {
998-
return String(format: "%0.16g", locale: locale, self.doubleValue)
999-
}
1000-
default: fatalError("Unknown NSNumber Type")
976+
let aLocale = locale
977+
let formatter: CFNumberFormatter
978+
if (aLocale == nil) {
979+
formatter = NSNumber._numberFormatterForNilLocale
980+
} else {
981+
formatter = CFNumberFormatterCreate(nil, aLocale?._cfObject, kCFNumberFormatterDecimalStyle)
1001982
}
983+
return CFNumberFormatterCreateStringWithNumber(nil, formatter, self._cfObject)._swiftObject
1002984
}
1003985

1004986
override open var _cfTypeID: CFTypeID {
1005987
return CFNumberGetTypeID()
1006988
}
1007989

1008990
open override var description: String {
1009-
switch _CFNumberGetType2(_cfObject) {
1010-
case kCFNumberSInt8Type, kCFNumberCharType, kCFNumberSInt16Type, kCFNumberShortType,
1011-
kCFNumberSInt32Type, kCFNumberIntType, kCFNumberLongType, kCFNumberNSIntegerType, kCFNumberCFIndexType:
1012-
return self.intValue.description
1013-
1014-
case kCFNumberSInt64Type, kCFNumberLongLongType:
1015-
return self.int64Value.description
1016-
1017-
case kCFNumberSInt128Type:
1018-
let value = self.int128Value
1019-
if value.high == 0 {
1020-
return value.low.description
1021-
} else {
1022-
return String(format: "%@", locale: nil, unsafeBitCast(_cfObject, to: UnsafePointer<CFNumber>.self))
1023-
}
1024-
1025-
case kCFNumberFloatType, kCFNumberFloat32Type:
1026-
return self.floatValue.description
1027-
1028-
case kCFNumberFloat64Type, kCFNumberDoubleType:
1029-
return self.doubleValue.description
1030-
1031-
case kCFNumberCGFloatType:
1032-
if Int.max == Int32.max {
1033-
return self.floatValue.description
1034-
} else {
1035-
return self.doubleValue.description
1036-
}
1037-
default: fatalError("Unknown NSNumber Type")
1038-
}
991+
return description(withLocale: nil)
1039992
}
1040-
993+
1041994
internal func _cfNumberType() -> CFNumberType {
1042995
switch objCType.pointee {
1043996
case 0x42: return kCFNumberCharType

0 commit comments

Comments
 (0)