module Text.Hexdump (hexdump) where
import Control.Monad (guard)
import Data.Char (ord)
import Data.List (unfoldr)
import Text.Printf (printf)
unfoldUntil :: (b -> Bool) -> (b -> (a, b)) -> b -> [a]
unfoldUntil p f = unfoldr (\x -> guard (not (p x)) >> return (f x))
bytehex :: Int -> String
bytehex n = printf "%02x" n
prChar ch | ord ch >= 32 && ord ch < 128 = ch
| otherwise = '.'
hexdump :: Int -> String -> String
hexdump n xs = unlines $ zipWith hexLine addrs dlines
where addrs = [n, n+16..]
dlines = unfoldUntil null (splitAt 16) xs
hexLine :: Int -> String -> String
hexLine addr xs = printf "%08x: %-24s %-24s| %s" addr h1 h2 s
where h1 = unwords $ map (bytehex . ord) $ take 8 xs
h2 = unwords $ map (bytehex . ord) $ drop 8 xs
s = map prChar xs