module ADNS.Endian ( Endian(..), endian, readWord32, readWord16 ) where
import Foreign
import System.IO.Unsafe
data Endian
= LittleEndian
| BigEndian
| PDPEndian
deriving (Show, Eq)
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, Word)
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)
readWord16 :: Word16 -> (Word8, Word8)
readWord16 n =
let (b1,n1) = (n .&. 255, n `shiftR` 8)
b2 = n1 .&. 255
in
case endian of
BigEndian -> (fromIntegral b2, fromIntegral b1)
LittleEndian -> (fromIntegral b1, fromIntegral b2)
PDPEndian -> (fromIntegral b2, fromIntegral b1)