| 318 | } |
| 319 | |
| 320 | func stringFixedDistanceStringFilter(literal string, distance, minRequiredLength int) StringPrefixFilter { |
| 321 | if literal == "" || distance < 0 || len(literal) > maxStringFilterLiteralLen { |
| 322 | return nil |
| 323 | } |
| 324 | |
| 325 | return func(input string, startAt int) (candidateByteIndex int, ok bool) { |
| 326 | if !hasMinRequiredBytes(input, startAt, minRequiredLength) { |
| 327 | return 0, false |
| 328 | } |
| 329 | |
| 330 | searchAt := startAt |
| 331 | for searchAt <= len(input)-len(literal) { |
| 332 | offset := strings.Index(input[searchAt:], literal) |
| 333 | if offset < 0 { |
| 334 | return 0, false |
| 335 | } |
| 336 | literalIndex := searchAt + offset |
| 337 | candidateByteIndex, ok := stringFixedDistanceCandidateStart(input, startAt, literalIndex, distance) |
| 338 | if ok && hasMinRequiredBytes(input, candidateByteIndex, minRequiredLength) { |
| 339 | return candidateByteIndex, true |
| 340 | } |
| 341 | if ok { |
| 342 | return 0, false |
| 343 | } |
| 344 | searchAt = literalIndex + 1 |
| 345 | } |
| 346 | return 0, false |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | func stringLiteralAfterLoopFilter(literal *syntax.LiteralAfterLoop, minRequiredLength int) StringPrefixFilter { |
| 351 | if literal == nil || literal.LoopNode == nil || literal.LoopNode.Set == nil { |