{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.ByteString.Base16.Internal.Head
( encodeBase16_
, decodeBase16_
) where
#include "MachDeps.h"
import Data.ByteString (ByteString)
import Data.ByteString.Internal
import Data.ByteString.Base16.Internal.Tables
#if WORD_SIZE_IN_BITS >= 32
import Data.ByteString.Base16.Internal.W32.Loop
#elif WORD_SIZE_IN_BITS >= 64
import Data.ByteString.Base16.Internal.W64.Loop
#else
import Data.ByteString.Base16.Internal.W16.Loop
#endif
import Data.Text (Text)
import Foreign.Ptr
import Foreign.ForeignPtr
import GHC.ForeignPtr
import System.IO.Unsafe
encodeBase16_ :: ByteString -> ByteString
encodeBase16_ (PS !sfp !soff !slen) =
unsafeCreate dlen $ \dptr ->
withForeignPtr sfp $ \sptr ->
innerLoop
(castPtr dptr)
(castPtr (plusPtr sptr soff))
(plusPtr sptr (soff + slen))
where
!dlen = 2 * slen
decodeBase16_ :: ByteString -> Either Text ByteString
decodeBase16_ (PS !sfp !soff !slen)
| slen == 0 = Right ""
| r /= 0 = Left "invalid bytestring size"
| otherwise = unsafeDupablePerformIO $ do
dfp <- mallocPlainForeignPtrBytes q
withForeignPtr dfp $ \dptr ->
withForeignPtr dtableHi $ \hi ->
withForeignPtr dtableLo $ \lo ->
withForeignPtr sfp $ \sptr ->
decodeLoop
dfp
hi
lo
(castPtr dptr)
(castPtr (plusPtr sptr soff))
(plusPtr sptr (soff + slen))
where
(!q, !r) = slen `divMod` 2