| 23 | type StringPrefixFilter func(input string, startAt int) (candidateByteIndex int, ok bool) |
| 24 | |
| 25 | func newStringPrefixFilter(code *syntax.Code) StringPrefixFilter { |
| 26 | if code == nil || code.RightToLeft || code.FindOptimizations == nil { |
| 27 | return nil |
| 28 | } |
| 29 | |
| 30 | opts := code.FindOptimizations |
| 31 | minRequiredLength := opts.MinRequiredLength |
| 32 | |
| 33 | switch opts.FindMode { |
| 34 | case syntax.LeadingString_LeftToRight: |
| 35 | return stringIndexPrefixFilter(opts.LeadingPrefix, false, minRequiredLength) |
| 36 | case syntax.LeadingString_OrdinalIgnoreCase_LeftToRight: |
| 37 | return stringIndexPrefixFilter(opts.LeadingPrefix, true, minRequiredLength) |
| 38 | case syntax.LeadingStrings_LeftToRight: |
| 39 | return stringIndexPrefixesFilter(opts.LeadingPrefixes, false, minRequiredLength) |
| 40 | case syntax.LeadingStrings_OrdinalIgnoreCase_LeftToRight: |
| 41 | return stringIndexPrefixesFilter(opts.LeadingPrefixes, true, minRequiredLength) |
| 42 | case syntax.LeadingSet_LeftToRight: |
| 43 | if len(opts.FixedDistanceSets) == 0 { |
| 44 | return nil |
| 45 | } |
| 46 | set := opts.FixedDistanceSets[0] |
| 47 | if set.Range == nil && (len(set.Chars) == 0 || len(set.Chars) > 5) { |
| 48 | return nil |
| 49 | } |
| 50 | return stringFixedDistanceSetFilter(set, minRequiredLength) |
| 51 | case syntax.FixedDistanceChar_LeftToRight: |
| 52 | return stringFixedDistanceCharFilter(opts.FixedDistanceLiteral.C, opts.FixedDistanceLiteral.Distance, minRequiredLength) |
| 53 | case syntax.FixedDistanceString_LeftToRight: |
| 54 | return stringFixedDistanceStringFilter(opts.FixedDistanceLiteral.S, opts.FixedDistanceLiteral.Distance, minRequiredLength) |
| 55 | case syntax.LiteralAfterLoop_LeftToRight: |
| 56 | return stringLiteralAfterLoopFilter(opts.LiteralAfterLoop, minRequiredLength) |
| 57 | default: |
| 58 | return nil |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | type asciiSetStringScanner struct { |
| 63 | chars string |