1 | module Data.ByteString.Search.BoyerMoore
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 Int))
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 ((cast {to=Int} headelem') :: []) # t
37 | Yes patprf := decSo (not $
null pat)
40 | occurrencesarr # t := occurrences pat {prf=patprf} t
41 | Just occurrencesarr' := occurrencesarr
44 | suffixshiftsarr # t := suffixShifts pat {prf=patprf} t
45 | Just suffixshiftsarr' := suffixshiftsarr
48 | matches # t := checkEnd (cast {to=Int} (minus (length pat) (S 0))) pat target Lin occurrencesarr' suffixshiftsarr' overlap t
49 | Just matches' := matches
52 | in Just (matches' <>> []) # t
55 | checkEnd : (stri : Int)
56 | -> (pat : ByteString)
57 | -> (target : ByteString)
58 | -> (final : SnocList Int)
59 | -> (occurrencesarr : MArray s 256 Int)
60 | -> (suffixshiftsarr : MArray s (length pat) Int)
62 | -> F1 s (Maybe (SnocList Int))
63 | checkEnd stri pat target final occurrencesarr suffixshiftarr overlap t =
64 | let patend := (cast {to=Int} (length pat)) - 1
65 | strend := (cast {to=Int} (length target)) - 1
66 | False := strend < stri
69 | target' := index (cast {to=Nat} stri) target
70 | Just target'' := target'
73 | pat' := index (cast {to=Nat} patend) pat
77 | False := target'' == pat''
79 | assert_total (findMatch (stri - patend) (patend - 1) pat target final occurrencesarr suffixshiftarr overlap t)
80 | Just target''' := tryNatToFin (cast {to=Nat} target'')
83 | target'''' # t := get occurrencesarr target''' t
84 | newtarget := stri + patend + target''''
85 | in assert_total (checkEnd newtarget pat target final occurrencesarr suffixshiftarr overlap t)
86 | findMatch : (diff : Int)
88 | -> (pat : ByteString)
89 | -> (target : ByteString)
90 | -> (final : SnocList Int)
91 | -> (occurrencesarr : MArray s 256 Int)
92 | -> (suffixshiftsarr : MArray s (length pat) Int)
94 | -> F1 s (Maybe (SnocList Int))
95 | findMatch diff pati pat target final occurrencesarr suffixshiftarr overlap t =
96 | let diffpati := index (cast {to=Nat} (diff + pati)) target
97 | Just diffpati' := diffpati
100 | pati' := index (cast {to=Nat} pati) pat
101 | Just pati'' := pati'
104 | True := diffpati' == pati''
106 | let Just diffpati'' := tryNatToFin (cast {to=Nat} diffpati')
109 | Just pati''' := tryNatToFin (cast {to=Nat} pati)
112 | occur # t := get occurrencesarr diffpati'' t
113 | suff # t := get suffixshiftarr pati''' t
114 | diff' := diff + (max (pati + occur) suff)
115 | maxdiff := minus (length target) (length pat)
116 | False := (cast {to=Int} maxdiff) < diff'
119 | in assert_total (checkEnd (diff' + ((cast {to=Int} (length pat)) - 1)) pat target final occurrencesarr suffixshiftarr overlap t)
122 | assert_total (findMatch diff (pati - 1) pat target final occurrencesarr suffixshiftarr overlap t)
123 | final' := final :< diff
126 | let skip := length pat
127 | diff' := diff + (cast {to=Int} skip)
128 | maxdiff := minus (length target) (length pat)
129 | False := (cast {to=Int} maxdiff) < diff'
132 | False := skip == (length pat)
134 | assert_total (checkEnd (diff' + ((cast {to=Int} (length pat)) - 1)) pat target final' occurrencesarr suffixshiftarr overlap t)
135 | in assert_total (afterMatch diff' ((cast {to=Int} (length pat)) - 1) pat target final' occurrencesarr suffixshiftarr overlap t)
136 | Just zero := tryNatToFin Z
139 | skip # t := get suffixshiftarr zero t
140 | diff' := diff + skip
141 | maxdiff := minus (length target) (length pat)
142 | False := (cast {to=Int} maxdiff) < diff'
145 | False := skip == (cast {to=Int} (length pat))
147 | assert_total (checkEnd (diff' + ((cast {to=Int} (length pat)) - 1)) pat target final' occurrencesarr suffixshiftarr overlap t)
148 | in assert_total (afterMatch diff' ((cast {to=Int} (length pat)) - 1) pat target final' occurrencesarr suffixshiftarr overlap t)
149 | afterMatch : (diff : Int)
151 | -> (pat : ByteString)
152 | -> (target : ByteString)
153 | -> (final : SnocList Int)
154 | -> (occurrencesarr : MArray s 256 Int)
155 | -> (suffixshiftsarr : MArray s (length pat) Int)
156 | -> (overlap : Bool)
157 | -> F1 s (Maybe (SnocList Int))
158 | afterMatch diff pati pat target final occurrencesarr suffixshiftarr overlap t =
159 | let diffpati := index (cast {to=Nat} (diff + pati)) target
160 | Just diffpati' := diffpati
163 | pati' := index (cast {to=Nat} pati) pat
164 | Just pati'' := pati'
167 | True := diffpati' == pati''
169 | let False := pati == ((cast {to=Int} (length pat)) - 1)
171 | let Just diffpati'' := tryNatToFin (cast {to=Nat} diffpati')
174 | occur # t := get occurrencesarr diffpati'' t
175 | occur' := diff + (2 * ((cast {to=Int} (length pat)) - 1)) + occur
176 | in assert_total (checkEnd occur' pat target final occurrencesarr suffixshiftarr overlap t)
177 | Just diffpati'' := tryNatToFin (cast {to=Nat} diffpati')
180 | Just pati''' := tryNatToFin (cast {to=Nat} pati)
183 | occur # t := get occurrencesarr diffpati'' t
184 | goodshift # t := get suffixshiftarr pati''' t
185 | badshift := pati + occur
186 | diff' := diff + (max badshift goodshift)
187 | maxdiff := minus (length target) (length pat)
188 | False := (cast {to=Int} maxdiff) < diff'
191 | in assert_total (checkEnd (diff + ((cast {to=Int} (length pat)) - 1)) pat target final occurrencesarr suffixshiftarr overlap t)
194 | let kept := minus (length pat) (length pat)
195 | True := pati == (cast {to=Int} kept)
197 | assert_total (afterMatch diff (pati - 1) pat target final occurrencesarr suffixshiftarr overlap t)
198 | final' := final :< diff
200 | diff' := diff + (cast {to=Int} skip)
201 | maxdiff := minus (length target) (length pat)
202 | False := (cast {to=Int} maxdiff) < diff'
205 | in assert_total (afterMatch diff' ((cast {to=Int} (length pat)) - 1) pat target final' occurrencesarr suffixshiftarr overlap t)
206 | Just zero := tryNatToFin Z
209 | skip # t := get suffixshiftarr zero t
210 | kept := (cast {to=Int} (length pat)) - skip
211 | True := pati == kept
213 | assert_total (afterMatch diff (pati - 1) pat target final occurrencesarr suffixshiftarr overlap t)
214 | final' := final :< diff
215 | diff' := diff + skip
216 | maxdiff := minus (length target) (length pat)
217 | False := (cast {to=Int} maxdiff) < diff'
220 | in assert_total (afterMatch diff' ((cast {to=Int} (length pat)) - 1) pat target final' occurrencesarr suffixshiftarr overlap t)
246 | matchBM : (pat : ByteString)
247 | -> (target : ByteString)
248 | -> {0 prfpat : So (not $
null pat)}
249 | -> {0 prftarget : So (not $
null target)}
250 | -> {0 prflength : So ((length target) >= (length pat))}
251 | -> F1 s (Maybe (List Int))
252 | matchBM pat target {prfpat} {prftarget} {prflength} t =
253 | let matcher' # t := matcher False pat target t
254 | Just matcher'' := matcher'
257 | in Just matcher'' # t
281 | indicesBM : (pat : ByteString)
282 | -> (target : ByteString)
283 | -> {0 prfpat : So (not $
null pat)}
284 | -> {0 prftarget : So (not $
null target)}
285 | -> {0 prflength : So ((length target) >= (length pat))}
286 | -> F1 s (Maybe (List Int))
287 | indicesBM pat target {prfpat} {prftarget} {prflength} t =
288 | let matcher' # t := matcher True pat target t
289 | Just matcher'' := matcher'
292 | in Just matcher'' # t
306 | breakBM : (pat : ByteString)
307 | -> (target : ByteString)
308 | -> {0 prfpat : So (not $
null pat)}
309 | -> {0 prftarget : So (not $
null target)}
310 | -> {0 prflength : So ((length target) >= (length pat))}
311 | -> F1 s (Maybe (ByteString, ByteString))
312 | breakBM pat target {prfpat} {prftarget} {prflength} t =
313 | let matcher' # t := matcher False pat target t
314 | Just matcher'' := matcher'
317 | (i :: _) := matcher''
319 | Just (target, empty) # t
320 | target' := splitAt (cast {to=Nat} i) target
321 | Just target'' := target'
324 | in Just target'' # t
339 | breakAfterBM : (pat : ByteString)
340 | -> (target : ByteString)
341 | -> {0 prfpat : So (not $
null pat)}
342 | -> {0 prftarget : So (not $
null target)}
343 | -> {0 prflength : So ((length target) >= (length pat))}
344 | -> F1 s (Maybe (ByteString, ByteString))
345 | breakAfterBM pat target {prfpat} {prftarget} {prflength} t =
346 | let matcher' # t := matcher False pat target t
347 | Just matcher'' := matcher'
350 | (i :: _) := matcher''
352 | Just (target, empty) # t
353 | target' := splitAt (plus (cast {to=Nat} i) (length pat)) target
354 | Just target'' := target'
357 | in Just target'' # t
374 | splitKeepFrontBM : (pat : ByteString)
375 | -> (target : ByteString)
376 | -> {0 prfpat : So (not $
null pat)}
377 | -> {0 prftarget : So (not $
null target)}
378 | -> {0 prflength : So ((length target) >= (length pat))}
379 | -> F1 s (Maybe (List ByteString))
380 | splitKeepFrontBM pat target {prfpat} {prftarget} {prflength} t =
381 | let splitter' # t := splitter pat target Lin t
382 | Just splitter'' := splitter'
385 | in Just (splitter'' <>> []) # t
387 | psSplitter : (pat : ByteString)
388 | -> (target : ByteString)
389 | -> (final : SnocList ByteString)
390 | -> F1 s (Maybe (SnocList ByteString))
391 | psSplitter pat target final t =
392 | let matcher' # t := matcher False pat (drop (length pat) target) t
393 | Just matcher'' := matcher'
396 | (i :: _) := matcher''
398 | let final' := final :< target
400 | length' := plus (cast {to=Nat} i) (length pat)
401 | final' := final :< (take length' target)
402 | in assert_total (psSplitter pat (drop length' target) final' t)
403 | splitter : (pat : ByteString)
404 | -> (target : ByteString)
405 | -> (final : SnocList ByteString)
406 | -> F1 s (Maybe (SnocList ByteString))
407 | splitter pat target final t =
408 | let matcher' # t := matcher False pat target t
409 | Just matcher'' := matcher'
412 | (i :: _) := matcher''
414 | let final' := final :< target
418 | assert_total (psSplitter pat target final t)
419 | final' := final :< (take (cast {to=Nat} i) target)
420 | in assert_total (psSplitter pat (drop (cast {to=Nat} i) target) final' t)
443 | splitKeepEndBM : (pat : ByteString)
444 | -> (target : ByteString)
445 | -> {0 prfpat : So (not $
null pat)}
446 | -> {0 prftarget : So (not $
null target)}
447 | -> {0 prflength : So ((length target) >= (length pat))}
448 | -> F1 s (Maybe (List ByteString))
449 | splitKeepEndBM pat target {prfpat} {prftarget} {prflength} t =
450 | let splitter' # t := splitter pat target Lin t
451 | Just splitter'' := splitter'
454 | in Just (splitter'' <>> []) # t
456 | splitter : (pat : ByteString)
457 | -> (target : ByteString)
458 | -> (final : SnocList ByteString)
459 | -> F1 s (Maybe (SnocList ByteString))
460 | splitter pat target final t =
461 | let matcher' # t := matcher False pat target t
462 | Just matcher'' := matcher'
465 | (i :: _) := matcher''
467 | let final' := final :< target
469 | length' := plus (cast {to=Nat} i) (length pat)
470 | final' := final :< (take length' target)
471 | in assert_total (splitter pat (drop length' target) final' t)
496 | splitDropBM : (pat : ByteString)
497 | -> (target : ByteString)
498 | -> {0 prfpat : So (not $
null pat)}
499 | -> {0 prftarget : So (not $
null target)}
500 | -> {0 prflength : So ((length target) >= (length pat))}
501 | -> F1 s (Maybe (List ByteString))
502 | splitDropBM pat target {prfpat} {prftarget} {prflength} t =
503 | let splitter' # t := splitter pat target Lin t
504 | Just splitter'' := splitter'
507 | in Just (splitter'' <>> []) # t
509 | splitter : (pat : ByteString)
510 | -> (target : ByteString)
511 | -> (final : SnocList ByteString)
512 | -> F1 s (Maybe (SnocList ByteString))
513 | splitter pat target final t =
514 | let matcher' # t := matcher False pat target t
515 | Just matcher'' := matcher'
518 | (i :: _) := matcher''
520 | let final' := final :< target
522 | length' := plus (cast {to=Nat} i) (length pat)
523 | final' := final :< (take (cast {to=Nat} i) target)
524 | in assert_total (splitter pat (drop length' target) final' t)
547 | replaceBM : (pat : ByteString)
548 | -> (sub : ByteString)
549 | -> (target : ByteString)
550 | -> {0 prfpat : So (not $
null pat)}
551 | -> {0 prftarget : So (not $
null target)}
552 | -> {0 prflength : So ((length target) >= (length pat))}
553 | -> F1 s (Maybe (List ByteString))
554 | replaceBM pat sub target {prfpat} {prftarget} {prflength} t =
555 | let replacer' # t := replacer pat sub target Lin t
556 | Just replacer'' := replacer'
559 | in Just (replacer'' <>> []) # t
561 | replacer : (pat : ByteString)
562 | -> (sub : ByteString)
563 | -> (target : ByteString)
564 | -> (final : SnocList ByteString)
565 | -> F1 s (Maybe (SnocList ByteString))
566 | replacer pat sub target final t =
567 | let matcher' # t := matcher False pat target t
568 | Just matcher'' := matcher'
571 | (i :: _) := matcher''
573 | let final' := final :< target
575 | Z := cast {to=Nat} i
577 | let False := null sub
579 | let length' := plus (cast {to=Nat} i) (length pat)
580 | final' := final :< (take (cast {to=Nat} i) target)
581 | in assert_total (replacer pat sub (drop length' target) final' t)
582 | length' := plus (cast {to=Nat} i) (length pat)
583 | final' := final :< (take (cast {to=Nat} i) target) :< sub
584 | in assert_total (replacer pat sub (drop length' target) final' t)
587 | assert_total (replacer pat sub (drop (length pat) target) final t)
588 | final' := final :< sub
589 | in assert_total (replacer pat sub (drop (length pat) target) final') t