1 | module Data.ByteString.Search.BoyerMoore
3 | import Data.Array.Core
4 | import Data.Array.Mutable
6 | import Data.ByteString
7 | import Data.ByteString.Search.BoyerMoore.Internal
9 | import Data.Linear.Ref1
12 | %hide Data.Buffer.Core.get
13 | %hide Data.Buffer.Core.set
35 | -> F1 s (Maybe (List Int))
36 | matcher overlap pat target t =
37 | let patlen := length pat
38 | targetlen := length target
39 | patlenint := cast {to=Int} patlen
40 | patend := patlenint - 1
41 | strend := (cast {to=Int} targetlen) - 1
42 | maxdiff := cast {to=Int} (minus targetlen patlen)
43 | False := patlen == S Z
45 | let Just patzero := index Z pat
48 | Just headelem := elemIndex patzero target
51 | in Just ((cast {to=Int} headelem) :: []) # t
52 | Yes patprf := decSo (not $
null pat)
55 | occurrencesarr # t := occurrences pat {prf = patprf} t
56 | Just occurrencesarr' := occurrencesarr
59 | suffixshiftsarr # t := suffixShifts pat {prf = patprf} t
60 | Just (MkBMPatternTable stspace suffixshiftsarr') := suffixshiftsarr
63 | zero : PatternIndex stspace.size
64 | zero := I 0 {prf = stspace.sizePositive}
65 | suffixzero # t := bmGet suffixshiftsarr' zero t
66 | Just patlast := index (minus patlen 1) pat
69 | matches # t := checkEnd stspace patend Lin patend strend maxdiff patlenint patlast suffixzero occurrencesarr' suffixshiftsarr' t
70 | Just matches' := matches
73 | in Just (matches' <>> []) # t
87 | patternIndex : (stspace : BMPatternSpace)
89 | -> PatternIndex stspace.size
90 | patternIndex stspace idx =
91 | I (cast idx) {prf = believe_me ()}
99 | checkEnd : (stspace : BMPatternSpace)
101 | -> (final : SnocList Int)
106 | -> (patlast : Bits8)
107 | -> (suffixzero : Int)
108 | -> (occurrencesarr : OccurrenceTable s)
109 | -> (suffixshiftsarr : BMIntTable s stspace.size)
110 | -> F1 s (Maybe (SnocList Int))
111 | checkEnd stspace stri final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t =
112 | let False := strend < stri
115 | strinat := cast {to=Nat} stri
116 | Just targetbyte := index strinat target
119 | False := targetbyte == patlast
121 | assert_total (findMatch stspace (stri - patend) (patend - 1) final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
122 | occur # t := occurrence occurrencesarr targetbyte t
123 | newtarget := stri + patend + occur
124 | in assert_total (checkEnd stspace newtarget final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
135 | findMatch : (stspace : BMPatternSpace)
138 | -> (final : SnocList Int)
143 | -> (patlast : Bits8)
144 | -> (suffixzero : Int)
145 | -> (occurrencesarr : OccurrenceTable s)
146 | -> (suffixshiftsarr : BMIntTable s stspace.size)
147 | -> F1 s (Maybe (SnocList Int))
148 | findMatch stspace diff pati final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t =
149 | let targetidx := diff + pati
150 | targetnat := cast {to=Nat} targetidx
151 | patnat := cast {to=Nat} pati
152 | Just targetbyte := index targetnat target
155 | Just patbyte := index patnat pat
158 | False := targetbyte == patbyte
160 | let False := pati == 0
162 | let final' := final :< diff
165 | let diff' := diff + suffixzero
166 | False := maxdiff < diff'
169 | False := suffixzero == patlen
171 | assert_total (checkEnd stspace (diff' + patend) final' patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
172 | in assert_total (afterMatch stspace diff' patend final' patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
173 | diff' := diff + patlen
174 | False := maxdiff < diff'
177 | in assert_total (checkEnd stspace (diff' + patend) final' patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
178 | in assert_total (findMatch stspace diff (pati - 1) final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
179 | occur # t := occurrence occurrencesarr targetbyte t
180 | patidx := patternIndex stspace pati
181 | suff # t := bmGet suffixshiftsarr patidx t
182 | shift := max (pati + occur) suff
183 | diff' := diff + shift
184 | False := maxdiff < diff'
187 | in assert_total (checkEnd stspace (diff' + patend) final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
196 | afterMatch : (stspace : BMPatternSpace)
199 | -> (final : SnocList Int)
204 | -> (patlast : Bits8)
205 | -> (suffixzero : Int)
206 | -> (occurrencesarr : OccurrenceTable s)
207 | -> (suffixshiftsarr : BMIntTable s stspace.size)
208 | -> F1 s (Maybe (SnocList Int))
209 | afterMatch stspace diff pati final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t =
210 | let targetidx := diff + pati
211 | targetnat := cast {to=Nat} targetidx
212 | patnat := cast {to=Nat} pati
213 | Just targetbyte := index targetnat target
216 | Just patbyte := index patnat pat
219 | False := targetbyte == patbyte
221 | let kept := patlen - suffixzero
222 | False := pati == kept
224 | let final' := final :< diff
225 | diff' := diff + suffixzero
226 | False := maxdiff < diff'
229 | in assert_total (afterMatch stspace diff' patend final' patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
230 | in assert_total (afterMatch stspace diff (pati - 1) final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
231 | False := pati == patend
233 | let occur # t := occurrence occurrencesarr targetbyte t
234 | nextend := diff + (2 * patend) + occur
235 | in assert_total (checkEnd stspace nextend final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
236 | occur # t := occurrence occurrencesarr targetbyte t
237 | patidx := patternIndex stspace pati
238 | goodshift # t := bmGet suffixshiftsarr patidx t
239 | badshift := pati + occur
240 | diff' := diff + max badshift goodshift
241 | False := maxdiff < diff'
244 | in assert_total (checkEnd stspace (diff + patend) final patend strend maxdiff patlen patlast suffixzero occurrencesarr suffixshiftsarr t)
270 | matchBM : (pat : ByteString)
271 | -> (target : ByteString)
272 | -> {0 prfpat : So (not $
null pat)}
273 | -> {0 prftarget : So (not $
null target)}
274 | -> {0 prflength : So ((length target) >= (length pat))}
275 | -> F1 s (Maybe (List Int))
276 | matchBM pat target {prfpat} {prftarget} {prflength} t =
277 | let matcher' # t := matcher False pat target t
278 | Just matcher'' := matcher'
281 | in Just matcher'' # t
305 | indicesBM : (pat : ByteString)
306 | -> (target : ByteString)
307 | -> {0 prfpat : So (not $
null pat)}
308 | -> {0 prftarget : So (not $
null target)}
309 | -> {0 prflength : So ((length target) >= (length pat))}
310 | -> F1 s (Maybe (List Int))
311 | indicesBM pat target {prfpat} {prftarget} {prflength} t =
312 | let matcher' # t := matcher True pat target t
313 | Just matcher'' := matcher'
316 | in Just matcher'' # t
330 | breakBM : (pat : ByteString)
331 | -> (target : ByteString)
332 | -> {0 prfpat : So (not $
null pat)}
333 | -> {0 prftarget : So (not $
null target)}
334 | -> {0 prflength : So ((length target) >= (length pat))}
335 | -> F1 s (Maybe (ByteString, ByteString))
336 | breakBM pat target {prfpat} {prftarget} {prflength} t =
337 | let matcher' # t := matcher False pat target t
338 | Just matcher'' := matcher'
341 | (i :: _) := matcher''
343 | Just (target, empty) # t
344 | target' := splitAt (cast {to=Nat} i) target
345 | Just target'' := target'
348 | in Just target'' # t
363 | breakAfterBM : (pat : ByteString)
364 | -> (target : ByteString)
365 | -> {0 prfpat : So (not $
null pat)}
366 | -> {0 prftarget : So (not $
null target)}
367 | -> {0 prflength : So ((length target) >= (length pat))}
368 | -> F1 s (Maybe (ByteString, ByteString))
369 | breakAfterBM pat target {prfpat} {prftarget} {prflength} t =
370 | let matcher' # t := matcher False pat target t
371 | Just matcher'' := matcher'
374 | (i :: _) := matcher''
376 | Just (target, empty) # t
377 | target' := splitAt (plus (cast {to=Nat} i) (length pat)) target
378 | Just target'' := target'
381 | in Just target'' # t
398 | splitKeepFrontBM : (pat : ByteString)
399 | -> (target : ByteString)
400 | -> {0 prfpat : So (not $
null pat)}
401 | -> {0 prftarget : So (not $
null target)}
402 | -> {0 prflength : So ((length target) >= (length pat))}
403 | -> F1 s (Maybe (List ByteString))
404 | splitKeepFrontBM pat target {prfpat} {prftarget} {prflength} t =
405 | let splitter' # t := splitter pat target Lin t
406 | Just splitter'' := splitter'
409 | in Just (splitter'' <>> []) # t
411 | psSplitter : (pat : ByteString)
412 | -> (target : ByteString)
413 | -> (final : SnocList ByteString)
414 | -> F1 s (Maybe (SnocList ByteString))
415 | psSplitter pat target final t =
416 | let matcher' # t := matcher False pat (drop (length pat) target) t
417 | Just matcher'' := matcher'
420 | (i :: _) := matcher''
422 | let final' := final :< target
424 | length' := plus (cast {to=Nat} i) (length pat)
425 | final' := final :< (take length' target)
426 | in assert_total (psSplitter pat (drop length' target) final' t)
427 | splitter : (pat : ByteString)
428 | -> (target : ByteString)
429 | -> (final : SnocList ByteString)
430 | -> F1 s (Maybe (SnocList ByteString))
431 | splitter pat target final t =
432 | let matcher' # t := matcher False pat target t
433 | Just matcher'' := matcher'
436 | (i :: _) := matcher''
438 | let final' := final :< target
442 | assert_total (psSplitter pat target final t)
443 | final' := final :< (take (cast {to=Nat} i) target)
444 | in assert_total (psSplitter pat (drop (cast {to=Nat} i) target) final' t)
467 | splitKeepEndBM : (pat : ByteString)
468 | -> (target : ByteString)
469 | -> {0 prfpat : So (not $
null pat)}
470 | -> {0 prftarget : So (not $
null target)}
471 | -> {0 prflength : So ((length target) >= (length pat))}
472 | -> F1 s (Maybe (List ByteString))
473 | splitKeepEndBM pat target {prfpat} {prftarget} {prflength} t =
474 | let splitter' # t := splitter pat target Lin t
475 | Just splitter'' := splitter'
478 | in Just (splitter'' <>> []) # t
480 | splitter : (pat : ByteString)
481 | -> (target : ByteString)
482 | -> (final : SnocList ByteString)
483 | -> F1 s (Maybe (SnocList ByteString))
484 | splitter pat target final t =
485 | let matcher' # t := matcher False pat target t
486 | Just matcher'' := matcher'
489 | (i :: _) := matcher''
491 | let final' := final :< target
493 | length' := plus (cast {to=Nat} i) (length pat)
494 | final' := final :< (take length' target)
495 | in assert_total (splitter pat (drop length' target) final' t)
520 | splitDropBM : (pat : ByteString)
521 | -> (target : ByteString)
522 | -> {0 prfpat : So (not $
null pat)}
523 | -> {0 prftarget : So (not $
null target)}
524 | -> {0 prflength : So ((length target) >= (length pat))}
525 | -> F1 s (Maybe (List ByteString))
526 | splitDropBM pat target {prfpat} {prftarget} {prflength} t =
527 | let splitter' # t := splitter pat target Lin t
528 | Just splitter'' := splitter'
531 | in Just (splitter'' <>> []) # t
533 | splitter : (pat : ByteString)
534 | -> (target : ByteString)
535 | -> (final : SnocList ByteString)
536 | -> F1 s (Maybe (SnocList ByteString))
537 | splitter pat target final t =
538 | let matcher' # t := matcher False pat target t
539 | Just matcher'' := matcher'
542 | (i :: _) := matcher''
544 | let final' := final :< target
546 | length' := plus (cast {to=Nat} i) (length pat)
547 | final' := final :< (take (cast {to=Nat} i) target)
548 | in assert_total (splitter pat (drop length' target) final' t)
571 | replaceBM : (pat : ByteString)
572 | -> (sub : ByteString)
573 | -> (target : ByteString)
574 | -> {0 prfpat : So (not $
null pat)}
575 | -> {0 prftarget : So (not $
null target)}
576 | -> {0 prflength : So ((length target) >= (length pat))}
577 | -> F1 s (Maybe (List ByteString))
578 | replaceBM pat sub target {prfpat} {prftarget} {prflength} t =
579 | let replacer' # t := replacer pat sub target Lin t
580 | Just replacer'' := replacer'
583 | in Just (replacer'' <>> []) # t
585 | replacer : (pat : ByteString)
586 | -> (sub : ByteString)
587 | -> (target : ByteString)
588 | -> (final : SnocList ByteString)
589 | -> F1 s (Maybe (SnocList ByteString))
590 | replacer pat sub target final t =
591 | let matcher' # t := matcher False pat target t
592 | Just matcher'' := matcher'
595 | (i :: _) := matcher''
597 | let final' := final :< target
599 | Z := cast {to=Nat} i
601 | let False := null sub
603 | let length' := plus (cast {to=Nat} i) (length pat)
604 | final' := final :< (take (cast {to=Nat} i) target)
605 | in assert_total (replacer pat sub (drop length' target) final' t)
606 | length' := plus (cast {to=Nat} i) (length pat)
607 | final' := final :< (take (cast {to=Nat} i) target) :< sub
608 | in assert_total (replacer pat sub (drop length' target) final' t)
611 | assert_total (replacer pat sub (drop (length pat) target) final t)
612 | final' := final :< sub
613 | in assert_total (replacer pat sub (drop (length pat) target) final') t