{-# LANGUAGE CPP #-}
{-# LANGUAGE Haskell2010 #-}
module Endianness
( Word8, Word16, Word32, Word64
, ByteOrder(LittleEndian,BigEndian), targetByteOrder
, byteSwap16
, byteSwap32
, byteSwap64
, pokeWord16be
, pokeWord32be
, pokeWord64be
, peekWord16be
, peekWord32be
, peekWord64be
) where
import Data.Word (Word16, Word32, Word64, Word8)
import Foreign.Ptr
import Foreign.Storable
import GHC.ByteOrder (ByteOrder (..), targetByteOrder)
#if MIN_VERSION_base(4,7,0)
import Data.Word (byteSwap16, byteSwap32, byteSwap64)
#else
import Data.Bits
byteSwap16 :: Word16 -> Word16
byteSwap16 = (`rotateL` 8)
byteSwap32 :: Word32 -> Word32
byteSwap32 x
= (x `shiftR` 24) .|.
((x .&. 0x00ff0000) `shiftR` 8) .|.
((x .&. 0x0000ff00) `shiftL` 8) .|.
(x `shiftL` 24)
byteSwap64 :: Word64 -> Word64
byteSwap64 x = xh .|. (xl `shiftL` 32)
where
xl = fromIntegral (byteSwap32 (fromIntegral x))
xh = fromIntegral (byteSwap32 (fromIntegral (x `shiftR` 32)))
#endif
pokeWord16be :: Ptr Word16 -> Word16 -> IO ()
pokeWord16be = case targetByteOrder of
BigEndian -> poke
LittleEndian -> \p w -> poke p (byteSwap16 w)
pokeWord32be :: Ptr Word32 -> Word32 -> IO ()
pokeWord32be = case targetByteOrder of
BigEndian -> poke
LittleEndian -> \p w -> poke p (byteSwap32 w)
pokeWord64be :: Ptr Word64 -> Word64 -> IO ()
pokeWord64be = case targetByteOrder of
BigEndian -> poke
LittleEndian -> \p w -> poke p (byteSwap64 w)
peekWord16be :: Ptr Word16 -> IO Word16
peekWord16be = case targetByteOrder of
BigEndian -> peek
LittleEndian -> \p -> fmap byteSwap16 (peek p)
peekWord32be :: Ptr Word32 -> IO Word32
peekWord32be = case targetByteOrder of
BigEndian -> peek
LittleEndian -> \p -> fmap byteSwap32 (peek p)
peekWord64be :: Ptr Word64 -> IO Word64
peekWord64be = case targetByteOrder of
BigEndian -> peek
LittleEndian -> \p -> fmap byteSwap64 (peek p)