{-

Module : System.ByteOrder
Copyright : (c) Antoine Latter 2009
License : BSD3

Maintainer : Antoine Latter <aslatter@gmail.com>

-}

{-# OPTIONS_GHC -fno-cse #-}

module System.ByteOrder(byteOrder, ByteOrder(..)) where

import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (peekArray)
import Foreign.Ptr (castPtr)
import Foreign.Storable (poke)
import Data.Word
import System.IO.Unsafe (unsafePerformIO)

-- |Indicates the byte-ordering for a 4-byte value, where '1'
-- indicates the most-significant byte and '4' indicates the
-- least significant byte.
--
-- In this format, big endian byte order would be represented as:
-- (1,2,3,4).
--
-- For convinience, the most common cases (BigEndian and LittleEndian)
-- are provided their own constructors.
data ByteOrder
    = BigEndian
    | LittleEndian
    | Mixed (Word8, Word8, Word8, Word8)
 deriving (ByteOrder -> ByteOrder -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ByteOrder -> ByteOrder -> Bool
$c/= :: ByteOrder -> ByteOrder -> Bool
== :: ByteOrder -> ByteOrder -> Bool
$c== :: ByteOrder -> ByteOrder -> Bool
Eq, Int -> ByteOrder -> ShowS
[ByteOrder] -> ShowS
ByteOrder -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ByteOrder] -> ShowS
$cshowList :: [ByteOrder] -> ShowS
show :: ByteOrder -> String
$cshow :: ByteOrder -> String
showsPrec :: Int -> ByteOrder -> ShowS
$cshowsPrec :: Int -> ByteOrder -> ShowS
Show, ReadPrec [ByteOrder]
ReadPrec ByteOrder
Int -> ReadS ByteOrder
ReadS [ByteOrder]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ByteOrder]
$creadListPrec :: ReadPrec [ByteOrder]
readPrec :: ReadPrec ByteOrder
$creadPrec :: ReadPrec ByteOrder
readList :: ReadS [ByteOrder]
$creadList :: ReadS [ByteOrder]
readsPrec :: Int -> ReadS ByteOrder
$creadsPrec :: Int -> ReadS ByteOrder
Read, Eq ByteOrder
ByteOrder -> ByteOrder -> Bool
ByteOrder -> ByteOrder -> Ordering
ByteOrder -> ByteOrder -> ByteOrder
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ByteOrder -> ByteOrder -> ByteOrder
$cmin :: ByteOrder -> ByteOrder -> ByteOrder
max :: ByteOrder -> ByteOrder -> ByteOrder
$cmax :: ByteOrder -> ByteOrder -> ByteOrder
>= :: ByteOrder -> ByteOrder -> Bool
$c>= :: ByteOrder -> ByteOrder -> Bool
> :: ByteOrder -> ByteOrder -> Bool
$c> :: ByteOrder -> ByteOrder -> Bool
<= :: ByteOrder -> ByteOrder -> Bool
$c<= :: ByteOrder -> ByteOrder -> Bool
< :: ByteOrder -> ByteOrder -> Bool
$c< :: ByteOrder -> ByteOrder -> Bool
compare :: ByteOrder -> ByteOrder -> Ordering
$ccompare :: ByteOrder -> ByteOrder -> Ordering
Ord)

input :: Word32
input :: Word32
input = Word32
0x01020304

-- |Returns the native byte ordering of the system.
byteOrder :: ByteOrder
byteOrder :: ByteOrder
byteOrder = forall a. IO a -> a
unsafePerformIO IO ByteOrder
byteOrderIO
{-# NOINLINE byteOrder #-}

byteOrderIO :: IO ByteOrder
byteOrderIO :: IO ByteOrder
byteOrderIO = (Word8, Word8, Word8, Word8) -> ByteOrder
bytesToByteOrder forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Word32 -> IO (Word8, Word8, Word8, Word8)
wordToBytes Word32
input

wordToBytes :: Word32 -> IO (Word8,Word8,Word8,Word8)
wordToBytes :: Word32 -> IO (Word8, Word8, Word8, Word8)
wordToBytes Word32
word = forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca forall a b. (a -> b) -> a -> b
$ \Ptr Word32
wordPtr -> do
         forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word32
wordPtr Word32
word
         [Word8
x1,Word8
x2,Word8
x3,Word8
x4] <- forall a. Storable a => Int -> Ptr a -> IO [a]
peekArray Int
4 (forall a b. Ptr a -> Ptr b
castPtr Ptr Word32
wordPtr)
         forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
x1,Word8
x2,Word8
x3,Word8
x4)

bytesToByteOrder :: (Word8,Word8,Word8,Word8) -> ByteOrder
bytesToByteOrder :: (Word8, Word8, Word8, Word8) -> ByteOrder
bytesToByteOrder (Word8
1, Word8
2, Word8
3, Word8
4)     = ByteOrder
BigEndian
bytesToByteOrder (Word8
4, Word8
3, Word8
2, Word8
1)     = ByteOrder
LittleEndian
bytesToByteOrder (Word8
x1, Word8
x2, Word8
x3, Word8
x4) = (Word8, Word8, Word8, Word8) -> ByteOrder
Mixed (Word8
x1,Word8
x2,Word8
x3,Word8
x4)