packages feed

data-svd-0.1.1.0: src/Data/Bits/Pretty.hs

module Data.Bits.Pretty
  (
  -- * Show in base
    showBin
  , showDec
  , showHex
  , formatHex
  -- * Show binary groups
  , showBinGroups
  -- * Size of Int
  , platformSizeOfInt
  -- * Shorthand
  , showHex8
  , showHex16
  , showHex32
  ) where

import Data.Bits (FiniteBits, (.&.), shiftR)
import Data.Word (Word8, Word16, Word32)
import Text.Printf (PrintfArg, printf)
import qualified Data.Bits

-- * Show in base

-- | Format number using binary notation with leading 0b,
-- padded according to its bit size
showBin :: (PrintfArg t, FiniteBits t) => t -> String
showBin x =
  printf
    ("0b%0"
    ++ (show $ Data.Bits.finiteBitSize x)
    ++ "b"
    )
    x

-- | Format number using decimal notation
showDec :: (PrintfArg t, FiniteBits t) => t -> String
showDec x =
  printf ("%0" ++ (show decSize) ++ "u") x
  where
    decSize :: Int
    decSize =
      ceiling
      $ logBase
          (10 :: Double)
          (2 ^ (Data.Bits.finiteBitSize x))

-- | Format number using hexadecimal notation with leading 0x,
-- padded according to its bit size
showHex :: (PrintfArg t, FiniteBits t) => t -> String
showHex x =
  printf
    ("0x%0"
    ++ (show $ Data.Bits.finiteBitSize x `div` 4)
    ++ "X"
    )
    x

-- | Format number using hexadecimal notation with leading 0x
formatHex :: PrintfArg t => t -> String
formatHex = printf "0x%x"

-- * Show binary groups

-- | Print number in binary with bits grouped by `groupSize`
-- e.g. with `groupSize = 4` we would get `0000 1010 0000 0101`
showBinGroups :: (PrintfArg b, Num b, FiniteBits b) => Int -> b -> String
showBinGroups groupSize x =
  unwords
    $ flip map [gs -1 ,gs - 2 .. 0]
    $ \g -> ((printf ("%0" ++ (show groupSize) ++ "b") (mask g x)) :: String)
  where
    mask g n = (2^groupSize - 1) .&. (n `shiftR` (fromIntegral (g * groupSize)))
    gs = sz `div` groupSize
    sz = fromIntegral $ Data.Bits.finiteBitSize x

-- * Size of Int

-- | Size of `Int` at the current platform
platformSizeOfInt :: Int
platformSizeOfInt = Data.Bits.finiteBitSize (0 :: Int)

-- * Shorthand

-- | Format Int as 32-bit unsigned hexadecimal string
showHex32 :: Int -> String
showHex32 = showHex . (fromIntegral :: Int -> Word32)

-- | Format Int as 16-bit unsigned hexadecimal string
showHex16 :: Int -> String
showHex16 = showHex . (fromIntegral :: Int -> Word16)

-- | Format Int as 8-bit unsigned hexadecimal string
showHex8 :: Int -> String
showHex8  = showHex . (fromIntegral :: Int -> Word8)