module Codec.Container.Ogg.Dump (
hexDump
) where
import Data.Char (isSpace, chr, ord)
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as C
import Numeric
hexDump :: L.ByteString -> C.ByteString
hexDump = hexDump' 0
hexDump' :: Int -> L.ByteString -> C.ByteString
hexDump' o d
| L.null d = C.empty
| otherwise = lineDump `C.append` hexDump' (o+16) rest
where (line, rest) = L.splitAt 16 d
lineDump = C.pack $ spaces 4 ++ offset ++ ": " ++ hexLine ++ spaces hexPad ++ ascLine ++ "\n"
spaces n = take n $ repeat ' '
offset = hexOffset o
(hexLine, ascLine) = makeDump line False
hexPad = 1 + 8*5 length hexLine
hexOffset x
| x < 0x10 = showHex x "000"
| x < 0x100 = showHex x "00"
| x < 0x1000 = showHex x "0"
| otherwise = showHex x ""
makeDump :: L.ByteString -> Bool -> (String, String)
makeDump d hexSpace
| L.null d = ([], [])
| otherwise = (newHex ++ nextHex, newChr ++ nextChr)
where (nextHex, nextChr) = makeDump ls (not hexSpace)
(l, ls) = (L.head d, L.tail d)
newHex = if hexSpace then h ++ " " else h
h = hexByte l
newChr = ascByte $ chr $ fromIntegral l
hexByte x
| x < 16 = showHex x "0"
| otherwise = showHex x ""
ascByte c
| (ord c) > 126 = "."
| isSpace c = " "
| (ord c) < 32 = "."
| otherwise = [c]