{-# LANGUAGE MagicHash, BangPatterns #-}
-- |
-- Module : Crypto.Hash.Utils
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : unknown
--
-- Crypto hash utility for hexadecimal
--
module Crypto.Hash.Utils ( toHex ) where import
Data.ByteString
(ByteString) import qualified Data.ByteString.Internal as B import GHC.Prim import
GHC.Types
import
GHC.Word
import Foreign.ForeignPtr (withForeignPtr) import
Foreign.Ptr
(plusPtr, castPtr) import
Foreign.Storable
(poke, peek) import Crypto.Hash.Utils.Cpu import Data.Bits (
testBit
)
-- | Convert a bytestring to the hexadecimal equivalent
-- using 0123456789abcdef as digit
toHex
::
ByteString
->
ByteString
toHex
(
B.PS
fp
off
len
) =
B.unsafeCreate
(
len
*
2
)
$
\
d
->
withForeignPtr
fp
$
\
s
->
start
d
(
s
`plusPtr`
off
) where
start
db
sb
|
use32Hex
&&
(
len
`testBit`
0
)
==
False
=
loop32
db
sb
|
otherwise
=
loop8
db
sb
where
end
=
sb
`plusPtr`
len
-- write the hex output using 32 bits write.
loop32
d
s
|
s
==
end
=
return
()
|
otherwise
= do
b1
<-
fromIntegral
`fmap`
(
peek
s
::
IO
Word8
)
b2
<-
fromIntegral
`fmap`
(
peek
(
s
`plusPtr`
1
) ::
IO
Word8
)
poke
(
castPtr
d
) (
to32
b1
b2
)
loop32
(
d
`plusPtr`
4
) (
s
`plusPtr`
2
)
-- write the hex output 8 bits, 2 at a time
loop8
d
s
|
s
==
end
=
return
()
|
otherwise
= do
b
<-
fromIntegral
`fmap`
(
peek
s
::
IO
Word8
)
poke
d
(
r
tableHi
b
)
poke
(
d
`plusPtr`
1
) (
r
tableLo
b
)
loop8
(
d
`plusPtr`
2
) (
s
`plusPtr`
1
)
-- little endian version
to32
(
I#
i1
) (
I#
i2
) =
W32#
(
or#
(
or#
(
or#
hi2
lo2
)
hi1
)
lo1
) where
hi2
=
uncheckedShiftL#
(
indexWord8OffAddr#
tableLo
i2
) 24#
lo2
=
uncheckedShiftL#
(
indexWord8OffAddr#
tableHi
i2
) 16#
hi1
=
uncheckedShiftL#
(
indexWord8OffAddr#
tableLo
i1
) 8#
lo1
=
indexWord8OffAddr#
tableHi
i1
r
::
Addr#
->
Int
->
Word8
r
table
(
I#
index
) =
W8#
(
indexWord8OffAddr#
table
index
) !
tableLo
= "0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef\ \0123456789abcdef0123456789abcdef"# !
tableHi
= "00000000000000001111111111111111\ \22222222222222223333333333333333\ \44444444444444445555555555555555\ \66666666666666667777777777777777\ \88888888888888889999999999999999\ \aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb\ \ccccccccccccccccdddddddddddddddd\ \eeeeeeeeeeeeeeeeffffffffffffffff"#