{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Trustworthy #-}
#endif
module Data.ByteString.Builder.Prim.Internal.Base16 (
EncodingTable
, lowerTable
, encode8_as_16h
) where
import qualified Data.ByteString as S
import qualified Data.ByteString.Internal as S
#if MIN_VERSION_base(4,4,0)
#if MIN_VERSION_base(4,7,0)
import Foreign
#else
import Foreign hiding (unsafePerformIO, unsafeForeignPtrToPtr)
#endif
import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
import System.IO.Unsafe (unsafePerformIO)
#else
import Foreign
#endif
newtype EncodingTable = EncodingTable (ForeignPtr Word8)
tableFromList :: [Word8] -> EncodingTable
tableFromList :: [Word8] -> EncodingTable
tableFromList [Word8]
xs = case [Word8] -> ByteString
S.pack [Word8]
xs of S.PS ForeignPtr Word8
fp Int
_ Int
_ -> ForeignPtr Word8 -> EncodingTable
EncodingTable ForeignPtr Word8
fp
unsafeIndex :: EncodingTable -> Int -> IO Word8
unsafeIndex :: EncodingTable -> Int -> IO Word8
unsafeIndex (EncodingTable ForeignPtr Word8
table) = Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
table)
base16EncodingTable :: EncodingTable -> IO EncodingTable
base16EncodingTable :: EncodingTable -> IO EncodingTable
base16EncodingTable EncodingTable
alphabet = do
[Word8]
xs <- [IO Word8] -> IO [Word8]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([IO Word8] -> IO [Word8]) -> [IO Word8] -> IO [Word8]
forall a b. (a -> b) -> a -> b
$ [[IO Word8]] -> [IO Word8]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[IO Word8]] -> [IO Word8]) -> [[IO Word8]] -> [IO Word8]
forall a b. (a -> b) -> a -> b
$ [ [Int -> IO Word8
ix Int
j, Int -> IO Word8
ix Int
k] | Int
j <- [Int
0..Int
15], Int
k <- [Int
0..Int
15] ]
EncodingTable -> IO EncodingTable
forall (m :: * -> *) a. Monad m => a -> m a
return (EncodingTable -> IO EncodingTable)
-> EncodingTable -> IO EncodingTable
forall a b. (a -> b) -> a -> b
$ [Word8] -> EncodingTable
tableFromList [Word8]
xs
where
ix :: Int -> IO Word8
ix = EncodingTable -> Int -> IO Word8
unsafeIndex EncodingTable
alphabet
{-# NOINLINE lowerAlphabet #-}
lowerAlphabet :: EncodingTable
lowerAlphabet :: EncodingTable
lowerAlphabet =
[Word8] -> EncodingTable
tableFromList ([Word8] -> EncodingTable) -> [Word8] -> EncodingTable
forall a b. (a -> b) -> a -> b
$ (Char -> Word8) -> [Char] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
forall a. Enum a => a -> Int
fromEnum) ([Char] -> [Word8]) -> [Char] -> [Word8]
forall a b. (a -> b) -> a -> b
$ [Char
'0'..Char
'9'] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char
'a'..Char
'f']
{-# NOINLINE lowerTable #-}
lowerTable :: EncodingTable
lowerTable :: EncodingTable
lowerTable = IO EncodingTable -> EncodingTable
forall a. IO a -> a
unsafePerformIO (IO EncodingTable -> EncodingTable)
-> IO EncodingTable -> EncodingTable
forall a b. (a -> b) -> a -> b
$ EncodingTable -> IO EncodingTable
base16EncodingTable EncodingTable
lowerAlphabet
{-# INLINE encode8_as_16h #-}
encode8_as_16h :: EncodingTable -> Word8 -> IO Word16
encode8_as_16h :: EncodingTable -> Word8 -> IO Word16
encode8_as_16h (EncodingTable ForeignPtr Word8
table) =
Ptr Word16 -> Int -> IO Word16
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr Word8 -> Ptr Word16
forall a b. Ptr a -> Ptr b
castPtr (Ptr Word8 -> Ptr Word16) -> Ptr Word8 -> Ptr Word16
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
table) (Int -> IO Word16) -> (Word8 -> Int) -> Word8 -> IO Word16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral