@@ -45,49 +45,54 @@ func readShellStyleSpecial(pb *patternBuild, valsIn []typedVal) (pathVals []type
4545 return
4646}
4747
48- // makeShellStyleAutomaton - recognize a "-delimited string containing one or more '*' globs.
49- // TODO: Add “?”
50- func makeShellStyleAutomaton (val []byte , useThisTansition * fieldMatcher ) (start * smallTable , nextField * fieldMatcher ) {
48+ // mssA2 - recognize a "-delimited string containing one or more '*' globs.
49+ // This isn't quite as simple as you'd think. Consider matching "*abc". When you see an 'a' you move to a state
50+ // where you're looking for 'b'. So if it's not a 'b' you go back to the '*' state. But suppose you see "xaabc";
51+ // when you're in that looking-for-'b' state and you see that second 'a', you don't go back to the '*' state, you
52+ // have to stay in the looking-for-'b' state because you have seen the 'a'. Similarly, when you see 'xabac', when
53+ // you're looking for 'c' and you see the 'a', once again, you have to go to the looking-for-'b' state. Let's
54+ // call the 'a the bounceBackByte and the looking-for-b state the bounceBackStep
55+ func makeShellStyleAutomaton (val []byte , useThisTransition * fieldMatcher ) (start * smallTable , nextField * fieldMatcher ) {
5156 table := newSmallTable ()
5257 start = table
53- if useThisTansition != nil {
54- nextField = useThisTansition
58+ if useThisTransition != nil {
59+ nextField = useThisTransition
5560 } else {
5661 nextField = newFieldMatcher ()
5762 }
5863
59- // since this is provided as a string, the last byte will be '"'. In the special case where the pattern ends
60- // with '*' (and thus the string ends with '*"', we will insert a successful transition as soon as we hit
61- // that last '*', so that the reaching the transition doesn't require going through the trailing characters to
62- // reach the '"'
63- if val [len (val ) - 2 ] == '*' {
64- for i := 0 ; i < len (val ) - 2 ; i ++ {
65- ch := val [i ]
66- if ch == '*' {
67- table .addRangeSteps (0 , ByteCeiling , table )
68- } else {
69- next := newSmallTable ()
70- table .addByteStep (ch , next )
71- table = next
72- }
73- }
74- table .addRangeSteps (0 , ByteCeiling , newSmallTransition (nextField ))
75- return
76- }
64+ var bounceBackByte byte
65+ var bounceBackStep smallStep = nil
66+ var globStep smallStep = nil
7767
78- // loop through all but last byte
79- for i := 0 ; i < len (val )- 1 ; i ++ {
68+ // loop through all but last bytea
69+ i := 0
70+ for i < len (val )- 1 {
8071 ch := val [i ]
8172 if ch == '*' {
82- // just loop back
83- table .addRangeSteps (0 , ByteCeiling , table )
73+ // special-case handling for string ending in '*"'
74+ if i == len (val )- 2 {
75+ lastStep := newSmallTransition (nextField )
76+ table .addRangeSteps (0 , ByteCeiling , lastStep )
77+ return
78+ }
79+ globStep = table
80+ i ++
81+ bounceBackStep = newSmallTable ()
82+ bounceBackByte = val [i ]
83+ table .load (table , []byte {val [i ]}, []smallStep {bounceBackStep })
84+ table = bounceBackStep .SmallTable ()
8485 } else {
8586 next := newSmallTable ()
87+ if globStep != nil {
88+ table .load (globStep , []byte {bounceBackByte }, []smallStep {bounceBackStep })
89+ }
8690 table .addByteStep (ch , next )
8791 table = next
8892 }
93+ i ++
8994 }
90-
9195 table .addByteStep (val [len (val )- 1 ], newSmallTransition (nextField ))
96+
9297 return
9398}
0 commit comments