packages feed

binary-bits (empty) → 0.1

raw patch · 6 files changed

+739/−0 lines, 6 filesdep +QuickCheckdep +basedep +binarysetup-changed

Dependencies added: QuickCheck, base, binary, bytestring, random, test-framework, test-framework-quickcheck2

Files

+ Data/Binary/Bits.hs view
@@ -0,0 +1,45 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Binary.Bits+-- Copyright   :  (c) Lennart Kolmodin 2010-2011+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  kolmodin@gmail.com+-- Stability   :  experimental+-- Portability :  portable (should run where the package binary runs)+--+-- Parse and write bits easily. Parsing can be done either in a monadic style, or more+-- efficiently, using the 'Applicative' style. Writing is monadic style only.+-- See "Data.Binary.Bits.Get" and "Data.Binary.Bits.Put", respectively.+-----------------------------------------------------------------------------++module Data.Binary.Bits where++import Data.Binary.Bits.Get+import Data.Binary.Bits.Put++import Data.Word++class BinaryBit a where+  putBits :: Int -> a -> BitPut ()+  getBits :: Int -> BitGet a++instance BinaryBit Bool where+  putBits _ = putBool+  getBits _ = getBool++instance BinaryBit Word8 where+  putBits = putWord8+  getBits = getWord8++instance BinaryBit Word16 where+  putBits = putWord16be+  getBits = getWord16be++instance BinaryBit Word32 where+  putBits = putWord32be+  getBits = getWord32be++instance BinaryBit Word64 where+  putBits = putWord64be+  getBits = getWord64be
+ Data/Binary/Bits/Get.hs view
@@ -0,0 +1,468 @@+{-# LANGUAGE RankNTypes, MagicHash, BangPatterns, CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Binary.Bits.Get+-- Copyright   :  (c) Lennart Kolmodin 2010-2011+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  kolmodin@gmail.com+-- Stability   :  experimental+-- Portability :  portable (should run where the package binary runs)+--+-- Parse bits easily. Parsing can be done either in a monadic style, or more+-- efficiently, using the 'Applicative' style.+--+-- For the monadic style, write your parser as a 'BitGet' monad using the+--+--   * 'getBool'+--+--   * 'getWord8'+--+--   * 'getWord16be'+--+--   * 'getWord32be'+--+--   * 'getWord64be'+--+--   * 'getByteString'+--+-- functions and run it with 'runBitGet'.+-- +-- For the applicative style, compose the fuctions+--+--   * 'bool'+--+--   * 'word8'+--+--   * 'word16be'+--+--   * 'word32be'+--+--   * 'word64be'+--+--   * 'byteString'+--+-- to make a 'Block'.+-- Use 'block' to turn it into the 'BitGet' monad to be able to run it with+-- 'runBitGet'.+-----------------------------------------------------------------------------++module Data.Binary.Bits.Get+            (+            -- * BitGet monad++            -- $bitget++              BitGet+            , runBitGet++            -- ** Get bytes+            , getBool+            , getWord8+            , getWord16be+            , getWord32be+            , getWord64be++            -- * Blocks++            -- $blocks+            , Block+            , block++            -- ** Read in Blocks+            , bool+            , word8+            , word16be+            , word32be+            , word64be+            , byteString+            , Data.Binary.Bits.Get.getByteString++            ) where++import Data.Binary.Get as B ( runGet, Get, getByteString )++import Data.ByteString as B+import Data.ByteString.Unsafe++import Data.Bits+import Data.Word++import Control.Applicative++import Prelude as P++#if defined(__GLASGOW_HASKELL__) && !defined(__HADDOCK__)+import GHC.Base+import GHC.Word+#endif+++-- $bitget+-- Parse bits using a monad.+--+-- @+--myBitParser :: 'Get' ('Word8', 'Word8')+--myBitParser = 'runGetBit' parse4by4+--+--parse4by4 :: 'BitGet' ('Word8', 'Word8')+--parse4by4 = do+--   bits <- 'getWord8' 4+--   more <- 'getWord8' 4+--   return (bits,more)+-- @++-- $blocks+-- Parse more efficiently in blocks. Each block is read with only one boundry+-- check (checking that there is enough input) as the size of the block can be+-- calculated statically. This is somewhat limiting as you cannot make the+-- parsing depend on the input being parsed.+-- +-- @+--data IPV6Header = IPV6Header {+--     ipv6Version :: 'Word8'+--   , ipv6TrafficClass :: 'Word8'+--   , ipv6FlowLabel :: 'Word32+--   , ipv6PayloadLength :: 'Word16'+--   , ipv6NextHeader :: 'Word8'+--   , ipv6HopLimit :: 'Word8'+--   , ipv6SourceAddress :: 'ByteString'+--   , ipv6DestinationAddress :: 'ByteString'+-- }+--+-- ipv6headerblock =+--         IPV6Header '<$>' 'word8' 4+--                    '<*>' 'word8' 8+--                    '<*>' 'word32be' 24+--                    '<*>' 'word16be' 16+--                    '<*>' 'word8' 8+--                    '<*>' 'word8' 8+--                    '<*>' 'byteString' 16+--                    '<*>' 'byteString' 16+--+--ipv6Header :: 'Get' IPV6Header+--ipv6Header = 'runBitGet' ('block' ipv6headerblock)+-- @++data S = S !ByteString -- Input+           !Int -- Bit offset (0-7)+          deriving (Show)++-- | A block that will be read with only one boundry check. Needs to know the+-- number of bits in advance.+data Block a = Block !Int (S -> a)++instance Functor Block where+  fmap f (Block i p) = Block i (\s -> f (p s))++instance Applicative Block where+  pure a = Block 0 (\_ -> a)+  (Block i p) <*> (Block j q) = Block (i+j) (\s -> p s $ q (incS i s))+  (Block i _)  *> (Block j q) = Block (i+j) (q . incS i)+  (Block i p) <*  (Block j _) = Block (i+j) p++-- | Get a block. Will be read with one single boundry check, and+-- therefore requires a statically known number of bits.+-- Build blocks using 'bool', 'word8', 'word16be', 'word32be', 'word64be',+-- 'byteString' and 'Applicative'.+block :: Block a -> BitGet a+block (Block i p) = do+  ensureBits i+  modifyState (\s -> (incS i s, p s))+++incS :: Int -> S -> S+incS o (S bs n) =+  let !o' = (n+o)+      !d = o' `shiftR` 3+      !n' = o' .&. make_mask 3+  in S (unsafeDrop d bs) n'++-- | make_mask 3 = 00000111+make_mask :: Bits a => Int -> a+make_mask n = (1 `shiftL` fromIntegral n) - 1+{-# SPECIALIZE make_mask :: Int -> Int #-}+{-# SPECIALIZE make_mask :: Int -> Word #-}+{-# SPECIALIZE make_mask :: Int -> Word8 #-}+{-# SPECIALIZE make_mask :: Int -> Word16 #-}+{-# SPECIALIZE make_mask :: Int -> Word32 #-}+{-# SPECIALIZE make_mask :: Int -> Word64 #-}++bit_offset :: Int -> Int+bit_offset n = make_mask 3 .&. n++byte_offset :: Int -> Int+byte_offset n = n `shiftR` 3++readBool :: S -> Bool+readBool (S bs n) = testBit (unsafeHead bs) (7-n)++readWord8 :: Int -> S -> Word8+readWord8 n (S bs o)+  -- no bits at all, return 0+  | n == 0 = 0++  -- all bits are in the same byte+  -- we just need to shift and mask them right+  | n <= 8 - o = let w = unsafeHead bs+                     m = make_mask n+                     w' = (w `shiftr_w8` (8 - o - n)) .&. m+                 in w'++  -- the bits are in two different bytes+  -- make a word16 using both bytes, and then shift and mask+  | n <= 8 = let w = (fromIntegral (unsafeHead bs) `shiftl_w16` 8) .|.+                     (fromIntegral (unsafeIndex bs 1))+                 m = make_mask n+                 w' = (w `shiftr_w16` (16 - o - n)) .&. m+             in fromIntegral w'+++readWord16be :: Int -> S -> Word16+readWord16be n s@(S bs o)++  -- 8 or fewer bits, use readWord8+  | n <= 8 = fromIntegral (readWord8 n s)++  -- handle 9 or more bits, stored in two bytes++  -- no offset, plain and simple 16 bytes+  | o == 0 && n == 16 = let msb = fromIntegral (unsafeHead bs)+                            lsb = fromIntegral (unsafeIndex bs 1)+                            w = (msb `shiftl_w16` 8) .|. lsb+                        in w++  -- no offset, but not full 16 bytes+  | o == 0 = let msb = fromIntegral (unsafeHead bs)+                 lsb = fromIntegral (unsafeIndex bs 1)+                 w = (msb `shiftl_w16` (n-8)) .|. (lsb `shiftr_w16` (16-n))+             in w++  -- with offset, and n=9-16+  | n <= 16 = readWithOffset s shiftl_w16 shiftr_w16 n++  | otherwise = error "readWord16be: tried to read more than 16 bits"++readWord32be :: Int -> S -> Word32+readWord32be n s@(S _ o)+  -- 8 or fewer bits, use readWord8+  | n <= 8 = fromIntegral (readWord8 n s)++  -- 16 or fewer bits, use readWord16be+  | n <= 16 = fromIntegral (readWord16be n s)++  | o == 0 = readWithoutOffset s shiftl_w32 shiftr_w32 n++  | n <= 32 = readWithOffset s shiftl_w32 shiftr_w32 n++  | otherwise = error "readWord32be: tried to read more than 32 bits"+++readWord64be :: Int -> S -> Word64+readWord64be n s@(S _ o)+  -- 8 or fewer bits, use readWord8+  | n <= 8 = fromIntegral (readWord8 n s)++  -- 16 or fewer bits, use readWord16be+  | n <= 16 = fromIntegral (readWord16be n s)++  | o == 0 = readWithoutOffset s shiftl_w64 shiftr_w64 n++  | n <= 64 = readWithOffset s shiftl_w64 shiftr_w64 n++  | otherwise = error "readWord64be: tried to read more than 64 bits"+++readByteString :: Int -> S -> ByteString+readByteString n s@(S bs o)+  -- no offset, easy.+  | o == 0 = unsafeTake n bs+  -- offset. ugg. this is really naive and slow. but also pretty easy :)+  | otherwise = B.pack (P.map (readWord8 8) (P.take n (iterate (incS 8) s)))++readWithoutOffset :: (Bits a, Num a)+                  => S -> (a -> Int -> a) -> (a -> Int -> a) -> Int -> a+readWithoutOffset (S bs o) shifterL shifterR n+  | o /= 0 = error "readWithoutOffset: there is an offset"++  | bit_offset n == 0 && byte_offset n <= 4 = +              let segs = byte_offset n+                  bn 0 = fromIntegral (unsafeHead bs)+                  bn n = (bn (n-1) `shifterL` 8) .|. fromIntegral (unsafeIndex bs n)++              in bn (segs-1)++  | n <= 64 = let segs = byte_offset n+                  o' = bit_offset (n - 8 + o)++                  bn 0 = fromIntegral (unsafeHead bs)+                  bn n = (bn (n-1) `shifterL` 8) .|. fromIntegral (unsafeIndex bs n)++                  msegs = bn (segs-1) `shifterL` o'++                  last = (fromIntegral (unsafeIndex bs segs)) `shifterR` (8 - o')++                  w = msegs .|. last+              in w++readWithOffset :: (Bits a, Num a)+         => S -> (a -> Int -> a) -> (a -> Int -> a) -> Int -> a+readWithOffset (S bs o) shifterL shifterR n+  | n <= 64 = let bits_in_msb = 8 - o+                  (n',top) = (n - bits_in_msb+                             , (fromIntegral (unsafeHead bs) .&. make_mask bits_in_msb) `shifterL` n')+                    +                  segs = byte_offset n'++                  bn 0 = 0+                  bn n = (bn (n-1) `shifterL` 8) .|. fromIntegral (unsafeIndex bs n)++                  o' = bit_offset n'++                  mseg = bn segs `shifterL` o'++                  last | o' > 0 = (fromIntegral (unsafeIndex bs (segs + 1))) `shifterR` (8 - o')+                       | otherwise = 0++                  w = top .|. mseg .|. last+              in w++------------------------------------------------------------------------+-- | 'BitGet' is a monad, applicative and a functor. See 'runBitGet'+-- for how to run it.+newtype BitGet a = B { runState :: S -> Get (S,a) }++instance Monad BitGet where+  return x = B $ \s -> return (s,x)+  fail str = B $ \_s -> fail str+  (B f) >>= g = B $ \s -> do (s',a) <- f s+                             runState (g a) s'++instance Functor BitGet where+  fmap f m = m >>= \a -> return (f a)++instance Applicative BitGet where+  pure x = return x+  fm <*> m = fm >>= \f -> m >>= \v -> return (f v)++-- | Run a 'BitGet' within the Binary packages 'Get' monad. If a byte has+-- been partially consumed it will be discarded once 'runBitGet' is finished.+runBitGet :: BitGet a -> Get a+runBitGet bg = do+  (_,a) <- runState bg (S B.empty 0)+  return a++getState :: BitGet S+getState = B $ \s -> return (s,s)++putState :: S -> BitGet ()+putState s = B $ \_ -> return (s,())++modifyState :: (S -> (S,a)) -> BitGet a+modifyState f = B $ \s -> return (f s)++-- | Make sure there are at least @n@ bits.+ensureBits :: Int -> BitGet ()+ensureBits n = do+  (S bs o) <- getState+  if n <= (B.length bs * 8 - o)+    then return ()+    else do let currentBits = B.length bs * 8 - o+            let byteCount = (n - currentBits + 7) `div` 8+            B $ \_ -> do bs' <- B.getByteString byteCount+                         return (S (bs`append`bs') o, ())++-- | Get 1 bit as a 'Bool'.+getBool :: BitGet Bool+getBool = block bool++-- | Get @n@ bits as a 'Word8'. @n@ must be within @[0..8]@.+getWord8 :: Int -> BitGet Word8+getWord8 n = block (word8 n)++-- | Get @n@ bits as a 'Word16'. @n@ must be within @[0..16]@.+getWord16be :: Int -> BitGet Word16+getWord16be n = block (word16be n)++-- | Get @n@ bits as a 'Word32'. @n@ must be within @[0..32]@.+getWord32be :: Int -> BitGet Word32+getWord32be n = block (word32be n)++-- | Get @n@ bits as a 'Word64'. @n@ must be within @[0..64]@.+getWord64be :: Int -> BitGet Word64+getWord64be n = block (word64be n)++-- | Get @n@ bytes as a 'ByteString'.+getByteString :: Int -> BitGet ByteString+getByteString n = block (byteString n)++-- | Read a 1 bit 'Bool'.+bool :: Block Bool+bool = Block 1 readBool++-- | Read @n@ bits as a 'Word8'. @n@ must be within @[0..8]@.+word8 :: Int -> Block Word8+word8 n = Block n (readWord8 n)++-- | Read @n@ bits as a 'Word16'. @n@ must be within @[0..16]@.+word16be :: Int -> Block Word16+word16be n = Block n (readWord16be n)++-- | Read @n@ bits as a 'Word32'. @n@ must be within @[0..32]@.+word32be :: Int -> Block Word32+word32be n = Block n (readWord32be n)++-- | Read @n@ bits as a 'Word64'. @n@ must be within @[0..64]@.+word64be :: Int -> Block Word64+word64be n = Block n (readWord64be n)++-- | Read @n@ bytes as a 'ByteString'.+byteString :: Int -> Block ByteString+byteString n = Block (n*8) (readByteString n)++------------------------------------------------------------------------+-- Unchecked shifts, from the package binary++shiftl_w16 :: Word16 -> Int -> Word16+shiftl_w32 :: Word32 -> Int -> Word32+shiftl_w64 :: Word64 -> Int -> Word64++#if defined(__GLASGOW_HASKELL__) && !defined(__HADDOCK__)+shiftl_w8  (W8#  w) (I# i) = W8# (w `uncheckedShiftL#`   i)+shiftl_w16 (W16# w) (I# i) = W16# (w `uncheckedShiftL#`   i)+shiftl_w32 (W32# w) (I# i) = W32# (w `uncheckedShiftL#`   i)++shiftr_w8  (W8#  w) (I# i) = W8# (w `uncheckedShiftRL#`   i)+shiftr_w16 (W16# w) (I# i) = W16# (w `uncheckedShiftRL#`  i)+shiftr_w32 (W32# w) (I# i) = W32# (w `uncheckedShiftRL#`  i)+++#if WORD_SIZE_IN_BITS < 64+shiftl_w64 (W64# w) (I# i) = W64# (w `uncheckedShiftL64#`  i)+shiftr_w64 (W64# w) (I# i) = W64# (w `uncheckedShiftRL64#` i)++#if __GLASGOW_HASKELL__ <= 606+-- Exported by GHC.Word in GHC 6.8 and higher+foreign import ccall unsafe "stg_uncheckedShiftL64"+    uncheckedShiftL64#     :: Word64# -> Int# -> Word64#+foreign import ccall unsafe "stg_uncheckedShiftRL64"+    uncheckedShiftRL64#     :: Word64# -> Int# -> Word64#+#endif++#else+shiftl_w64 (W64# w) (I# i) = W64# (w `uncheckedShiftL#`  i)+shiftr_w64 (W64# w) (I# i) = W64# (w `uncheckedShiftRL#` i)+#endif++#else+shiftl_w8 = shiftL+shiftl_w16 = shiftL+shiftl_w32 = shiftL+shiftl_w64 = shiftL++shiftr_w8 = shiftR+shiftr_w16 = shiftR+shiftr_w32 = shiftR+shiftr_w64 = shiftR+#endif
+ Data/Binary/Bits/Put.hs view
@@ -0,0 +1,150 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Binary.Bits.Put+-- Copyright   :  (c) Lennart Kolmodin 2010-2011+-- License     :  BSD3-style (see LICENSE)+--+-- Maintainer  :  kolmodin@gmail.com+-- Stability   :  experimental+-- Portability :  portable (should run where the package binary runs)+--+-- Put bits easily.+-----------------------------------------------------------------------------++module Data.Binary.Bits.Put+          ( BitPut+          , runBitPut+          , joinPut++          -- * Data types+          -- ** Bool+          , putBool++          -- ** Words+          , putWord8+          , putWord16be+          , putWord32be+          , putWord64be++          -- ** ByteString+          , putByteString+          )+          where++import qualified Data.Binary.Builder as B+import Data.Binary.Builder ( Builder )+import qualified Data.Binary.Put as Put+import Data.Binary.Put ( Put )++import Data.ByteString++import Data.Bits+import Data.Monoid+import Data.Word++data BitPut a = BitPut { run :: (S -> PairS a) }++data PairS a = PairS a {-# UNPACK #-} !S++data S = S !Builder !Word8 !Int++-- | Put a 1 bit 'Bool'.+putBool :: Bool -> BitPut ()+putBool b = putWord8 1 (if b then 1 else 0)++-- | Put the @n@ lower bits of a 'Word8'.+putWord8 :: Int -> Word8 -> BitPut ()+putWord8 n w = BitPut $ \s -> PairS () $+  case s of+                -- a whole word8, no offset+    (S b t o) | n == 8 && o == 0 -> flush $ S b w n+                -- less than a word8, will fit in the current word8+              | n <= 8 - o       -> flush $ S b (t .|. (w `shiftL` (8 - n - o))) (o+n)+                -- will finish this word8, and spill into the next one+              | otherwise -> flush $+                              let o' = o + n - 8+                                  w' = t .|. (w `shiftR` o')+                                  t' = w `shiftL` (8 - o')+                              in S (b `mappend` B.singleton w') t' o'++-- | Put the @n@ lower bits of a 'Word16'.+putWord16be :: Int -> Word16 -> BitPut ()+putWord16be n w+  | n <= 8 = putWord8 n (fromIntegral w)+  | otherwise =+      BitPut $ \s -> PairS () $+        case s of+          -- as n>=9, it's too big to fit into one single byte+          -- it'll either use 2 or 3 bytes+                                     -- it'll fit in 2 bytes+          (S b t o) | o + n <= 16 -> flush $+                        let o' = o + n - 8+                            w' = t .|. fromIntegral (w `shiftR` o')+                            t' = fromIntegral (w `shiftL` (8-o'))+                        in (S (b `mappend` B.singleton w') t' o')+                                   -- 3 bytes required+                    | otherwise -> flush $+                        let o'  = o + n - 16+                            w'  = t .|. fromIntegral (w `shiftR` (o' + 8))+                            w'' = fromIntegral ((w `shiftR` o') .&. 0xff)+                            t'  = fromIntegral (w `shiftL` (8-o'))+                        in (S (b `mappend` B.singleton w' `mappend` B.singleton w'') t' o')++-- | Put the @n@ lower bits of a 'Word32'.+putWord32be :: Int -> Word32 -> BitPut ()+putWord32be n w+  | n <= 16 = putWord16be n (fromIntegral w)+  | otherwise = do+      putWord32be (n-16) (w`shiftR`16)+      putWord32be    16  (w .&. 0x0000ffff)++-- | Put the @n@ lower bits of a 'Word64'.+putWord64be :: Int -> Word64 -> BitPut ()+putWord64be n w+  | n <= 32 = putWord32be n (fromIntegral w)+  | otherwise = do+      putWord64be (n-32) (w`shiftR`32)+      putWord64be    32  (w .&. 0xffffffff)++-- | Put a 'ByteString'.+putByteString :: ByteString -> BitPut ()+putByteString bs = do+  offset <- hasOffset+  if offset+    then mapM_ (putWord8 8) (unpack bs) -- naive+    else joinPut (Put.putByteString bs)+  where+    hasOffset = BitPut $ \ s@(S _ _ o) -> PairS (o /= 0) s++-- | Run a 'Put' inside 'BitPut'. Any partially written bytes will be flushed+-- before 'Put' executes to ensure byte alignment.+joinPut :: Put -> BitPut ()+joinPut m = BitPut $ \s0 -> PairS () $+  let (S b0 _ _) = flushIncomplete s0+      b = Put.execPut m+  in (S (b0`mappend`b) 0 0)++flush :: S -> S+flush s@(S b w o)+  | o > 8 = error "flush: offset > 8"+  | o == 8 = S (b `mappend` B.singleton w) 0 0+  | otherwise = s++flushIncomplete :: S -> S+flushIncomplete s@(S b w o)+  | o == 0 = s+  | otherwise = (S (b `mappend` B.singleton w) 0 0)++-- | Run the 'BitPut' monad inside 'Put'.+runBitPut :: BitPut () -> Put.Put+runBitPut m = Put.putBuilder b+  where+  PairS _ s = run m (S mempty 0 0)+  (S b _ _) = flushIncomplete s++instance Monad BitPut where+  m >>= k = BitPut $ \s ->+    let PairS a s'  = run m s+        PairS b s'' = run (k a) s'+    in PairS b s''+  return x = BitPut $ \s -> PairS x s
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) Lennart Kolmodin++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ binary-bits.cabal view
@@ -0,0 +1,44 @@+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/+name:                binary-bits+version:             0.1+synopsis:            Bit parsing/writing on top of binary.+description:         Bit parsing/writing on top of binary. Provides functions to+                     read and write bits to and from 8\/16\/32\/64 words.+license:             BSD3+license-file:        LICENSE+author:              Lennart Kolmodin <kolmodin@gmail.com>+maintainer:          Lennart Kolmodin <kolmodin@gmail.com>+category:            Data, Parsing+build-type:          Simple++cabal-version:       >=1.10++source-repository head+  type: darcs+  location: http://code.haskell.org/binary-bits++library+  build-depends: base==4.*, binary, bytestring++  other-extensions: RankNTypes, MagicHash, BangPatterns, CPP++  exposed-modules:     Data.Binary.Bits ,+                       Data.Binary.Bits.Put ,+                       Data.Binary.Bits.Get++  default-language:    Haskell98++  ghc-options: -O2 -Wall++test-suite qc+  type: exitcode-stdio-1.0+  main-is: BitsQC.hs+  default-language:    Haskell98++  build-depends: base==4.*, binary, bytestring,+                 QuickCheck>=2, random,+                 test-framework,+                 test-framework-quickcheck2++  other-extensions: RankNTypes, MagicHash, BangPatterns, CPP,+                    FlexibleInstances, FlexibleContexts, TupleSections