@@ -70,18 +70,17 @@ internal func _parseUnsignedAsciiAsUIntMax(
70
70
/// - Note: For text matching the regular expression "-0+", the result
71
71
/// is `0`, not `nil`.
72
72
internal func _parseAsciiAsUIntMax(
73
- u16 : String.UTF16View, _ radix: Int, _ maximum: UIntMax
73
+ utf16 : String.UTF16View, _ radix: Int, _ maximum: UIntMax
74
74
) -> UIntMax? {
75
- if u16.isEmpty { return nil }
76
- let c = u16.first
77
- if _fastPath(c != _ascii16("-")) {
78
- let unsignedText
79
- = c == _ascii16("+") ? u16.dropFirst() : u16
80
- return _parseUnsignedAsciiAsUIntMax(unsignedText, radix, maximum)
81
- }
82
- else {
83
- return _parseAsciiAsIntMax(u16, radix, 0) == 0 ? 0 : nil
84
- }
75
+ if utf16.isEmpty { return nil }
76
+ // Parse (optional) sign
77
+ let (digitsUTF16, hasMinus) = _parseOptionalAsciiSign(utf16)
78
+ // Parse digits
79
+ guard let result = _parseUnsignedAsciiAsUIntMax(digitsUTF16, radix, maximum) else { return nil }
80
+ // Disallow < 0
81
+ if hasMinus && result != 0 { return nil }
82
+ // Return
83
+ return result
85
84
}
86
85
87
86
/// If text is an ASCII representation in the given `radix` of a
@@ -91,23 +90,28 @@ internal func _parseAsciiAsUIntMax(
91
90
/// - Note: For text matching the regular expression "-0+", the result
92
91
/// is `0`, not `nil`.
93
92
internal func _parseAsciiAsIntMax(
94
- u16 : String.UTF16View, _ radix: Int, _ maximum: IntMax
93
+ utf16 : String.UTF16View, _ radix: Int, _ maximum: IntMax
95
94
) -> IntMax? {
96
95
_sanityCheck(maximum >= 0, "maximum should be non-negative")
96
+ if utf16.isEmpty { return nil }
97
+ // Parse (optional) sign
98
+ let (digitsUTF16, hasMinus) = _parseOptionalAsciiSign(utf16)
99
+ // Parse digits
100
+ let absValueMax = UIntMax(bitPattern: maximum) + (hasMinus ? 1 : 0)
101
+ guard let absValue = _parseUnsignedAsciiAsUIntMax(digitsUTF16, radix, absValueMax) else { return nil }
102
+ // Return signed result
103
+ return IntMax(bitPattern: hasMinus ? 0 &- absValue : absValue)
104
+ }
97
105
98
- if u16.isEmpty { return nil }
99
-
100
- // Drop any leading "-"
101
- let negative = u16.first == _ascii16("-")
102
- let absResultText = negative ? u16.dropFirst() : u16
103
-
104
- let absResultMax = UIntMax(bitPattern: maximum) + (negative ? 1 : 0)
105
-
106
- // Parse the result as unsigned
107
- if let absResult = _parseAsciiAsUIntMax(absResultText, radix, absResultMax) {
108
- return IntMax(bitPattern: negative ? 0 &- absResult : absResult)
106
+ /// Strip an optional single leading ASCII plus/minus sign from `utf16`.
107
+ private func _parseOptionalAsciiSign(
108
+ utf16: String.UTF16View
109
+ ) -> (digitsUTF16: String.UTF16View, isMinus: Bool) {
110
+ switch utf16.first {
111
+ case _ascii16("-")?: return (utf16.dropFirst(), true)
112
+ case _ascii16("+")?: return (utf16.dropFirst(), false)
113
+ default: return (utf16, false)
109
114
}
110
- return nil
111
115
}
112
116
113
117
//===--- Loop over all integer types --------------------------------------===//
0 commit comments