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