@@ -1,5 +1,3 @@
1−{-# LANGUAGE MagicHash #-}
2−
31-----------------------------------------------------------------------------
42-- |
53-- Module : Data.Binary.Bits.Put
@@ -22,10 +20,8 @@ module Data.Binary.Bits.Put
2220 -- * Data types
2321 -- ** Bool
2422 , putBool
25− , putBool#
2623
2724 -- ** Words
28− , putWord#
2925 , putWord8
3026 , putWord16
3127 , putWord32
@@ -45,16 +41,14 @@ import qualified Data.Binary.Put as Put
4541import Data.Binary.Put ( Put )
4642import Data.Binary.Bits.Internal
4743import Data.Binary.Bits.BitOrder
48−import Data.Binary.Bits.Alignment
4944
5045import Data.ByteString as BS
5146import Data.ByteString.Unsafe as BS
5247
53−import Control.Monad (when)
48+import Control.Applicative
5449import Data.Bits
50+import Data.Monoid
5551import Data.Word
56−import GHC.Base (Word#, shiftRL#, Int (..), Int#, (-#), (<#), isTrue#, (+#), shiftL#, wordToWord8#, orWord8#)
57−import GHC.Word (Word8(..))
5852
5953data BitPut a = BitPut { run :: (S -> PairS a) }
6054
@@ -66,18 +60,11 @@ data S = S !Builder !Word8 !Int !BitOrder
6660putBool :: Bool -> BitPut ()
6761putBool b = putWord8 1 (if b then 0xff else 0x00)
6862
69−-- | Put a 1 bit 'Bool'.
70−putBool# :: Word# -> BitPut ()
71−putBool# b = putWord# 1# b
72−
7363
7464-- | Generic putWord
7565putWord :: (Num a, FastBits a, Integral a) => Int -> a -> BitPut ()
7666putWord n w = BitPut $ \s -> PairS () (putWordS n w s)
7767
78−putWord# :: Int# -> Word# -> BitPut ()
79−putWord# n w = BitPut $ \s -> PairS () (putWordS# n w s)
80−
8168putWordS :: (Num a, FastBits a, Integral a) => Int -> a -> S -> S
8269putWordS n w s@(S builder b o bo) = s'
8370 where
@@ -96,8 +83,8 @@ putWordS n w s@(S builder b o bo) = s'
9683 w' = case bo of
9784 BB -> w
9885 BL -> w `fastShiftR` cn
99− LL -> w `fastShiftR` cn
100− LB -> w
86+ LB -> w `fastShiftR` cn
87+ LL -> w
10188
10289 -- Select bits to store in the current byte.
10390 -- Put them in the correct order and return them in the least-significant
@@ -105,8 +92,8 @@ putWordS n w s@(S builder b o bo) = s'
10592 selectBits :: (Num a, FastBits a, Integral a) => a -> Word8
10693 selectBits x = fromIntegral $ case bo of
10794 BB -> mask cn $ x `fastShiftR` (n-cn)
108− LB -> reverseBits cn $ mask cn $ x `fastShiftR` (n-cn)
109− LL -> mask cn x
95+ LL -> reverseBits cn $ mask cn $ x `fastShiftR` (n-cn)
96+ LB -> mask cn x
11097 BL -> reverseBits cn $ mask cn x
11198
11299 -- shift left at the correct position
@@ -114,55 +101,8 @@ putWordS n w s@(S builder b o bo) = s'
114101 shl x = case bo of
115102 BB -> x `fastShiftL` (8-o-cn)
116103 BL -> x `fastShiftL` (8-o-cn)
117− LL -> x `fastShiftL` o
118104 LB -> x `fastShiftL` o
119−
120− flush s2@(S b2 w2 o2 bo2)
121− | o2 == 8 = S (b2 `mappend` B.singleton w2) 0 0 bo2
122− | otherwise = s2
123−
124−putWordS# :: Int# -> Word# -> S -> S
125−putWordS# n w s@(S builder (W8# b) (I# o) bo) = s'
126− where
127− min# :: Int# -> Int# -> Int#
128− min# x y | isTrue# (x <# y) = x
129− min# _ y = y
130−
131− -- number of bits that will be stored in the current byte
132− cn = min# (8# -# o) n
133−
134− -- new state
135− s' = case n of
136− 0# -> s
137− _ -> putWordS# (n -# cn) w' (flush (S builder (W8# b') (I# (o +# cn)) bo))
138−
139− -- new current byte
140− b' = wordToWord8# (shl (selectBits w)) `orWord8#` b
141−
142− -- Word containing the remaining (n-cn) bits to store in its LSB
143− w' = case bo of
144− BB -> w
145− BL -> w `shiftRL#` cn
146− LL -> w `shiftRL#` cn
147− LB -> w
148−
149− -- Select bits to store in the current byte.
150− -- Put them in the correct order and return them in the least-significant
151− -- bits of the returned value
152− selectBits :: Word# -> Word#
153− selectBits x = case bo of
154− BB -> mask# cn (x `shiftRL#` (n -# cn))
155− LB -> reverseBits# cn (mask# cn (x `shiftRL#` (n -# cn)))
156− LL -> mask# cn x
157− BL -> reverseBits# cn (mask# cn x)
158−
159− -- shift left at the correct position
160− shl :: Word# -> Word#
161− shl x = case bo of
162− BB -> x `shiftL#` (8# -# o -# cn)
163− BL -> x `shiftL#` (8# -# o -# cn)
164− LL -> x `shiftL#` o
165− LB -> x `shiftL#` o
105+ LL -> x `fastShiftL` o
166106
167107 flush s2@(S b2 w2 o2 bo2)
168108 | o2 == 8 = S (b2 `mappend` B.singleton w2) 0 0 bo2
@@ -201,9 +141,9 @@ putWord64be = putWord
201141--
202142-- Examples: 3 bits are already written in the current byte
203143-- BB: ABCDEFGH IJKLMNOP -> xxxABCDE FGHIJKLM NOPxxxxx
204−-- LL: ABCDEFGH IJKLMNOP -> LMNOPxxx DEFGHIJK xxxxxABC
144+-- LB: ABCDEFGH IJKLMNOP -> LMNOPxxx DEFGHIJK xxxxxABC
205145-- BL: ABCDEFGH IJKLMNOP -> xxxPONML KJIHGFED CBAxxxxx
206−-- LB: ABCDEFGH IJKLMNOP -> EDCBAxxx MLKJIHGF xxxxxPON
146+-- LL: ABCDEFGH IJKLMNOP -> EDCBAxxx MLKJIHGF xxxxxPON
207147putByteString :: ByteString -> BitPut ()
208148putByteString bs = BitPut $ \s -> PairS () (putByteStringS bs s)
209149
@@ -212,13 +152,13 @@ putByteStringS bs s
212152 | BS.null bs = s
213153 | otherwise = case s of
214154 (S builder b 0 BB) -> S (builder `mappend` B.fromByteString bs) b 0 BB
215− (S builder b 0 LL) -> S (builder `mappend` B.fromByteString (BS.reverse bs)) b 0 LL
216− (S builder b 0 LB) -> S (builder `mappend` B.fromByteString (rev bs)) b 0 LB
155+ (S builder b 0 LB) -> S (builder `mappend` B.fromByteString (BS.reverse bs)) b 0 LB
156+ (S builder b 0 LL) -> S (builder `mappend` B.fromByteString (rev bs)) b 0 LL
217157 (S builder b 0 BL) -> S (builder `mappend` B.fromByteString (rev (BS.reverse bs))) b 0 BL
218158 (S _ _ _ BB) -> putByteStringS (BS.unsafeTail bs) (putWordS 8 (BS.unsafeHead bs) s)
219− (S _ _ _ LL) -> putByteStringS (BS.unsafeInit bs) (putWordS 8 (BS.unsafeLast bs) s)
159+ (S _ _ _ LB) -> putByteStringS (BS.unsafeInit bs) (putWordS 8 (BS.unsafeLast bs) s)
220160 (S _ _ _ BL) -> putByteStringS (BS.unsafeInit bs) (putWordS 8 (BS.unsafeLast bs) s)
221− (S _ _ _ LB) -> putByteStringS (BS.unsafeTail bs) (putWordS 8 (BS.unsafeHead bs) s)
161+ (S _ _ _ LL) -> putByteStringS (BS.unsafeTail bs) (putWordS 8 (BS.unsafeHead bs) s)
222162 where
223163 rev = BS.map (reverseBits 8)
224164
@@ -238,9 +178,6 @@ flushIncomplete s@(S b w o bo)
238178 | o == 0 = s
239179 | otherwise = (S (b `mappend` B.singleton w) 0 0 bo)
240180
241−getOffset :: BitPut Int
242−getOffset = BitPut $ \s@(S _ _ o _) -> PairS o s
243−
244181-- | Run the 'BitPut' monad inside 'Put'.
245182runBitPut :: BitPut () -> Put.Put
246183runBitPut m = Put.putBuilder b
@@ -271,15 +208,3 @@ instance BitOrderable BitPut where
271208 setBitOrder bo = BitPut $ \(S bu b o _) -> PairS () (S bu b o bo)
272209
273210 getBitOrder = BitPut $ \s@(S _ _ _ bo) -> PairS bo s
274−
275−instance Alignable BitPut where
276− -- | Skip the given number of bits
277− skipBits n
278− | n <= 64 = putWord64 n 0
279− | otherwise = putWord64 64 0 >> skipBits (n-64)
280−
281− -- | Skip bits if necessary to align to the next byte
282− alignByte = do
283− o <- getOffset
284− when (o /= 0) $
285− skipBits (8-o)