module Encode (CodeEvent(..), encode, maxBits)
where
--import GlaExts
data PrefixTrie a b = PTNil |
PT a b (PrefixTrie a b) (PrefixTrie a b) (PrefixTrie a b)
type CodeTable = PrefixTrie Char Int
data CodeEvent =
Code Int |
NewWordSize |
Clear deriving Show{-was:Text-}
data CodeState = CS
Int {- # STRICT # -}
Int {- # STRICT # -}
Int {- # STRICT # -}
Int {- # STRICT # -}
Int {- # STRICT # -}
Int {- # STRICT # -}
firstEnt = 257 :: Int
maxBits = 16 :: Int
checkGap = 10000 :: Int
firstCheck = 10000 :: Int
firstChange = (2^9) + 1 :: Int
maxmaxCode = 2^maxBits + 1 :: Int
encode :: [Int] -> String -> [CodeEvent]
encode = encode' (CS 3 1 firstCheck 0 firstEnt firstChange) initial_table
encode' :: CodeState -> CodeTable -> [Int] -> String -> [CodeEvent]
encode' _ _ _ [] = []
encode' c@(CS bo ci cp ra nx cg) t sizes input
= if nx == cg then
NewWordSize : encode' (CS (bo+s) ci cp ra nx cg') t ss input
else
if nx == maxmaxCode then
if ci >= cp then
let ra' = (ci * 256) `div` bo in
if ra' > ra then
encode' (CS bo ci (ci+checkGap) ra' nx cg) t sizes input
else
Clear :
encode' (CS (bo+s) ci (ci+checkGap) 0 firstEnt firstChange)
initial_table ss input
else
let (input', n, i) = code_string_r (input, 0, 0) nx t
in Code n :
encode' (CS (bo+s) (ci+i) cp ra nx cg) t ss input'
else
(\ ((input', n, i), t') ->
Code n :
encode' (CS (bo+s) (ci+i) cp ra (nx+1) cg) t' ss input')
(code_string_rw (input, 0, 0) nx t)
where
(s:ss) = sizes
cg' = let val = ((cg - 1) * 2) + 1 in
if val == maxmaxCode then 0 else val
csForced (CS a b c d e f) = (a==a) && (b==b) && (c==c) && (d==d)
&& (e==e) && (f==f)
code_string_r :: (String, Int, Int) -> Int -> CodeTable -> (String, Int, Int)
code_string_r s@([], _, _) _ _
= s
code_string_r s _ PTNil
= s
code_string_r s@(c:cs, old_code, n) next_code (PT k v k_pt l r)
= if c == k then
code_string_r (cs, v, (n+1)) next_code k_pt
else
code_string_r s next_code (if c < k then l else r)
code_string_rw :: (String, Int, Int) -> Int -> CodeTable
-> ((String, Int, Int), CodeTable)
code_string_rw s@([], _, _) _ _
= (s, PTNil)
code_string_rw s@(c:_,_,_) next_code PTNil
= (s, PT c next_code PTNil PTNil PTNil)
code_string_rw s@(c:cs, old_code, n) next_code (PT k k_code k_pt l r)
| c < k = (\ (s', l') -> (s', PT k k_code k_pt l' r))
(code_string_rw s next_code l)
| c > k = (\ (s', r') -> (s', PT k k_code k_pt l r'))
(code_string_rw s next_code r)
| otherwise = (\ (s', t') -> (s', PT k k_code t' l r))
(code_string_rw (cs, k_code, n+1) next_code k_pt)
initial_table :: CodeTable
initial_table = build_table 0 255
build_table :: Int -> Int -> CodeTable
build_table lo hi
= if lo > hi then
PTNil
else let mid = (lo + hi) `div` 2 in
--trace (show (lo,hi,mid))
PT (toEnum mid) mid PTNil
(build_table lo (mid - 1))
(build_table (mid + 1) hi)
|