1 | module Data.ByteString.Search.Internal.Utils
3 | import Data.Array.Core
4 | import Data.Array.Mutable
6 | import Data.ByteString
7 | import Data.Linear.Ref1
10 | %hide Data.Buffer.Core.get
11 | %hide Data.Buffer.Core.set
40 | kmpBorders : (bs : ByteString)
41 | -> F1 s (Maybe (MArray s (S (length bs)) Nat))
43 | let arr # t := unsafeMArray1 (S (length bs)) t
44 | Just zero := tryNatToFin Z
45 | | Nothing => Nothing # t
46 | () # t := set arr zero Z t
47 | in go (S Z) Z bs arr t
53 | -> (bs : ByteString)
54 | -> (arr : MArray s (S (length bs)) Nat)
55 | -> F1 s (Maybe (MArray s (S (length bs)) Nat))
56 | advance i j wi bs arr t =
57 | let Just wj := index j bs
58 | | Nothing => Nothing # t
59 | wj' := cast {to=Nat} wj
63 | Just fi' := tryNatToFin (S i)
64 | | Nothing => Nothing # t
65 | () # t := set arr fi' j' t
66 | in assert_total (go (S i) j' bs arr t)
69 | let Just fi' := tryNatToFin (S i)
70 | | Nothing => Nothing # t
71 | () # t := set arr fi' Z t
72 | in assert_total (go (S i) Z bs arr t)
73 | Just fj := tryNatToFin j
74 | | Nothing => Nothing # t
75 | j' # t := get arr fj t
76 | in assert_total (advance i j' wi bs arr t)
79 | -> (bs : ByteString)
80 | -> (arr : MArray s (S (length bs)) Nat)
81 | -> F1 s (Maybe (MArray s (S (length bs)) Nat))
83 | let False := i == length bs
86 | Just wi := index i bs
87 | | Nothing => Nothing # t
88 | wi' := cast {to=Nat} wi
89 | in advance i j wi' bs arr t
137 | automaton : (bs : ByteString)
138 | -> F1 s (Maybe (MArray s (mult (plus (length bs) 1) 256) Nat))
140 | let arr # t := unsafeMArray1 (mult (plus (length bs) 1) 256) t
141 | bord # t := kmpBorders bs t
143 | | Nothing => Nothing # t
144 | in go Z arr bord' t
146 | fillState : (state : Nat)
148 | -> (patbyte : Maybe Nat)
150 | -> (statebase : Nat)
151 | -> (arr : MArray s (mult (plus (length bs) 1) 256) Nat)
152 | -> F1 s (Maybe (MArray s (mult (plus (length bs) 1) 256) Nat))
153 | fillState state byte patbyte bordcur statebase arr t =
154 | let idx := plus statebase byte
155 | Just idx' := the (Maybe (Fin (mult (plus (length bs) 1) 256))) (tryNatToFin idx)
158 | Just patbyte' := patbyte
160 | let False := state == Z
162 | let () # t := set arr idx' Z t
166 | in assert_total (fillState state (minus byte 1) patbyte bordcur statebase arr t)
167 | fidx := plus (mult bordcur 256) byte
168 | Just fidx' := tryNatToFin fidx
169 | | Nothing => Nothing # t
170 | bordcur' # t := get arr fidx' t
171 | () # t := set arr idx' bordcur' t
175 | in assert_total (fillState state (minus byte 1) patbyte bordcur' statebase arr t)
176 | False := byte == patbyte'
178 | let () # t := set arr idx' (S state) t
182 | in assert_total (fillState state (minus byte 1) patbyte bordcur statebase arr t)
183 | False := state == Z
185 | let () # t := set arr idx' Z t
189 | in assert_total (fillState state (minus byte 1) patbyte bordcur statebase arr t)
190 | fidx := plus (mult bordcur 256) byte
191 | Just fidx' := tryNatToFin fidx
194 | bordcur' # t := get arr fidx' t
195 | () # t := set arr idx' bordcur' t
199 | in assert_total (fillState state (minus byte 1) patbyte bordcur' statebase arr t)
201 | -> (arr : MArray s (mult (plus (length bs) 1) 256) Nat)
202 | -> (bord : MArray s (S (length bs)) Nat)
203 | -> F1 s (Maybe (MArray s (mult (plus (length bs) 1) 256) Nat))
204 | go state arr bord t =
205 | let False := state > length bs
208 | Just state' := tryNatToFin state
209 | | Nothing => Nothing # t
210 | bordcur # t := get bord state' t
212 | case index state bs of
216 | Just (cast {to=Nat} b)
217 | statebase := mult state 256
218 | arr' # t := fillState state 255 patbyte bordcur statebase arr t
220 | | Nothing => Nothing # t
221 | in assert_total (go (S state) arr'' bord t)
260 | occurrences : (bs : ByteString)
261 | -> {0 prf : So (not $
null bs)}
262 | -> F1 s (Maybe (MArray s 256 Int))
264 | let arr # t := marray1 256 (the Int 1) t
265 | arr' # t := go Z (length bs) bs arr t
273 | -> (bs : ByteString)
274 | -> (arr : MArray s 256 Int)
275 | -> F1 s (Maybe (MArray s 256 Int))
276 | go i patend bs arr t =
277 | let False := (S i) >= patend
284 | Just i''' := tryNatToFin (cast {to=Nat} i'')
287 | () # t := set arr i''' (negate $
cast {to=Int} i) t
288 | in assert_total (go (S i) patend bs arr t)
331 | suffixLengths : (bs : ByteString)
332 | -> {0 prf : So (not $
null bs)}
333 | -> F1 s (Maybe (MArray s (length bs) Int))
334 | suffixLengths bs t =
335 | let arr # t := marray1 (length bs) (the Int 0) t
336 | Just idx := tryNatToFin (minus (length bs) 1)
339 | () # t := set arr idx (cast {to=Int} (length bs)) t
340 | arr' # t := noSuffix (cast {to=Int} (minus (length bs) 2)) bs arr t
348 | -> F1 s (Maybe Int)
353 | j' := index (cast {to=Nat} j) bs
357 | j''' := index (cast {to=Nat} (j + diff)) bs
361 | False := j'' /= j''''
364 | in assert_total (dec diff (j - 1) t)
366 | suffixLoop : (pre : Int)
369 | -> (bs : ByteString)
370 | -> (arr : MArray s (length bs) Int)
371 | -> F1 s (Maybe (MArray s (length bs) Int))
372 | suffixLoop _ _ 0 _ arr t =
374 | suffixLoop pre end idx bs arr t =
375 | let True := pre < idx
377 | noSuffix idx bs arr t
378 | idx' := index (cast {to=Nat} idx) bs
382 | idx''' := index (minus (length bs) 1) bs
383 | Just idx'''' := idx'''
386 | False := idx'' /= idx''''
388 | let Just idxs := tryNatToFin (cast {to=Nat} idx)
391 | () # t := set arr idxs 0 t
392 | in assert_total (suffixLoop pre (end - 1) (idx - 1) bs arr t)
393 | Just end' := tryNatToFin (cast {to=Nat} end)
396 | prevs # t := get arr end' t
397 | Just idxs := tryNatToFin (cast {to=Nat} idx)
400 | False := (pre + prevs) < idx
402 | let () # t := set arr idxs prevs t
403 | in assert_total (suffixLoop pre (end - 1) (idx - 1) bs arr t)
404 | pri # t := dec (cast {to=Int} (minus (length bs) (cast {to=Nat} idx))) pre t
408 | () # t := set arr idxs (idx - pri') t
409 | in assert_total (suffixLoop pri' (cast {to=Int} (minus (length bs) 2)) (idx - 1) bs arr t)
410 | noSuffix : (i : Int)
411 | -> (bs : ByteString)
412 | -> (arr : MArray s (length bs) Int)
413 | -> F1 s (Maybe (MArray s (length bs) Int))
414 | noSuffix 0 _ arr t =
416 | noSuffix i bs arr t =
417 | let patati := index (cast {to=Nat} i) bs
418 | Just patati' := patati
421 | patatend := index (minus (length bs) 1) bs
422 | Just patatend' := patatend
425 | True := patati' == patatend'
427 | let Just i' := tryNatToFin (cast {to=Nat} i)
430 | () # t := set arr i' 0 t
431 | in assert_total (noSuffix (i - 1) bs arr t)
432 | diff := (cast {to=Int} (minus (length bs) 1)) - i
434 | previ # t := dec diff nexti t
435 | Just previ' := previ
438 | Just i' := tryNatToFin (cast {to=Nat} i)
441 | False := previ' == nexti
443 | let () # t := set arr i' 1 t
444 | in assert_total (noSuffix nexti bs arr t)
445 | () # t := set arr i' (i - previ') t
446 | in assert_total (suffixLoop previ' (cast {to=Int} (minus (length bs) 2)) nexti bs arr t)
497 | suffixShifts : (bs : ByteString)
498 | -> {0 prf : So (not $
null bs)}
499 | -> F1 s (Maybe (MArray s (length bs) Int))
500 | suffixShifts bs {prf} t =
501 | let arr # t := marray1 (length bs) (cast {to=Int} (length bs)) t
502 | suff # t := suffixLengths bs {prf=prf} t
506 | arr' # t := prefixShift (cast {to=Int} (minus (length bs) 2)) 0 bs suff' arr t
510 | arr''' # t := suffixShift 0 bs suff' arr'' t
511 | Just arr'''' := arr'''
514 | in Just arr'''' # t
516 | fillToShift : (i : Int)
518 | -> (bs : ByteString)
519 | -> (arr : MArray s (length bs) Int)
520 | -> F1 s (Maybe (MArray s (length bs) Int))
521 | fillToShift i shift bs arr t =
522 | let False := i == shift
525 | Just i' := tryNatToFin (cast {to=Nat} i)
528 | () # t := set arr i' shift t
529 | in assert_total (fillToShift (i + 1) shift bs arr t)
530 | prefixShift : (idx : Int)
532 | -> (bs : ByteString)
533 | -> (suff : MArray s (length bs) Int)
534 | -> (arr : MArray s (length bs) Int)
535 | -> F1 s (Maybe (MArray s (length bs) Int))
536 | prefixShift idx j bs suff arr t =
537 | let False := idx < 0
540 | Just idx' := tryNatToFin (cast {to=Nat} idx)
543 | idx'' # t := get suff idx' t
544 | True := idx'' == (idx + 1)
546 | assert_total (prefixShift (idx - 1) j bs suff arr t)
547 | shift := (cast {to=Int} (minus (length bs) 1)) - idx
548 | arr' # t := fillToShift j shift bs arr t
552 | in assert_total (prefixShift (idx - 1) shift bs suff arr'' t)
553 | suffixShift : (idx : Int)
554 | -> (bs : ByteString)
555 | -> (suff : MArray s (length bs) Int)
556 | -> (arr : MArray s (length bs) Int)
557 | -> F1 s (Maybe (MArray s (length bs) Int))
558 | suffixShift idx bs suff arr t =
559 | let patend := cast {to=Int} (minus (length bs) 1)
560 | False := idx >= patend
563 | Just idx' := tryNatToFin (cast {to=Nat} idx)
566 | idx'' # t := get suff idx' t
567 | target := patend - idx''
568 | Just target' := tryNatToFin (cast {to=Nat} target)
571 | value := patend - idx
572 | () # t := set arr target' value t
573 | in assert_total (suffixShift (idx + 1) bs suff arr t)