-- This code is in the public domain. module Text.Hexdump (hexdump) where import Control.Monad (guard) import Data.Char (ord) import Data.List (unfoldr) import Text.Printf (printf) -- | Unfold using f until the predicate becomes true. unfoldUntil :: (b -> Bool) -> (b -> (a, b)) -> b -> [a] unfoldUntil p f = unfoldr (\x -> guard (not (p x)) >> return (f x)) -- | Return hex characters for the byte value. bytehex :: Int -> String bytehex n = printf "%02x" n -- | Return a printable character, or a dot. prChar ch | ord ch >= 32 && ord ch < 128 = ch | otherwise = '.' -- | Return a string containing a pretty hexdump of xs using addresses -- starting at n. 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