diff --git a/Foundation/NSScanner.swift b/Foundation/NSScanner.swift index cd1873f9db..28ec5c17df 100644 --- a/Foundation/NSScanner.swift +++ b/Foundation/NSScanner.swift @@ -224,37 +224,12 @@ internal protocol _IntegerLike : Integer, _BitShiftable { static var min: Self { get } } -internal protocol _FloatArithmeticType { - static func +(lhs: Self, rhs: Self) -> Self - static func -(lhs: Self, rhs: Self) -> Self - static func *(lhs: Self, rhs: Self) -> Self - static func /(lhs: Self, rhs: Self) -> Self -} - -internal protocol _FloatLike : FloatingPoint, _FloatArithmeticType { - init(_ value: Int) - init(_ value: Double) - static var max: Self { get } - static var min: Self { get } -} - extension Int : _IntegerLike { } extension Int32 : _IntegerLike { } extension Int64 : _IntegerLike { } extension UInt32 : _IntegerLike { } extension UInt64 : _IntegerLike { } -// these might be good to have in the stdlib -extension Float : _FloatLike { - static var max: Float { return FLT_MAX } - static var min: Float { return FLT_MIN } -} - -extension Double : _FloatLike { - static var max: Double { return DBL_MAX } - static var min: Double { return DBL_MIN } -} - private func numericValue(_ ch: unichar) -> Int { if (ch >= unichar(unicodeScalarLiteral: "0") && ch <= unichar(unicodeScalarLiteral: "9")) { return Int(ch) - Int(unichar(unicodeScalarLiteral: "0")) @@ -366,7 +341,7 @@ extension String { return true } - internal func scan(_ skipSet: CharacterSet?, locale: Locale?, locationToScanFrom: inout Int, to: (T) -> Void) -> Bool { + internal func scan(_ skipSet: CharacterSet?, locale: Locale?, locationToScanFrom: inout Int, to: (T) -> Void) -> Bool { let ds_chars = decimalSep(locale).utf16 let ds = ds_chars[ds_chars.startIndex] var buf = _NSStringBuffer(string: self, start: locationToScanFrom, end: length) @@ -388,13 +363,13 @@ extension String { if numeral == -1 { break } - // if (localResult >= T.max / T(10)) && ((localResult > T.max / T(10)) || T(numericValue(buf.currentCharacter) - (neg ? 1 : 0)) >= T.max - localResult * T(10)) is evidently too complex; so break it down to more "edible chunks" - let limit1 = localResult >= T.max / T(10) - let limit2 = localResult > T.max / T(10) - let limit3 = T(numeral - (neg ? 1 : 0)) >= T.max - localResult * T(10) + // if (localResult >= T.greatestFiniteMagnitude / T(10)) && ((localResult > T.greatestFiniteMagnitude / T(10)) || T(numericValue(buf.currentCharacter) - (neg ? 1 : 0)) >= T.greatestFiniteMagnitude - localResult * T(10)) is evidently too complex; so break it down to more "edible chunks" + let limit1 = localResult >= T.greatestFiniteMagnitude / T(10) + let limit2 = localResult > T.greatestFiniteMagnitude / T(10) + let limit3 = T(numeral - (neg ? 1 : 0)) >= T.greatestFiniteMagnitude - localResult * T(10) if (limit1) && (limit2 || limit3) { // apply the clamps and advance past the ending of the buffer where there are still digits - localResult = neg ? T.min : T.max + localResult = neg ? -T.infinity : T.infinity neg = false repeat { buf.advance() @@ -425,7 +400,7 @@ extension String { return true } - internal func scanHex(_ skipSet: CharacterSet?, locale: Locale?, locationToScanFrom: inout Int, to: (T) -> Void) -> Bool { + internal func scanHex(_ skipSet: CharacterSet?, locale: Locale?, locationToScanFrom: inout Int, to: (T) -> Void) -> Bool { NSUnimplemented() } } diff --git a/TestFoundation/TestNSScanner.swift b/TestFoundation/TestNSScanner.swift index 88f9254a08..a6d53c3d30 100644 --- a/TestFoundation/TestNSScanner.swift +++ b/TestFoundation/TestNSScanner.swift @@ -24,6 +24,7 @@ class TestNSScanner : XCTestCase { static var allTests: [(String, (TestNSScanner) -> () throws -> Void)] { return [ ("test_scanInteger", test_scanInteger), + ("test_scanFloat", test_scanFloat), ] } @@ -33,4 +34,11 @@ class TestNSScanner : XCTestCase { XCTAssert(scanner.scanInteger(&value), "An Integer should be found in the string `123`.") XCTAssertEqual(value, 123, "Scanned Integer value of the string `123` should be `123`.") } + + func test_scanFloat() { + let scanner = Scanner(string: "-350000000000000000000000000000000000000000") + var value: Float = 0 + XCTAssert(scanner.scanFloat(&value), "A Float should be found in the string `-350000000000000000000000000000000000000000`.") + XCTAssert(value.isInfinite, "Scanned Float value of the string `-350000000000000000000000000000000000000000` should be infinite`.") + } }