@@ -167,6 +167,13 @@ extension CChar {
167
167
}
168
168
}
169
169
170
+ extension Character {
171
+ fileprivate var isPartOfWord : Bool {
172
+ let utf8Value = String ( self ) . utf8. first!
173
+ return isalnum ( Int32 ( utf8Value) ) != 0 || utf8Value == " - " . utf8. first! || utf8Value == " _ " . utf8. first!
174
+ }
175
+ }
176
+
170
177
private func findCheckType( in buf : UnsafeBufferPointer < CChar > , with prefix : String ) -> CheckType {
171
178
let nextChar = UInt8 ( buf [ prefix. utf8. count] )
172
179
@@ -245,21 +252,35 @@ private func findFirstMatch(in inbuffer : UnsafeBufferPointer<CChar>, among pref
245
252
246
253
while !buffer. isEmpty {
247
254
let str = String ( bytesNoCopy: UnsafeMutableRawPointer ( mutating: buffer. baseAddress!) , length: buffer. count, encoding: . utf8, freeWhenDone: false ) !
248
- let matches = RE . matches ( in: str, options: [ ] , range: NSRange ( location: 0 , length: buffer . count ) )
249
- guard let prefix = matches . first else {
255
+ let match = RE . firstMatch ( in: str, options: [ ] , range: NSRange ( location: 0 , length: str . distance ( from : str . startIndex , to : str . endIndex ) ) )
256
+ guard let prefix = match else {
250
257
return ( " " , . none, lineNumber, buffer)
251
258
}
252
- let skippedPrefix = buffer. substr ( 0 , prefix. range. location)
253
- let prefixStr = substring ( in: buffer, with: prefix. range)
259
+ let skippedPrefix = substring ( in: buffer, with: NSMakeRange ( 0 , prefix. range. location) )
260
+ let prefixStr = str. substring (
261
+ with: Range (
262
+ uncheckedBounds: (
263
+ str. index ( str. startIndex, offsetBy: prefix. range. location) ,
264
+ str. index ( str. startIndex, offsetBy: NSMaxRange ( prefix. range) )
265
+ )
266
+ )
267
+ )
254
268
255
- buffer = buffer. dropFront ( prefix. range. location)
256
- lineNumber += skippedPrefix. filter ( { c in UInt8 ( c) == " \n " . utf8. first! } ) . count
269
+ // HACK: Conversion between the buffer and `String` causes index
270
+ // mismatches when searching for strings. We're instead going to do
271
+ // something terribly inefficient here: Use the regular expression to
272
+ // look for check prefixes, then use Foundation's Data to find their
273
+ // actual locations in the buffer.
274
+ let bd = Data ( buffer: buffer)
275
+ let range = bd. range ( of: prefixStr. data ( using: . utf8) !) !
276
+ buffer = buffer. dropFront ( range. lowerBound)
277
+ lineNumber += skippedPrefix. characters. filter ( { c in c == " \n " } ) . count
257
278
// Check that the matched prefix isn't a suffix of some other check-like
258
279
// word.
259
280
// FIXME: This is a very ad-hoc check. it would be better handled in some
260
281
// other way. Among other things it seems hard to distinguish between
261
282
// intentional and unintentional uses of this feature.
262
- if skippedPrefix. isEmpty || !skippedPrefix. last!. isPartOfWord {
283
+ if skippedPrefix. isEmpty || !skippedPrefix. characters . last!. isPartOfWord {
263
284
// Now extract the type.
264
285
let CheckTy = findCheckType ( in: buffer, with: prefixStr)
265
286
@@ -279,11 +300,10 @@ private func findFirstMatch(in inbuffer : UnsafeBufferPointer<CChar>, among pref
279
300
}
280
301
buffer = buffer. dropFront ( loc)
281
302
}
282
-
303
+
283
304
return ( " " , . none, lineNumber, buffer)
284
305
}
285
306
286
-
287
307
private func readCheckStrings( in buf : UnsafeBufferPointer < CChar > , withPrefixes prefixes : [ String ] , options: FileCheckOptions , _ RE : NSRegularExpression ) -> [ CheckString ] {
288
308
// Keeps track of the line on which CheckPrefix instances are found.
289
309
var lineNumber = 1
0 commit comments