@@ -136,60 +136,56 @@ extension DataProtocol {
136
136
return self . copyBytes ( to: UnsafeMutableRawBufferPointer ( start: ptr. baseAddress, count: ptr. count * MemoryLayout< DestinationType> . stride) , from: range)
137
137
}
138
138
139
+ private func matches< D: DataProtocol > ( _ data: D , from index: Index ) -> Bool {
140
+ var haystackIndex = index
141
+ var needleIndex = data. startIndex
142
+
143
+ while true {
144
+ guard self [ haystackIndex] == data [ needleIndex] else { return false }
145
+
146
+ haystackIndex = self . index ( after: haystackIndex)
147
+ needleIndex = data. index ( after: needleIndex)
148
+ if needleIndex == data. endIndex {
149
+ // i.e. needle is found.
150
+ return true
151
+ } else if haystackIndex == endIndex {
152
+ return false
153
+ }
154
+ }
155
+ }
156
+
139
157
public func firstRange< D: DataProtocol , R: RangeExpression > ( of data: D , in range: R ) -> Range < Index > ? where R. Bound == Index {
140
158
let r = range. relative ( to: self )
141
- let rangeCount = distance ( from: r. lowerBound, to: r. upperBound)
142
- if rangeCount < data. count {
159
+ let length = data. count
160
+
161
+ if length == 0 || length > distance ( from: r. lowerBound, to: r. upperBound) {
143
162
return nil
144
163
}
145
- var haystackIndex = r. lowerBound
146
- let haystackEnd = index ( r. upperBound, offsetBy: - data. count)
147
- while haystackIndex < haystackEnd {
148
- var compareIndex = haystackIndex
149
- var needleIndex = data. startIndex
150
- let needleEnd = data. endIndex
151
- var matched = true
152
- while compareIndex < haystackEnd && needleIndex < needleEnd {
153
- if self [ compareIndex] != data [ needleIndex] {
154
- matched = false
155
- break
156
- }
157
- needleIndex = data. index ( after: needleIndex)
158
- compareIndex = index ( after: compareIndex)
159
- }
160
- if matched {
161
- return haystackIndex..< compareIndex
164
+
165
+ var position = r. lowerBound
166
+ while position < r. upperBound && distance ( from: position, to: r. upperBound) >= length {
167
+ if matches ( data, from: position) {
168
+ return position..< index ( position, offsetBy: length)
162
169
}
163
- haystackIndex = index ( after: haystackIndex )
170
+ position = index ( after: position )
164
171
}
165
172
return nil
166
173
}
167
174
168
175
public func lastRange< D: DataProtocol , R: RangeExpression > ( of data: D , in range: R ) -> Range < Index > ? where R. Bound == Index {
169
176
let r = range. relative ( to: self )
170
- let rangeCount = distance ( from: r. lowerBound, to: r. upperBound)
171
- if rangeCount < data. count {
177
+ let length = data. count
178
+
179
+ if length == 0 || length > distance ( from: r. lowerBound, to: r. upperBound) {
172
180
return nil
173
181
}
174
- var haystackIndex = r. upperBound
175
- let haystackStart = index ( r. lowerBound, offsetBy: data. count)
176
- while haystackIndex > haystackStart {
177
- var compareIndex = haystackIndex
178
- var needleIndex = data. endIndex
179
- let needleStart = data. startIndex
180
- var matched = true
181
- while compareIndex > haystackStart && needleIndex > needleStart {
182
- if self [ compareIndex] != data [ needleIndex] {
183
- matched = false
184
- break
185
- }
186
- needleIndex = data. index ( before: needleIndex)
187
- compareIndex = index ( before: compareIndex)
188
- }
189
- if matched {
190
- return compareIndex..< haystackIndex
182
+
183
+ var position = index ( r. upperBound, offsetBy: - length)
184
+ while position >= r. lowerBound {
185
+ if matches ( data, from: position) {
186
+ return position..< index ( position, offsetBy: length)
191
187
}
192
- haystackIndex = index ( before: haystackIndex )
188
+ position = index ( before: position )
193
189
}
194
190
return nil
195
191
}
0 commit comments