packages feed

http2-0.1.2: test/HexString.hs

module HexString (fromHexString, toHexString) where

import Data.ByteString.Internal (ByteString(..), unsafeCreate)
import Data.Word8
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (plusPtr)
import Foreign.Storable (peek, poke, peekByteOff, pokeByteOff)

fromHexString :: ByteString -> ByteString
fromHexString (PS fptr off len) = unsafeCreate size $ \dst ->
    withForeignPtr fptr $ \src -> go (src `plusPtr` off) dst 0
  where
    size = len `div` 2
    go from to bytes
      | bytes == size = return ()
      | otherwise    = do
          w1 <- peek from
          w2 <- peekByteOff from 1
          let w = hex2w (w1,w2)
          poke to w
          go (from `plusPtr` 2) (to `plusPtr` 1) (bytes + 1)

hex2w :: (Word8, Word8) -> Word8
hex2w (w1,w2) = h2w w1 * 16 + h2w w2

h2w :: Word8 -> Word8
h2w w
  | isDigit w = w - _0
  | otherwise = w - _a + 10

toHexString :: ByteString -> ByteString
toHexString (PS fptr off len) = unsafeCreate size $ \dst ->
    withForeignPtr fptr $ \src -> go (src `plusPtr` off) dst 0
  where
    size = len * 2
    go from to bytes
      | bytes == len = return ()
      | otherwise    = do
          w <- peek from
          let (w1,w2) = w2hex w
          poke to w1
          pokeByteOff to 1 w2
          go (from `plusPtr` 1) (to `plusPtr` 2) (bytes + 1)

w2hex :: Word8 -> (Word8, Word8)
w2hex w = (w2h w1, w2h w2)
  where
    (w1,w2) = w `divMod` 16

w2h :: Word8 -> Word8
w2h w
  | w < 10    = w + _0
  | otherwise = w + _a - 10