blob: 86f731425126127dfc7449693b6404650beb645a [file] [log] [blame] [edit]
module Util where
import Foreign
import Foreign.Marshal
import Foreign.Ptr
import Foreign.Storable (peek, pokeByteOff)
import System.IO.Unsafe
-- the following two functions are copied from hsdns package:
-- http://hackage.haskell.org/package/hsdns-1.6.1/docs/src/ADNS-Endian.html#readWord32
-- note that later versions don't have these functions
data Endian
= LittleEndian -- ^ byte order: @1234@
| BigEndian -- ^ byte order: @4321@
| PDPEndian -- ^ byte order: @3412@
deriving (Show, Eq)
{-# NOINLINE endian #-}
endian :: Endian
endian =
System.IO.Unsafe.unsafePerformIO $
allocaArray (sizeOf (undefined :: Word32)) $ \p -> do
let val = 0x01020304 :: Word32
poke p val
let p' = castPtr p :: Ptr Word8
val' <- peekArray 4 p'
case val' of
(0x01:0x02:0x03:0x04:[]) -> return BigEndian
(0x04:0x03:0x02:0x01:[]) -> return LittleEndian
(0x03:0x04:0x01:0x02:[]) -> return PDPEndian
_ -> error "unknown endian"
readWord32 :: Word32 -> (Word8, Word8, Word8, Word8)
readWord32 n =
let (b1,n1) = (n .&. 255, n `shiftR` 8)
(b2,n2) = (n1 .&. 255, n1 `shiftR` 8)
(b3,n3) = (n2 .&. 255, n2 `shiftR` 8)
b4 = n3 .&. 255
in
case endian of
BigEndian -> (fromIntegral b4, fromIntegral b3, fromIntegral b2, fromIntegral b1)
LittleEndian -> (fromIntegral b1, fromIntegral b2, fromIntegral b3, fromIntegral b4)
PDPEndian -> (fromIntegral b2, fromIntegral b1, fromIntegral b4, fromIntegral b3)
-- copied from random-source package: http://hackage.haskell.org/package/random-source-0.3.0.6/docs/src/Data-Random-Internal-Words.html#buildWord32
-- there're more auxilliary functions which come handy
{-# INLINE buildWord32 #-}
-- |Build a word out of 4 bytes. No promises are made regarding the order
-- in which the bytes are stuffed. Note that this means that a 'RandomSource'
-- or 'MonadRandom' making use of the default definition of 'getRandomWord', etc.,
-- may return different random values on different platforms when started
-- with the same seed, depending on the platform's endianness.
buildWord32 :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
buildWord32 b0 b1 b2 b3
= unsafePerformIO . allocaBytes 4 $ \p -> do
pokeByteOff p 0 b0
pokeByteOff p 1 b1
pokeByteOff p 2 b2
pokeByteOff p 3 b3
peek (castPtr p)