{-# LANGUAGE BangPatterns #-}
module Network.HPACK.Huffman.Tree (
HTree(..)
, eosInfo
, toHTree
, showTree
, printTree
, flatten
) where
import Control.Arrow (second)
import Data.List (partition)
import Network.HPACK.Huffman.Bit
import Network.HPACK.Huffman.Params
type EOSInfo = Maybe Int
data HTree = Tip
!EOSInfo
{-# UNPACK #-} !Int
| Bin
!EOSInfo
{-# UNPACK #-} !Int
!HTree
!HTree
deriving Show
eosInfo :: HTree -> EOSInfo
eosInfo (Tip mx _) = mx
eosInfo (Bin mx _ _ _) = mx
showTree :: HTree -> String
showTree = showTree' ""
showTree' :: String -> HTree -> String
showTree' _ (Tip _ i) = show i ++ "\n"
showTree' pref (Bin _ n l r) = "No " ++ show n ++ "\n"
++ pref ++ "+ " ++ showTree' pref' l
++ pref ++ "+ " ++ showTree' pref' r
where
pref' = " " ++ pref
printTree :: HTree -> IO ()
printTree = putStr . showTree
toHTree :: [Bits] -> HTree
toHTree bs = mark 1 eos $ snd $ build 0 $ zip [0..idxEos] bs
where
eos = bs !! idxEos
build :: Int -> [(Int,Bits)] -> (Int, HTree)
build !cnt0 [(v,[])] = (cnt0,Tip Nothing v)
build !cnt0 xs = let (cnt1,l) = build (cnt0 + 1) fs
(cnt2,r) = build cnt1 ts
in (cnt2, Bin Nothing cnt0 l r)
where
(fs',ts') = partition ((==) F . head . snd) xs
fs = map (second tail) fs'
ts = map (second tail) ts'
mark :: Int -> Bits -> HTree -> HTree
mark i [] (Tip Nothing v) = Tip (Just i) v
mark i (F:bs) (Bin Nothing n l r) = Bin (Just i) n (mark (i+1) bs l) r
mark i (T:bs) (Bin Nothing n l r) = Bin (Just i) n l (mark (i+1) bs r)
mark _ _ _ = error "mark"
flatten :: HTree -> [HTree]
flatten (Tip _ _) = []
flatten t@(Bin _ _ l r) = t : (flatten l ++ flatten r)