1 define: #Glob &parents: {Cloneable} &slots: {}.
3 Glob traits define: #Pattern &parents: {Glob} &slots: {#components}.
4 Glob traits define: #PatternMatcher &parents: {Glob} &slots: {#reader. #maskPattern}.
6 Glob traits define: #PatternFailure.
8 Glob traits define: #PatternComponent &parents: {Glob}.
9 Glob traits define: #PatternLiteral &parents: {Glob PatternComponent} &slots: {#string -> ''}.
10 Glob traits define: #PatternRange &parents: {Glob PatternComponent} &slots: {
11 #ranges -> ExtensibleArray new.
14 Glob traits define: #PatternAny &parents: {Glob PatternComponent}.
15 Glob traits define: #PatternAnyOne &parents: {Glob PatternComponent}.
17 glob@(Glob traits) newOn: s
18 [glob Pattern newOn: s].
20 glob@(Glob Pattern traits) newOn: s@(String traits)
22 glob components := ExtensibleArray new.
23 glob readFrom: s reader.
27 glob@(Glob Pattern traits) readFrom: s@(ReadStream traits)
34 (#{$*. $?. $\[. } includes: token) /\ [prev contents isEmpty not]
35 ifTrue: [matcher nextPut: (glob PatternLiteral new `>> [string := prev contents. ]).
38 $* -> [matcher nextPut: glob PatternAny].
39 $? -> [matcher nextPut: glob PatternAnyOne].
40 $\[ -> [matcher nextPut: (glob readRange := s upTo: $\])]
41 } otherwise: [prev nextPut: token]].
42 prev contents isEmpty ifFalse: [matcher nextPut: (glob PatternLiteral new `>> [string := prev contents. ])]] writingAs: glob components.
45 glob@(Glob Pattern traits) readRange: str@(String traits)
48 p := glob PatternRange new `>>
50 ranges := p ranges new.
51 negate := '^!' includes: (char2 := s peek). ].
54 (char2 := s peek) = $-
55 ifTrue: [s next. p ranges addLast: char -> s next]
56 ifFalse: [p ranges addLast: char]].
60 glob@(Glob Pattern traits) match: str@(String traits) from: pos
62 (glob PatternMatcher new `>> [maskPattern := glob. reader := glob components reader. ]) match: str from: pos
65 glob@(Glob PatternMatcher traits) match: str@(String traits) from: pos
67 "inform: 'match reader: ' ; glob reader printString ; ' pos: ' ; pos printString."
70 (token isSameAs: glob PatternAny)
71 ifTrue: [str size downTo: pos do:
72 [| :start | ((glob new `>> [reader := glob reader clone. ]) match: str from: start) = str size
73 ifTrue: [^ str size]]]
74 ifFalse: [(pos := (token match: str from: pos))
75 == glob PatternFailure ifTrue: [^ pos]]].
79 glob@(Glob Pattern traits) matches: str@(String traits)
81 (match ::= glob match: str from: 0) ~== glob PatternFailure /\ [match = str size]
84 glob@(Glob PatternAny traits) match: str@(String traits) from: pos
86 (pos to: str size - pos)
89 glob@(Glob PatternAnyOne traits) match: str@(String traits) from: pos
91 pos >= str size ifTrue: [glob PatternFailure] ifFalse: [pos + 1]
94 glob@(Glob PatternRange traits) match: str@(String traits) from: pos
96 pos >= str size \/ [glob matches: (str at: pos)] ifTrue: [glob PatternFailure] ifFalse: [pos + 1]
99 glob@(Glob PatternLiteral traits) match: str@(String traits) from: pos
101 pos + glob string size > str size ifTrue: [^ glob PatternFailure].
102 (str copyFrom: pos to: pos + glob string size - 1) = glob string ifTrue: [pos + glob string size] ifFalse: [glob PatternFailure]
105 glob@(Glob PatternRange traits) matches: c@(String Character traits)
108 [| :range | ((range isSameAs: c) /\ [range = c]) \/
109 [c code between: range key code and: c code]]