1 | module Data.ByteString.Search.DFA
3 | import Data.ByteString.Search.Internal.Utils
5 | import Data.Array.Core
6 | import Data.Array.Mutable
8 | import Data.ByteString
9 | import Data.Linear.Ref1
12 | %hide Data.Buffer.Core.get
13 | %hide Data.Buffer.Core.set
24 | -> F1 s (Maybe (List Nat))
25 | matcher overlap pat target t =
26 | let False := length pat == S Z
28 | let patzero := index Z pat
29 | Just patzero' := patzero
32 | headelem := elemIndex patzero' pat
33 | Just headelem' := headelem
36 | in Just (headelem' :: []) # t
37 | dfa # t := automaton pat t
41 | match' # t := match Z Z pat target Lin dfa' overlap t
42 | Just match'' := match'
45 | in Just (match'' <>> []) # t
47 | match : (state : Nat)
49 | -> (pat : ByteString)
50 | -> (target : ByteString)
51 | -> (final : SnocList Nat)
52 | -> (dfa : MArray s (mult (plus (length pat) 1) 256) Nat)
54 | -> F1 s (Maybe (SnocList Nat))
55 | match Z idx pat target final dfa overlap t =
56 | let False := idx == length target
59 | idx' := index idx target
63 | patzero := index Z pat
64 | Just patzero' := patzero
67 | False := idx'' == patzero'
69 | assert_total (match (S 0) (S idx) pat target final dfa overlap t)
70 | in assert_total (match Z (S idx) pat target final dfa overlap t)
71 | match state idx pat target final dfa overlap t =
72 | let False := idx == length target
75 | idx' := index idx target
79 | nstateidx := plus (mult state 256) (cast {to=Nat} idx'')
80 | Just nstateidx' := tryNatToFin nstateidx
83 | nstate # t := get dfa nstateidx' t
85 | True := nstate == length pat
87 | assert_total (match nstate nxtidx pat target final dfa overlap t)
88 | final' := minus nxtidx (length pat)
89 | final'' := final :< final'
92 | assert_total (match Z nxtidx pat target final'' dfa overlap t)
93 | ams := S (minus nxtidx (length pat))
94 | in assert_total (match Z ams pat target final'' dfa overlap t)
122 | matchDFA : (pat : ByteString)
123 | -> (target : ByteString)
124 | -> {0 prfpat : So (not $
null pat)}
125 | -> {0 prftarget : So (not $
null target)}
126 | -> F1 s (Maybe (List Nat))
127 | matchDFA pat target {prfpat} {prftarget} t =
128 | let matcher' # t := matcher False pat target t
129 | Just matcher'' := matcher'
132 | in Just matcher'' # t
157 | indicesDFA : (pat : ByteString)
158 | -> (target : ByteString)
159 | -> {0 prfpat : So (not $
null pat)}
160 | -> {0 prftarget : So (not $
null target)}
161 | -> F1 s (Maybe (List Nat))
162 | indicesDFA pat target {prfpat} {prftarget} t =
163 | let matcher' # t := matcher True pat target t
164 | Just matcher'' := matcher'
167 | in Just matcher'' # t
181 | breakDFA : (pat : ByteString)
182 | -> (target : ByteString)
183 | -> {0 prfpat : So (not $
null pat)}
184 | -> {0 prftarget : So (not $
null target)}
185 | -> {0 prflength : So ((length target) >= (length pat))}
186 | -> F1 s (Maybe (ByteString, ByteString))
187 | breakDFA pat target {prfpat} {prftarget} {prflength} t =
188 | let matcher' # t := matcher False pat target t
189 | Just matcher'' := matcher'
192 | (i :: _) := matcher''
194 | Just (target, empty) # t
195 | target' := splitAt (cast {to=Nat} i) target
196 | Just target'' := target'
199 | in Just target'' # t
214 | breakAfterDFA : (pat : ByteString)
215 | -> (target : ByteString)
216 | -> {0 prfpat : So (not $
null pat)}
217 | -> {0 prftarget : So (not $
null target)}
218 | -> {0 prflength : So ((length target) >= (length pat))}
219 | -> F1 s (Maybe (ByteString, ByteString))
220 | breakAfterDFA pat target {prfpat} {prftarget} {prflength} t =
221 | let matcher' # t := matcher False pat target t
222 | Just matcher'' := matcher'
225 | (i :: _) := matcher''
227 | Just (target, empty) # t
228 | target' := splitAt (plus (cast {to=Nat} i) (length pat)) target
229 | Just target'' := target'
232 | in Just target'' # t
249 | splitKeepFrontDFA : (pat : ByteString)
250 | -> (target : ByteString)
251 | -> {0 prfpat : So (not $
null pat)}
252 | -> {0 prftarget : So (not $
null target)}
253 | -> {0 prflength : So ((length target) >= (length pat))}
254 | -> F1 s (Maybe (List ByteString))
255 | splitKeepFrontDFA pat target {prfpat} {prftarget} {prflength} t =
256 | let splitter' # t := splitter pat target Lin t
257 | Just splitter'' := splitter'
260 | in Just (splitter'' <>> []) # t
262 | psSplitter : (pat : ByteString)
263 | -> (target : ByteString)
264 | -> (final : SnocList ByteString)
265 | -> F1 s (Maybe (SnocList ByteString))
266 | psSplitter pat target final t =
267 | let matcher' # t := matcher False pat (drop (length pat) target) t
268 | Just matcher'' := matcher'
271 | (i :: _) := matcher''
273 | let final' := final :< target
275 | length' := plus (cast {to=Nat} i) (length pat)
276 | final' := final :< (take length' target)
277 | in assert_total (psSplitter pat (drop length' target) final' t)
278 | splitter : (pat : ByteString)
279 | -> (target : ByteString)
280 | -> (final : SnocList ByteString)
281 | -> F1 s (Maybe (SnocList ByteString))
282 | splitter pat target final t =
283 | let matcher' # t := matcher False pat target t
284 | Just matcher'' := matcher'
287 | (i :: _) := matcher''
289 | let final' := final :< target
293 | assert_total (psSplitter pat target final t)
294 | final' := final :< (take (cast {to=Nat} i) target)
295 | in assert_total (psSplitter pat (drop (cast {to=Nat} i) target) final' t)
318 | splitKeepEndDFA : (pat : ByteString)
319 | -> (target : ByteString)
320 | -> {0 prfpat : So (not $
null pat)}
321 | -> {0 prftarget : So (not $
null target)}
322 | -> {0 prflength : So ((length target) >= (length pat))}
323 | -> F1 s (Maybe (List ByteString))
324 | splitKeepEndDFA pat target {prfpat} {prftarget} {prflength} t =
325 | let splitter' # t := splitter pat target Lin t
326 | Just splitter'' := splitter'
329 | in Just (splitter'' <>> []) # t
331 | splitter : (pat : ByteString)
332 | -> (target : ByteString)
333 | -> (final : SnocList ByteString)
334 | -> F1 s (Maybe (SnocList ByteString))
335 | splitter pat target final t =
336 | let matcher' # t := matcher False pat target t
337 | Just matcher'' := matcher'
340 | (i :: _) := matcher''
342 | let final' := final :< target
344 | length' := plus (cast {to=Nat} i) (length pat)
345 | final' := final :< (take length' target)
346 | in assert_total (splitter pat (drop length' target) final' t)
371 | splitDropDFA : (pat : ByteString)
372 | -> (target : ByteString)
373 | -> {0 prfpat : So (not $
null pat)}
374 | -> {0 prftarget : So (not $
null target)}
375 | -> {0 prflength : So ((length target) >= (length pat))}
376 | -> F1 s (Maybe (List ByteString))
377 | splitDropDFA pat target {prfpat} {prftarget} {prflength} t =
378 | let splitter' # t := splitter pat target Lin t
379 | Just splitter'' := splitter'
382 | in Just (splitter'' <>> []) # t
384 | splitter : (pat : ByteString)
385 | -> (target : ByteString)
386 | -> (final : SnocList ByteString)
387 | -> F1 s (Maybe (SnocList ByteString))
388 | splitter pat target final t =
389 | let matcher' # t := matcher False pat target t
390 | Just matcher'' := matcher'
393 | (i :: _) := matcher''
395 | let final' := final :< target
397 | length' := plus (cast {to=Nat} i) (length pat)
398 | final' := final :< (take (cast {to=Nat} i) target)
399 | in assert_total (splitter pat (drop length' target) final' t)
422 | replaceDFA : (pat : ByteString)
423 | -> (sub : ByteString)
424 | -> (target : ByteString)
425 | -> {0 prfpat : So (not $
null pat)}
426 | -> {0 prftarget : So (not $
null target)}
427 | -> {0 prflength : So ((length target) >= (length pat))}
428 | -> F1 s (Maybe (List ByteString))
429 | replaceDFA pat sub target {prfpat} {prftarget} {prflength} t =
430 | let replacer' # t := replacer pat sub target Lin t
431 | Just replacer'' := replacer'
434 | in Just (replacer'' <>> []) # t
436 | replacer : (pat : ByteString)
437 | -> (sub : ByteString)
438 | -> (target : ByteString)
439 | -> (final : SnocList ByteString)
440 | -> F1 s (Maybe (SnocList ByteString))
441 | replacer pat sub target final t =
442 | let matcher' # t := matcher False pat target t
443 | Just matcher'' := matcher'
446 | (i :: _) := matcher''
448 | let final' := final :< target
452 | let False := null sub
454 | let length' := plus (cast {to=Nat} i) (length pat)
455 | final' := final :< (take (cast {to=Nat} i) target)
456 | in assert_total (replacer pat sub (drop length' target) final' t)
457 | length' := plus (cast {to=Nat} i) (length pat)
458 | final' := final :< (take (cast {to=Nat} i) target) :< sub
459 | in assert_total (replacer pat sub (drop length' target) final' t)
462 | assert_total (replacer pat sub (drop (length pat) target) final t)
463 | final' := final :< sub
464 | in assert_total (replacer pat sub (drop (length pat) target) final') t