diff options
Diffstat (limited to 'lib/Text/XXD.hs')
-rw-r--r-- | lib/Text/XXD.hs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/Text/XXD.hs b/lib/Text/XXD.hs new file mode 100644 index 0000000..77606bf --- /dev/null +++ b/lib/Text/XXD.hs | |||
@@ -0,0 +1,48 @@ | |||
1 | {-# LANGUAGE RankNTypes #-} | ||
2 | {-# LANGUAGE ScopedTypeVariables #-} | ||
3 | module Text.XXD (xxd, xxd2) where | ||
4 | |||
5 | import Data.ByteArray (ByteArrayAccess) | ||
6 | import qualified Data.ByteArray as BA | ||
7 | import Data.Word | ||
8 | import Data.Bits | ||
9 | import Data.Char | ||
10 | import Text.Printf | ||
11 | |||
12 | nibble :: Word8 -> Char | ||
13 | nibble b = intToDigit (fromIntegral (b .&. 0x0F)) | ||
14 | |||
15 | nibbles :: ByteArrayAccess ba => ba -> String | ||
16 | nibbles xs = unwords $ map (\byte -> [nibble (byte `shiftR` 4), nibble byte]) | ||
17 | $ BA.unpack xs | ||
18 | |||
19 | xxd0 :: (ByteArrayAccess ba) => (forall b. ByteArrayAccess b => b -> String) -> Int -> ba -> [String] | ||
20 | xxd0 tr offset bs | BA.null bs = [] | ||
21 | xxd0 tr offset bs = printf "%03x: %s%s" offset (nibbles xs) (tr xs) | ||
22 | : xxd0 tr (offset + BA.length xs) bs' | ||
23 | where | ||
24 | (xs,bs') = splitAtView 16 bs | ||
25 | |||
26 | splitAtView :: (ByteArrayAccess ba) => Int -> ba -> (BA.View ba, BA.View ba) | ||
27 | splitAtView n bs = (BA.takeView bs n, BA.dropView bs n) | ||
28 | |||
29 | xxd :: ByteArrayAccess a => Int -> a -> [String] | ||
30 | xxd = xxd0 (const "") | ||
31 | |||
32 | -- | like xxd, but also shows ascii | ||
33 | xxd2 :: ByteArrayAccess a => Int -> a -> [String] | ||
34 | xxd2 = xxd0 withAscii | ||
35 | |||
36 | withAscii :: ByteArrayAccess a => a -> [Char] | ||
37 | withAscii row = replicate (50 - 3 * BA.length row) ' ' ++ myunpack row | ||
38 | where | ||
39 | myunpack s = map word8tochar (BA.unpack s) | ||
40 | where word8tochar w | (w .&. 0x80 /= 0) = '.' | ||
41 | word8tochar w = let c = chr (fromIntegral w) | ||
42 | in if isPrint c then c else '.' | ||
43 | |||
44 | {- | ||
45 | main = do | ||
46 | bs <- B.getContents | ||
47 | mapM_ putStrLn $ xxd2 0 bs | ||
48 | -} | ||