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 | matcher overlap pat target t =
25 | case length pat == S Z of
27 | let patzero := index Z pat
30 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.matcher: can't index into ByteString") # t
32 | let headelem := elemIndex patzero' pat
35 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.matcher: byte does not appear in ByteString") # t
37 | (headelem' :: []) # t
39 | let dfa # t := automaton pat t
40 | match' # t := match Z Z pat target Lin dfa overlap t
41 | in (match' <>> []) # t
43 | match : (state : Nat)
45 | -> (pat : ByteString)
46 | -> (target : ByteString)
47 | -> (final : SnocList Nat)
48 | -> (dfa : MArray s (mult (plus (length pat) 1) 256) Nat)
50 | -> F1 s (SnocList Nat)
51 | match Z idx pat target final dfa overlap t =
52 | case idx == length target of
56 | let idx' := index idx target
59 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.matcher:match: can't index into ByteString") # t
61 | let patzero := index Z pat
64 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.matcher:match: can't index into ByteString") # t
66 | case idx'' == patzero' of
68 | assert_total (match (S 0) (S idx) pat target final dfa overlap t)
70 | assert_total (match Z (S idx) pat target final dfa overlap t)
71 | match state idx pat target final dfa overlap t =
72 | case idx == length target of
76 | let idx' := index idx target
79 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.matcher:match: can't index into ByteString") # t
81 | let nstateidx := plus (mult state 256) (cast {to=Nat} idx'')
82 | in case tryNatToFin nstateidx of
84 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.matcher:match: can't convert Nat to Fin") # t
86 | let nstate # t := get dfa nstateidx' t
88 | in case nstate == length pat of
90 | let final' := minus nxtidx (length pat)
91 | final'' := final :< final'
94 | let ams := S (minus nxtidx (length pat))
95 | in assert_total (match Z ams pat target final'' dfa overlap t)
97 | assert_total (match Z nxtidx pat target final'' dfa overlap t)
99 | assert_total (match nstate nxtidx pat target final dfa overlap t)
127 | matchDFA : (pat : ByteString)
128 | -> (target : ByteString)
129 | -> {0 prfpat : So (not $
null pat)}
130 | -> {0 prftarget : So (not $
null target)}
132 | matchDFA pat target {prfpat} {prftarget} t =
133 | matcher False pat target t
158 | indicesDFA : (pat : ByteString)
159 | -> (target : ByteString)
160 | -> {0 prfpat : So (not $
null pat)}
161 | -> {0 prftarget : So (not $
null target)}
163 | indicesDFA pat target {prfpat} {prftarget} t =
164 | matcher True pat target t
178 | breakDFA : (pat : ByteString)
179 | -> (target : ByteString)
180 | -> {0 prfpat : So (not $
null pat)}
181 | -> {0 prftarget : So (not $
null target)}
182 | -> {0 prflength : So ((length target) >= (length pat))}
183 | -> F1 s (ByteString, ByteString)
184 | breakDFA pat target {prfpat} {prftarget} {prflength} t =
185 | let matcher' # t := matcher False pat target t
186 | in case matcher' of
188 | (target, empty) # t
190 | let target' := splitAt (cast {to=Nat} i) target
193 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.breakDFA: can't split ByteString") # t
210 | breakAfterDFA : (pat : ByteString)
211 | -> (target : ByteString)
212 | -> {0 prfpat : So (not $
null pat)}
213 | -> {0 prftarget : So (not $
null target)}
214 | -> {0 prflength : So ((length target) >= (length pat))}
215 | -> F1 s (ByteString, ByteString)
216 | breakAfterDFA pat target {prfpat} {prftarget} {prflength} t =
217 | let matcher' # t := matcher False pat target t
218 | in case matcher' of
220 | (target, empty) # t
222 | let target' := splitAt (plus (cast {to=Nat} i) (length pat)) target
225 | (assert_total $
idris_crash "Data.ByteString.Search.DFA.breakAfterDFA: can't split ByteString") # t
244 | splitKeepFrontDFA : (pat : ByteString)
245 | -> (target : ByteString)
246 | -> {0 prfpat : So (not $
null pat)}
247 | -> {0 prftarget : So (not $
null target)}
248 | -> {0 prflength : So ((length target) >= (length pat))}
249 | -> F1 s (List ByteString)
250 | splitKeepFrontDFA pat target {prfpat} {prftarget} {prflength} t =
251 | let splitter' # t := splitter pat target Lin t
252 | in (splitter' <>> []) # t
254 | psSplitter : (pat : ByteString)
255 | -> (target : ByteString)
256 | -> (final : SnocList ByteString)
257 | -> F1 s (SnocList ByteString)
258 | psSplitter pat target final t =
259 | let matcher' # t := matcher False pat (drop (length pat) target) t
260 | in case matcher' of
262 | let final' := final :< target
265 | let length' := plus (cast {to=Nat} i) (length pat)
266 | final' := final :< (take length' target)
267 | in assert_total (psSplitter pat (drop length' target) final' t)
268 | splitter : (pat : ByteString)
269 | -> (target : ByteString)
270 | -> (final : SnocList ByteString)
271 | -> F1 s (SnocList ByteString)
272 | splitter pat target final t =
273 | let matcher' # t := matcher False pat target t
274 | in case matcher' of
276 | let final' := final :< target
281 | assert_total (psSplitter pat target final t)
283 | let final' := final :< (take (cast {to=Nat} i) target)
284 | in assert_total (psSplitter pat (drop (cast {to=Nat} i) target) final' t)
307 | splitKeepEndDFA : (pat : ByteString)
308 | -> (target : ByteString)
309 | -> {0 prfpat : So (not $
null pat)}
310 | -> {0 prftarget : So (not $
null target)}
311 | -> {0 prflength : So ((length target) >= (length pat))}
312 | -> F1 s (List ByteString)
313 | splitKeepEndDFA pat target {prfpat} {prftarget} {prflength} t =
314 | let splitter' # t := splitter pat target Lin t
315 | in (splitter' <>> []) # t
317 | splitter : (pat : ByteString)
318 | -> (target : ByteString)
319 | -> (final : SnocList ByteString)
320 | -> F1 s (SnocList ByteString)
321 | splitter pat target final t =
322 | let matcher' # t := matcher False pat target t
323 | in case matcher' of
325 | let final' := final :< target
328 | let length' := plus (cast {to=Nat} i) (length pat)
329 | final' := final :< (take length' target)
330 | in assert_total (splitter pat (drop length' target) final' t)
355 | splitDropDFA : (pat : ByteString)
356 | -> (target : ByteString)
357 | -> {0 prfpat : So (not $
null pat)}
358 | -> {0 prftarget : So (not $
null target)}
359 | -> {0 prflength : So ((length target) >= (length pat))}
360 | -> F1 s (List ByteString)
361 | splitDropDFA pat target {prfpat} {prftarget} {prflength} t =
362 | let splitter' # t := splitter pat target Lin t
363 | in (splitter' <>> []) # t
365 | splitter : (pat : ByteString)
366 | -> (target : ByteString)
367 | -> (final : SnocList ByteString)
368 | -> F1 s (SnocList ByteString)
369 | splitter pat target final t =
370 | let matcher' # t := matcher False pat target t
371 | in case matcher' of
373 | let final' := final :< target
376 | let length' := plus (cast {to=Nat} i) (length pat)
377 | final' := final :< (take (cast {to=Nat} i) target)
378 | in assert_total (splitter pat (drop length' target) final' t)
401 | replaceDFA : (pat : ByteString)
402 | -> (sub : ByteString)
403 | -> (target : ByteString)
404 | -> {0 prfpat : So (not $
null pat)}
405 | -> {0 prftarget : So (not $
null target)}
406 | -> {0 prflength : So ((length target) >= (length pat))}
407 | -> F1 s (List ByteString)
408 | replaceDFA pat sub target {prfpat} {prftarget} {prflength} t =
409 | let replacer' # t := replacer pat sub target Lin t
410 | in (replacer' <>> []) # t
412 | replacer : (pat : ByteString)
413 | -> (sub : ByteString)
414 | -> (target : ByteString)
415 | -> (final : SnocList ByteString)
416 | -> F1 s (SnocList ByteString)
417 | replacer pat sub target final t =
418 | let matcher' # t := matcher False pat target t
419 | in case matcher' of
421 | let final' := final :< target
428 | assert_total (replacer pat sub (drop (length pat) target) final t)
430 | let final' := final :< sub
431 | in assert_total (replacer pat sub (drop (length pat) target) final') t
435 | let length' := plus (cast {to=Nat} i) (length pat)
436 | final' := final :< (take (cast {to=Nat} i) target)
437 | in assert_total (replacer pat sub (drop length' target) final' t)
439 | let length' := plus (cast {to=Nat} i) (length pat)
440 | final' := final :< (take (cast {to=Nat} i) target) :< sub
441 | in assert_total (replacer pat sub (drop length' target) final' t)