@@ -167,6 +167,13 @@ extension CChar {
167167 }
168168}
169169
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+
170177private func findCheckType( in buf : UnsafeBufferPointer < CChar > , with prefix : String ) -> CheckType {
171178 let nextChar = UInt8 ( buf [ prefix. utf8. count] )
172179
@@ -245,21 +252,35 @@ private func findFirstMatch(in inbuffer : UnsafeBufferPointer<CChar>, among pref
245252
246253 while !buffer. isEmpty {
247254 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 {
250257 return ( " " , . none, lineNumber, buffer)
251258 }
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+ )
254268
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
257278 // Check that the matched prefix isn't a suffix of some other check-like
258279 // word.
259280 // FIXME: This is a very ad-hoc check. it would be better handled in some
260281 // other way. Among other things it seems hard to distinguish between
261282 // intentional and unintentional uses of this feature.
262- if skippedPrefix. isEmpty || !skippedPrefix. last!. isPartOfWord {
283+ if skippedPrefix. isEmpty || !skippedPrefix. characters . last!. isPartOfWord {
263284 // Now extract the type.
264285 let CheckTy = findCheckType ( in: buffer, with: prefixStr)
265286
@@ -279,11 +300,10 @@ private func findFirstMatch(in inbuffer : UnsafeBufferPointer<CChar>, among pref
279300 }
280301 buffer = buffer. dropFront ( loc)
281302 }
282-
303+
283304 return ( " " , . none, lineNumber, buffer)
284305}
285306
286-
287307private func readCheckStrings( in buf : UnsafeBufferPointer < CChar > , withPrefixes prefixes : [ String ] , options: FileCheckOptions , _ RE : NSRegularExpression ) -> [ CheckString ] {
288308 // Keeps track of the line on which CheckPrefix instances are found.
289309 var lineNumber = 1
0 commit comments