Skip to content

Commit 529891c

Browse files
committed
[stdlib] Simplify implementation of string-to-integer parsing.
1 parent ebad4bb commit 529891c

File tree

1 file changed

+9
-80
lines changed

1 file changed

+9
-80
lines changed

stdlib/public/core/IntegerParsing.swift

Lines changed: 9 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -10,67 +10,6 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
// N.B.: This free function has been manually specialized below where
14-
// `UTF8CodeUnits == UnsafeBufferPoint<UInt8>`. Ensure that any changes are
15-
// made in sync.
16-
@_alwaysEmitIntoClient
17-
@inline(never)
18-
internal func _parseASCIIDigits<
19-
UTF8CodeUnits: Collection, Result: FixedWidthInteger
20-
>(
21-
_ codeUnits: UTF8CodeUnits, radix: Int, isNegative: Bool
22-
) -> Result? where UTF8CodeUnits.Element == UInt8 {
23-
_internalInvariant(radix >= 2 && radix <= 36)
24-
guard _fastPath(!codeUnits.isEmpty) else { return nil }
25-
let multiplicand = Result(radix)
26-
var result = 0 as Result
27-
if radix <= 10 {
28-
let upperBound = 48 /* "0" */ &+ UInt8(radix)
29-
for digit in codeUnits {
30-
let digitValue: Result
31-
if _fastPath(digit >= 48 && digit < upperBound) {
32-
digitValue = Result(digit &- 48)
33-
} else {
34-
return nil
35-
}
36-
let (temporary, overflow1) =
37-
result.multipliedReportingOverflow(by: multiplicand)
38-
guard _fastPath(!overflow1) else { return nil }
39-
let (nextResult, overflow2) = isNegative
40-
? temporary.subtractingReportingOverflow(digitValue)
41-
: temporary.addingReportingOverflow(digitValue)
42-
guard _fastPath(!overflow2) else { return nil }
43-
result = nextResult
44-
}
45-
} else {
46-
let uppercaseUpperBound = 65 /* "A" */ &+ UInt8(radix &- 10)
47-
let lowercaseUpperBound = 97 /* "a" */ &+ UInt8(radix &- 10)
48-
for digit in codeUnits {
49-
let digitValue: Result
50-
if _fastPath(digit >= 48 /* "0" */ && digit < 58) {
51-
digitValue = Result(digit &- 48)
52-
} else if _fastPath(digit >= 65 && digit < uppercaseUpperBound) {
53-
digitValue = Result(digit &- 65 &+ 10)
54-
} else if _fastPath(digit >= 97 && digit < lowercaseUpperBound) {
55-
digitValue = Result(digit &- 97 &+ 10)
56-
} else {
57-
return nil
58-
}
59-
let (temporary, overflow1) =
60-
result.multipliedReportingOverflow(by: multiplicand)
61-
guard _fastPath(!overflow1) else { return nil }
62-
let (nextResult, overflow2) = isNegative
63-
? temporary.subtractingReportingOverflow(digitValue)
64-
: temporary.addingReportingOverflow(digitValue)
65-
guard _fastPath(!overflow2) else { return nil }
66-
result = nextResult
67-
}
68-
}
69-
return result
70-
}
71-
72-
// N.B.: This free function is a manually specialized version of the function
73-
// above. Ensure that any changes are made in sync.
7413
@_alwaysEmitIntoClient
7514
internal func _parseASCIIDigits<Result: FixedWidthInteger>(
7615
_ codeUnits: UnsafeBufferPointer<UInt8>, radix: Int, isNegative: Bool
@@ -124,24 +63,6 @@ internal func _parseASCIIDigits<Result: FixedWidthInteger>(
12463
return result
12564
}
12665

127-
@_alwaysEmitIntoClient
128-
@inline(never)
129-
internal func _parseASCII<UTF8CodeUnits: Collection, Result: FixedWidthInteger>(
130-
_ codeUnits: UTF8CodeUnits, radix: Int
131-
) -> Result? where UTF8CodeUnits.Element == UInt8 {
132-
_internalInvariant(!codeUnits.isEmpty)
133-
let first = codeUnits.first!
134-
if first == 45 /* "-" */ {
135-
return _parseASCIIDigits(
136-
codeUnits.dropFirst(), radix: radix, isNegative: true)
137-
}
138-
if first == 43 /* "+" */ {
139-
return _parseASCIIDigits(
140-
codeUnits.dropFirst(), radix: radix, isNegative: false)
141-
}
142-
return _parseASCIIDigits(codeUnits, radix: radix, isNegative: false)
143-
}
144-
14566
@_alwaysEmitIntoClient
14667
internal func _parseASCII<Result: FixedWidthInteger>(
14768
_ codeUnits: UnsafeBufferPointer<UInt8>, radix: Int
@@ -161,6 +82,14 @@ internal func _parseASCII<Result: FixedWidthInteger>(
16182
return _parseASCIIDigits(codeUnits, radix: radix, isNegative: false)
16283
}
16384

85+
@_alwaysEmitIntoClient
86+
internal func _parseASCII<S: StringProtocol, Result: FixedWidthInteger>(
87+
_ text: S, radix: Int
88+
) -> Result? {
89+
var str = String(text)
90+
return str.withUTF8 { _parseASCII($0, radix: radix) }
91+
}
92+
16493
extension FixedWidthInteger {
16594
/// Creates a new integer value from the given string and radix.
16695
///
@@ -203,7 +132,7 @@ extension FixedWidthInteger {
203132
let result: Self? =
204133
text.utf8.withContiguousStorageIfAvailable {
205134
_parseASCII($0, radix: radix)
206-
} ?? _parseASCII(text.utf8, radix: radix)
135+
} ?? _parseASCII(text, radix: radix)
207136
guard let result_ = result else { return nil }
208137
self = result_
209138
}

0 commit comments

Comments
 (0)