-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUtils.hs
83 lines (67 loc) · 2.98 KB
/
Utils.hs
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
{-# LANGUAGE CPP, NoImplicitPrelude, UnicodeSyntax, BangPatterns #-}
-- | Module re-imported from "System.USB" codebase.
--
-- original author: Bas van Dijk
--
-- license: BSD3
module Utils where
--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------
-- from base:
import Prelude ( (+), (-), (^)
, Enum, toEnum, fromEnum
, Integral, fromIntegral
)
#if __GLASGOW_HASKELL__ < 700
import Prelude ( fromInteger )
import Control.Monad ( (>>) )
#endif
import Control.Monad ( Monad, (>>=), mapM )
import Foreign.Ptr ( Ptr )
import Foreign.Storable ( Storable, )
import Foreign.Marshal.Array ( peekArray )
import Data.Bool ( Bool, otherwise )
import Data.Ord ( Ord, (<) )
import Data.Bits ( Bits, shiftL, shiftR, bitSize, (.&.) )
import Data.Int ( Int )
import System.IO ( IO )
-- from base-unicode-symbols:
import Data.Function.Unicode ( (∘) )
import Data.Ord.Unicode ( (≥), (≤) )
import Data.Bool.Unicode ( (∧) )
--------------------------------------------------------------------------------
-- Utils
--------------------------------------------------------------------------------
-- | @bits s e b@ extract bit @s@ to @e@ (including) from @b@.
bits ∷ Bits α ⇒ Int → Int → α → α
bits s e b = (2 ^ (e - s + 1) - 1) .&. (b `shiftR` s)
-- | @between n b e@ tests if @n@ is between the given bounds @b@ and @e@
-- (including).
between ∷ Ord α ⇒ α → α → α → Bool
between n b e = n ≥ b ∧ n ≤ e
-- | A generalized 'toEnum' that works on any 'Integral' type.
genToEnum ∷ (Integral i, Enum e) ⇒ i → e
genToEnum = toEnum ∘ fromIntegral
-- | A generalized 'fromEnum' that returns any 'Integral' type.
genFromEnum ∷ (Integral i, Enum e) ⇒ e → i
genFromEnum = fromIntegral ∘ fromEnum
-- | @mapPeekArray f n a@ applies the monadic function @f@ to each of the @n@
-- elements of the array @a@ and returns the results in a list.
mapPeekArray ∷ Storable α ⇒ (α → IO β) → Int → Ptr α → IO [β]
mapPeekArray f n a = peekArray n a >>= mapM f
-- | Monadic if...then...else...
ifM ∷ Monad m ⇒ m Bool → m α → m α → m α
ifM cM tM eM = cM >>= \c → if c then tM else eM
{-| @decodeBCD bitsInDigit bcd@ decodes the Binary Coded Decimal @bcd@ to a list
of its encoded digits. @bitsInDigit@, which is usually 4, is the number of bits
used to encode a single digit. See:
<http://en.wikipedia.org/wiki/Binary-coded_decimal>
-}
decodeBCD ∷ Bits α ⇒ Int → α → [α]
decodeBCD bitsInDigit abcd = go shftR []
where
shftR = bitSize abcd - bitsInDigit
go shftL ds | shftL < 0 = ds
| otherwise = let !d = (abcd `shiftL` shftL) `shiftR` shftR
in go (shftL - bitsInDigit) (d : ds)