File: Endian.hs

package info (click to toggle)
haskell-cpu 0.1.2-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 84 kB
  • sloc: haskell: 171; ansic: 79; makefile: 2
file content (137 lines) | stat: -rw-r--r-- 3,806 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
{-# LANGUAGE CPP, ForeignFunctionInterface #-}
-- |
-- Module      : System.Endian
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : unknown
--
module System.Endian
    ( Endianness(..)
    , getSystemEndianness
    -- little endian to and from cpu
    , fromLE32
    , fromLE64
    , fromLE16
    , toLE32
    , toLE64
    , toLE16
    -- big endian to and from cpu
    , fromBE32
    , fromBE64
    , fromBE16
    , toBE32
    , toBE64
    , toBE16
    ) where

#include "MachDeps.h"

import Foreign.C.Types
import Data.Word

-- | represent the CPU endianness
--
-- Big endian system stores bytes with the MSB as the first byte.
-- Little endian system stores bytes with the LSB as the first byte.
--
-- middle endian is purposely avoided.
data Endianness = LittleEndian
                | BigEndian
                deriving (Show,Eq)

-- | return the system endianness
getSystemEndianness :: Endianness
#ifdef WORDS_BIGENDIAN
getSystemEndianness = BigEndian
#else
getSystemEndianness = LittleEndian
#endif

-- | Convert from a big endian 64 bit value to the cpu endianness
fromBE64 :: Word64 -> Word64
fromBE64 = if getSystemEndianness == BigEndian then id else swap64

-- | Convert from a little endian 64 bit value to the cpu endianness
fromLE64 :: Word64 -> Word64
fromLE64 = if getSystemEndianness == LittleEndian then id else swap64

-- | Convert from a big endian 32 bit value to the cpu endianness
fromBE32 :: Word32 -> Word32
fromBE32 = if getSystemEndianness == BigEndian then id else swap32

-- | Convert from a little endian 32 bit value to the cpu endianness
fromLE32 :: Word32 -> Word32
fromLE32 = if getSystemEndianness == LittleEndian then id else swap32

-- | Convert from a big endian 16 bit value to the cpu endianness
fromBE16 :: Word16 -> Word16
fromBE16 = if getSystemEndianness == BigEndian then id else swap16

-- | Convert from a little endian 16 bit value to the cpu endianness
fromLE16 :: Word16 -> Word16
fromLE16 = if getSystemEndianness == LittleEndian then id else swap16


-- | Convert a 64 bit value in cpu endianess to big endian
toBE64 :: Word64 -> Word64
toBE64 = fromBE64

-- | Convert a 64 bit value in cpu endianess to little endian
toLE64 :: Word64 -> Word64
toLE64 = fromLE64

-- | Convert a 32 bit value in cpu endianess to big endian
toBE32 :: Word32 -> Word32
toBE32 = fromBE32

-- | Convert a 32 bit value in cpu endianess to little endian
toLE32 :: Word32 -> Word32
toLE32 = fromLE32

-- | Convert a 16 bit value in cpu endianness to big endian
toBE16 :: Word16 -> Word16
toBE16 = fromBE16

-- | Convert a 16 bit value in cpu endianness to little endian
toLE16 :: Word16 -> Word16
toLE16 = fromLE16

#if MIN_VERSION_base(4,7,0)

-- | Transform a 16 bit value bytes from a.b to b.a
swap16 :: Word16 -> Word16
swap16 = byteSwap16
    
-- | Transform a 32 bit value bytes from a.b.c.d to d.c.b.a
swap32 :: Word32 -> Word32
swap32 = byteSwap32

-- | Transform a 64 bit value bytes from a.b.c.d.e.f.g.h to h.g.f.e.d.c.b.a
swap64 :: Word64 -> Word64
swap64 = byteSwap64

#else

-- | Transform a 16 bit value bytes from a.b to b.a
{-# INLINE swap16 #-}
swap16 :: Word16 -> Word16
swap16 = fromIntegral . c_swap16 . fromIntegral

-- | Transform a 32 bit value bytes from a.b.c.d to d.c.b.a
{-# INLINE swap32 #-}
swap32 :: Word32 -> Word32
swap32 = fromIntegral . c_swap32 . fromIntegral

-- | Transform a 64 bit value bytes from a.b.c.d.e.f.g.h to h.g.f.e.d.c.b.a
{-# INLINE swap64 #-}
swap64 :: Word64 -> Word64
swap64 = fromIntegral . c_swap64 . fromIntegral

foreign import ccall unsafe "bitfn_swap16" c_swap16 :: CUShort -> CUShort
foreign import ccall unsafe "bitfn_swap32" c_swap32 :: CUInt -> CUInt
foreign import ccall unsafe "bitfn_swap64" c_swap64 :: CULLong -> CULLong

#endif