bytestring 0.10.8.1 → 0.10.8.2
raw patch · 13 files changed
+223/−165 lines, 13 filesdep ~dlistnew-uploaderPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
Dependency ranges changed: dlist
API changes (from Hackage documentation)
+ Data.ByteString: infixl 5 `snoc`
+ Data.ByteString: infixr 5 `cons`
+ Data.ByteString.Builder.Prim: infixl 4 >$<
+ Data.ByteString.Builder.Prim: infixr 5 >*<
+ Data.ByteString.Char8: infixl 5 `snoc`
+ Data.ByteString.Char8: infixr 5 `cons`
+ Data.ByteString.Lazy: infixl 5 `snoc`
+ Data.ByteString.Lazy: infixr 5 `cons'`
+ Data.ByteString.Lazy.Char8: infixl 5 `snoc`
+ Data.ByteString.Lazy.Char8: infixr 5 `cons'`
Files
- Changelog.md +8/−0
- Data/ByteString.hs +41/−31
- Data/ByteString/Builder/Internal.hs +7/−3
- Data/ByteString/Builder/Prim.hs +4/−0
- Data/ByteString/Char8.hs +9/−28
- Data/ByteString/Internal.hs +72/−33
- Data/ByteString/Lazy.hs +55/−29
- Data/ByteString/Lazy/Char8.hs +7/−21
- Data/ByteString/Lazy/Internal.hs +6/−6
- Data/ByteString/Short/Internal.hs +6/−10
- Data/ByteString/Unsafe.hs +4/−0
- bytestring.cabal +2/−2
- tests/Properties.hs +2/−2
Changelog.md view
@@ -1,3 +1,11 @@+0.10.8.2 Duncan Coutts <duncan@community.haskell.org> Feb 2017++ * Make readFile work for files with no size like /dev/null+ * Extend the cases in which concat and toStrict can avoid copying data+ * Fix building with ghc-7.0+ * Minor documentation improvements+ * Internal code cleanups+ 0.10.8.1 Duncan Coutts <duncan@community.haskell.org> May 2016 * Fix Builder output on big-endian architectures
Data/ByteString.hs view
@@ -217,7 +217,11 @@ ,scanl,scanl1,scanr,scanr1 ,readFile,writeFile,appendFile,replicate ,getContents,getLine,putStr,putStrLn,interact- ,zip,zipWith,unzip,notElem)+ ,zip,zipWith,unzip,notElem+#if !MIN_VERSION_base(4,6,0)+ ,catch+#endif+ ) #if MIN_VERSION_base(4,7,0) import Data.Bits (finiteBitSize, shiftL, (.|.), (.&.))@@ -233,7 +237,7 @@ import Data.Word (Word8) import Data.Maybe (isJust) -import Control.Exception (finally, bracket, assert, throwIO)+import Control.Exception (IOException, catch, finally, assert, throwIO) import Control.Monad (when) import Foreign.C.String (CString, CStringLen)@@ -251,7 +255,8 @@ -- hGetBuf and hPutBuf not available in yhc or nhc import System.IO (stdin,stdout,hClose,hFileSize- ,hGetBuf,hPutBuf,openBinaryFile+ ,hGetBuf,hPutBuf,hGetBufNonBlocking+ ,hPutBufNonBlocking,withBinaryFile ,IOMode(..)) import System.IO.Error (mkIOError, illegalOperationErrorType) @@ -259,9 +264,6 @@ import Data.Monoid (Monoid(..)) #endif --import System.IO (hGetBufNonBlocking, hPutBufNonBlocking)- #if MIN_VERSION_base(4,3,0) import System.IO (hGetBufSome) #else@@ -318,14 +320,14 @@ -- -- --- | /O(n)/ Convert a '[Word8]' into a 'ByteString'.+-- | /O(n)/ Convert a @['Word8']@ into a 'ByteString'. -- -- For applications with large numbers of string literals, pack can be a -- bottleneck. In such cases, consider using packAddress (GHC only). pack :: [Word8] -> ByteString pack = packBytes --- | /O(n)/ Converts a 'ByteString' to a '[Word8]'.+-- | /O(n)/ Converts a 'ByteString' to a @['Word8']@. unpack :: ByteString -> [Word8] unpack bs = build (unpackFoldr bs) {-# INLINE unpack #-}@@ -353,7 +355,7 @@ -- --------------------------------------------------------------------- -- | /O(1)/ 'length' returns the length of a ByteString as an 'Int'. length :: ByteString -> Int-length (PS _ _ l) = assert (l >= 0) $ l+length (PS _ _ l) = assert (l >= 0) l {-# INLINE length #-} ------------------------------------------------------------------------@@ -472,7 +474,7 @@ -- | The 'transpose' function transposes the rows and columns of its -- 'ByteString' argument. transpose :: [ByteString] -> [ByteString]-transpose ps = P.map pack (List.transpose (P.map unpack ps))+transpose ps = P.map pack . List.transpose . P.map unpack $ ps -- --------------------------------------------------------------------- -- Reducing 'ByteString's@@ -645,7 +647,7 @@ mapAccumL f acc (PS fp o len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> do gp <- mallocByteString len acc' <- withForeignPtr gp $ \p -> mapAccumL_ acc 0 (a `plusPtr` o) p- return $! (acc', PS gp 0 len)+ return (acc', PS gp 0 len) where mapAccumL_ !s !n !p1 !p2 | n >= len = return s@@ -1042,12 +1044,12 @@ -- 'ByteString's and concatenates the list after interspersing the first -- argument between each element of the list. intercalate :: ByteString -> [ByteString] -> ByteString-intercalate s = concat . (List.intersperse s)+intercalate s = concat . List.intersperse s {-# INLINE [1] intercalate #-} {-# RULES "ByteString specialise intercalate c -> intercalateByte" forall c s1 s2 .- intercalate (singleton c) (s1 : s2 : []) = intercalateWithByte c s1 s2+ intercalate (singleton c) [s1, s2] = intercalateWithByte c s1 s2 #-} -- | /O(n)/ intercalateWithByte. An efficient way to join to two ByteStrings@@ -1275,6 +1277,8 @@ -- | /O(n)/ The 'stripPrefix' function takes two ByteStrings and returns 'Just' -- the remainder of the second iff the first is its prefix, and otherwise -- 'Nothing'.+--+-- @since 0.10.8.0 stripPrefix :: ByteString -> ByteString -> Maybe ByteString stripPrefix bs1@(PS _ _ l1) bs2 | bs1 `isPrefixOf` bs2 = Just (unsafeDrop l1 bs2)@@ -1514,7 +1518,7 @@ let go 256 !_ = return () go i !ptr = do n <- peekElemOff arr i when (n /= 0) $ memset ptr (fromIntegral i) n >> return ()- go (i + 1) (ptr `plusPtr` (fromIntegral n))+ go (i + 1) (ptr `plusPtr` fromIntegral n) go 0 p where -- | Count the number of occurrences of each byte.@@ -1535,9 +1539,10 @@ -- | /O(n) construction/ Use a @ByteString@ with a function requiring a -- null-terminated @CString@. The @CString@ is a copy and will be freed--- automatically.+-- automatically; it must not be stored or used after the+-- subcomputation finishes. useAsCString :: ByteString -> (CString -> IO a) -> IO a-useAsCString (PS fp o l) action = do+useAsCString (PS fp o l) action = allocaBytes (l+1) $ \buf -> withForeignPtr fp $ \p -> do memcpy buf (p `plusPtr` o) (fromIntegral l)@@ -1546,6 +1551,7 @@ -- | /O(n) construction/ Use a @ByteString@ with a function requiring a @CStringLen@. -- As for @useAsCString@ this function makes a copy of the original @ByteString@.+-- It must not be stored or used after the subcomputation finishes. useAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a useAsCStringLen p@(PS _ _ l) f = useAsCString p $ \cstr -> f (cstr,l) @@ -1622,12 +1628,11 @@ -- if eol == True, then off is the offset of the '\n' -- otherwise off == w and the buffer is now empty. if off /= w- then do if (w == off + 1)+ then do if w == off + 1 then writeIORef haByteBuffer buf{ bufL=0, bufR=0 } else writeIORef haByteBuffer buf{ bufL = off + 1 } mkBigPS new_len (xs:xss)- else do- fill h_ buf{ bufL=0, bufR=0 } new_len (xs:xss)+ else fill h_ buf{ bufL=0, bufR=0 } new_len (xs:xss) -- find the end-of-line character, if there is one findEOL r w raw@@ -1641,8 +1646,7 @@ mkPS :: RawBuffer Word8 -> Int -> Int -> IO ByteString mkPS buf start end = create len $ \p ->- withRawBuffer buf $ \pbuf -> do- copyBytes p (pbuf `plusPtr` start) len+ withRawBuffer buf $ \pbuf -> copyBytes p (pbuf `plusPtr` start) len where len = end - start @@ -1820,24 +1824,30 @@ -- readFile :: FilePath -> IO ByteString readFile f =- bracket (openBinaryFile f ReadMode) hClose $ \h -> do- filesz <- hFileSize h+ withBinaryFile f ReadMode $ \h -> do+ -- hFileSize fails if file is not regular file (like+ -- /dev/null). Catch exception and try reading anyway.+ filesz <- catch (hFileSize h) useZeroIfNotRegularFile let readsz = (fromIntegral filesz `max` 0) + 1 hGetContentsSizeHint h readsz (readsz `max` 255) -- Our initial size is one bigger than the file size so that in the -- typical case we will read the whole file in one go and not have -- to allocate any more chunks. We'll still do the right thing if the -- file size is 0 or is changed before we do the read.+ where+ useZeroIfNotRegularFile :: IOException -> IO Integer+ useZeroIfNotRegularFile _ = return 0 +modifyFile :: IOMode -> FilePath -> ByteString -> IO ()+modifyFile mode f txt = withBinaryFile f mode (`hPut` txt)+ -- | Write a 'ByteString' to a file. writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\h -> hPut h txt)+writeFile = modifyFile WriteMode -- | Append a 'ByteString' to a file. appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\h -> hPut h txt)+appendFile = modifyFile AppendMode -- --------------------------------------------------------------------- -- Internal utilities@@ -1876,7 +1886,7 @@ -- Find from the end of the string using predicate findFromEndUntil :: (Word8 -> Bool) -> ByteString -> Int-findFromEndUntil f ps@(PS x s l) =- if null ps then 0- else if f (unsafeLast ps) then l- else findFromEndUntil f (PS x s (l-1))+findFromEndUntil f ps@(PS x s l)+ | null ps = 0+ | f (unsafeLast ps) = l+ | otherwise = findFromEndUntil f (PS x s (l - 1))
Data/ByteString/Builder/Internal.hs view
@@ -1,4 +1,8 @@ {-# LANGUAGE ScopedTypeVariables, CPP, BangPatterns, RankNTypes #-}+#if __GLASGOW_HASKELL__ == 700+-- This is needed as a workaround for an old bug in GHC 7.0.1 (Trac #4498)+{-# LANGUAGE MonoPatBinds #-}+#endif #if __GLASGOW_HASKELL__ >= 703 {-# LANGUAGE Unsafe #-} #endif@@ -92,7 +96,7 @@ , lazyByteStringCopy , lazyByteStringInsert , lazyByteStringThreshold- + , shortByteString , maximalCopySize@@ -201,8 +205,8 @@ byteStringFromBuffer (Buffer fpbuf (BufferRange op _)) = S.PS fpbuf 0 (op `minusPtr` unsafeForeignPtrToPtr fpbuf) ---- | Prepend the filled part of a 'Buffer' to a lazy 'L.ByteString'---- trimming it if necessary.+-- | Prepend the filled part of a 'Buffer' to a lazy 'L.ByteString'+-- trimming it if necessary. {-# INLINE trimmedChunkFromBuffer #-} trimmedChunkFromBuffer :: AllocationStrategy -> Buffer -> L.ByteString -> L.ByteString
Data/ByteString/Builder/Prim.hs view
@@ -1,5 +1,9 @@ {-# LANGUAGE CPP, BangPatterns, ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-}+#if __GLASGOW_HASKELL__ == 700+-- This is needed as a workaround for an old bug in GHC 7.0.1 (Trac #4498)+{-# LANGUAGE MonoPatBinds #-}+#endif #if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-} #endif
Data/ByteString/Char8.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE CPP, BangPatterns #-}-{-# LANGUAGE MagicHash, UnboxedTuples #-}+{-# LANGUAGE MagicHash #-} {-# OPTIONS_HADDOCK prune #-} #if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-}@@ -248,6 +248,7 @@ ,findSubstring,findSubstrings,breakSubstring,copy,group ,getLine, getContents, putStr, interact+ ,readFile, writeFile, appendFile ,hGetContents, hGet, hGetSome, hPut, hPutStr ,hGetLine, hGetNonBlocking, hPutNonBlocking ,packCString,packCStringLen@@ -263,8 +264,7 @@ #endif import qualified Data.List as List (intersperse) -import System.IO (Handle,stdout,openBinaryFile,hClose,hFileSize,IOMode(..))-import Control.Exception (bracket)+import System.IO (Handle,stdout) import Foreign @@ -460,7 +460,7 @@ -- -- This implemenation uses @memset(3)@ replicate :: Int -> Char -> ByteString-replicate w = B.replicate w . c2w+replicate n = B.replicate n . c2w {-# INLINE replicate #-} -- | /O(n)/, where /n/ is the length of the result. The 'unfoldr'@@ -474,7 +474,7 @@ -- -- > unfoldr (\x -> if x <= '9' then Just (x, succ x) else Nothing) '0' == "0123456789" unfoldr :: (a -> Maybe (Char, a)) -> a -> ByteString-unfoldr f x0 = B.unfoldr (fmap k . f) x0+unfoldr f x = B.unfoldr (fmap k . f) x where k (i, j) = (c2w i, j) -- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a ByteString from a seed@@ -486,7 +486,7 @@ -- -- > unfoldrN n f s == take n (unfoldr f s) unfoldrN :: Int -> (a -> Maybe (Char, a)) -> a -> (ByteString, Maybe a)-unfoldrN n f w = B.unfoldrN n ((k `fmap`) . f) w+unfoldrN n f = B.unfoldrN n ((k `fmap`) . f) where k (i,j) = (c2w i, j) {-# INLINE unfoldrN #-} @@ -877,7 +877,7 @@ -- after appending a terminating newline to each. unlines :: [ByteString] -> ByteString unlines [] = empty-unlines ss = (concat $ List.intersperse nl ss) `append` nl -- half as much space+unlines ss = concat (List.intersperse nl ss) `append` nl -- half as much space where nl = singleton '\n' -- | 'words' breaks a ByteString up into a list of words, which@@ -957,7 +957,7 @@ combine _ acc [] ps = (toInteger acc, ps) combine d acc ns ps =- ((10^d * combine1 1000000000 ns + toInteger acc), ps)+ (10^d * combine1 1000000000 ns + toInteger acc, ps) combine1 _ [n] = n combine1 b ns = combine1 (b*b) $ combine2 b ns@@ -968,30 +968,11 @@ ------------------------------------------------------------------------ -- For non-binary text processing: --- | Read an entire file strictly into a 'ByteString'. This is far more--- efficient than reading the characters into a 'String' and then using--- 'pack'. It also may be more efficient than opening the file and--- reading it using hGet.-readFile :: FilePath -> IO ByteString-readFile f = bracket (openBinaryFile f ReadMode) hClose- (\h -> hFileSize h >>= hGet h . fromIntegral)---- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\h -> hPut h txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\h -> hPut h txt)-- -- | Write a ByteString to a handle, appending a newline byte hPutStrLn :: Handle -> ByteString -> IO () hPutStrLn h ps | length ps < 1024 = hPut h (ps `B.snoc` 0x0a)- | otherwise = hPut h ps >> hPut h (B.singleton (0x0a)) -- don't copy+ | otherwise = hPut h ps >> hPut h (B.singleton 0x0a) -- don't copy -- | Write a ByteString to stdout, appending a newline byte putStrLn :: ByteString -> IO ()
Data/ByteString/Internal.hs view
@@ -34,7 +34,6 @@ unpackBytes, unpackAppendBytesLazy, unpackAppendBytesStrict, unpackChars, unpackAppendCharsLazy, unpackAppendCharsStrict, unsafePackAddress,- checkedSum, -- * Low level imperative construction create, -- :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString@@ -51,6 +50,7 @@ -- * Utilities nullForeignPtr, -- :: ForeignPtr Word8+ checkedAdd, -- :: String -> Int -> Int -> Int -- * Standard C Functions c_strlen, -- :: CString -> IO CInt@@ -76,17 +76,19 @@ inlinePerformIO -- :: IO a -> a ) where -import Prelude hiding (concat)+import Prelude hiding (concat, null) import qualified Data.List as List import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr, FunPtr, plusPtr) import Foreign.Storable (Storable(..))+ #if MIN_VERSION_base(4,5,0) || __GLASGOW_HASKELL__ >= 703 import Foreign.C.Types (CInt(..), CSize(..), CULong(..)) #else import Foreign.C.Types (CInt, CSize, CULong) #endif+ import Foreign.C.String (CString) #if MIN_VERSION_base(4,9,0)@@ -95,6 +97,7 @@ #if !(MIN_VERSION_base(4,8,0)) import Data.Monoid (Monoid(..)) #endif+ import Control.DeepSeq (NFData(rnf)) import Data.String (IsString(..))@@ -107,25 +110,22 @@ import Data.Typeable (Typeable) import Data.Data (Data(..), mkNoRepType) -import GHC.Base (realWorld#,unsafeChr)+import GHC.Base (nullAddr#,realWorld#,unsafeChr)+ #if MIN_VERSION_base(4,4,0) import GHC.CString (unpackCString#) #else import GHC.Base (unpackCString#) #endif+ import GHC.Prim (Addr#)-#if __GLASGOW_HASKELL__ >= 611-import GHC.IO (IO(IO))-#else-import GHC.IOBase (IO(IO),RawBuffer)-#endif+ #if __GLASGOW_HASKELL__ >= 611-import GHC.IO (unsafeDupablePerformIO)+import GHC.IO (IO(IO),unsafeDupablePerformIO) #else-import GHC.IOBase (unsafeDupablePerformIO)+import GHC.IOBase (IO(IO),RawBuffer,unsafeDupablePerformIO) #endif -import GHC.Base (nullAddr#) import GHC.ForeignPtr (ForeignPtr(ForeignPtr) ,newForeignPtr_, mallocPlainForeignPtrBytes) import GHC.Ptr (Ptr(..), castPtr)@@ -168,7 +168,7 @@ mconcat = concat instance NFData ByteString where- rnf (PS _ _ _) = ()+ rnf PS{} = () instance Show ByteString where showsPrec p ps r = showsPrec p (unpackChars ps) r@@ -180,7 +180,7 @@ fromString = packChars instance Data ByteString where- gfoldl f z txt = z packBytes `f` (unpackBytes txt)+ gfoldl f z txt = z packBytes `f` unpackBytes txt toConstr _ = error "Data.ByteString.ByteString.toConstr" gunfold _ _ = error "Data.ByteString.ByteString.gunfold" dataTypeOf _ = mkNoRepType "Data.ByteString.ByteString"@@ -306,7 +306,7 @@ unpackAppendBytesStrict :: ByteString -> [Word8] -> [Word8] unpackAppendBytesStrict (PS fp off len) xs =- accursedUnutterablePerformIO $ withForeignPtr fp $ \base -> do+ accursedUnutterablePerformIO $ withForeignPtr fp $ \base -> loop (base `plusPtr` (off-1)) (base `plusPtr` (off-1+len)) xs where loop !sentinal !p acc@@ -343,7 +343,7 @@ -> Int -- ^ Offset -> Int -- ^ Length -> ByteString-fromForeignPtr fp s l = PS fp s l+fromForeignPtr = PS {-# INLINE fromForeignPtr #-} -- | /O(1)/ Deconstruct a ForeignPtr from a ByteString@@ -418,15 +418,15 @@ withForeignPtr fp $ \p -> do (off, l', res) <- f p if assert (l' <= l) $ l' >= l- then return $! (PS fp 0 l, res)+ then return (PS fp 0 l, res) else do ps <- create l' $ \p' -> memcpy p' (p `plusPtr` off) l'- return $! (ps, res)+ return (ps, res) -- | Wrapper of 'mallocForeignPtrBytes' with faster implementation for GHC -- mallocByteString :: Int -> IO (ForeignPtr a)-mallocByteString l = mallocPlainForeignPtrBytes l+mallocByteString = mallocPlainForeignPtrBytes {-# INLINE mallocByteString #-} ------------------------------------------------------------------------@@ -461,24 +461,63 @@ withForeignPtr fp2 $ \p2 -> memcpy destptr2 (p2 `plusPtr` off2) len2 concat :: [ByteString] -> ByteString-concat [] = mempty-concat [bs] = bs-concat bss0 = unsafeCreate totalLen $ \ptr -> go bss0 ptr+concat = \bss0 -> goLen0 bss0 bss0+ -- The idea here is we first do a pass over the input list to determine:+ --+ -- 1. is a copy necessary? e.g. @concat []@, @concat [mempty, "hello"]@,+ -- and @concat ["hello", mempty, mempty]@ can all be handled without+ -- copying.+ -- 2. if a copy is necessary, how large is the result going to be?+ --+ -- If a copy is necessary then we create a buffer of the appropriate size+ -- and do another pass over the input list, copying the chunks into the+ -- buffer. Also, since foreign calls aren't entirely free we skip over+ -- empty chunks while copying.+ --+ -- We pass the original [ByteString] (bss0) through as an argument through+ -- goLen0, goLen1, and goLen since we will need it again in goCopy. Passing+ -- it as an explicit argument avoids capturing it in these functions'+ -- closures which would result in unnecessary closure allocation. where- totalLen = checkedSum "concat" [ len | (PS _ _ len) <- bss0 ]- go [] !_ = return ()- go (PS fp off len:bss) !ptr = do+ -- It's still possible that the result is empty+ goLen0 _ [] = mempty+ goLen0 bss0 (PS _ _ 0 :bss) = goLen0 bss0 bss+ goLen0 bss0 (bs :bss) = goLen1 bss0 bs bss++ -- It's still possible that the result is a single chunk+ goLen1 _ bs [] = bs+ goLen1 bss0 bs (PS _ _ 0 :bss) = goLen1 bss0 bs bss+ goLen1 bss0 bs (PS _ _ len:bss) = goLen bss0 (checkedAdd "concat" len' len) bss+ where PS _ _ len' = bs++ -- General case, just find the total length we'll need+ goLen bss0 !total (PS _ _ len:bss) = goLen bss0 total' bss+ where total' = checkedAdd "concat" total len+ goLen bss0 total [] =+ unsafeCreate total $ \ptr -> goCopy bss0 ptr++ -- Copy the data+ goCopy [] !_ = return ()+ goCopy (PS _ _ 0 :bss) !ptr = goCopy bss ptr+ goCopy (PS fp off len:bss) !ptr = do withForeignPtr fp $ \p -> memcpy ptr (p `plusPtr` off) len- go bss (ptr `plusPtr` len)+ goCopy bss (ptr `plusPtr` len)+{-# NOINLINE concat #-} --- | Add a list of non-negative numbers. Errors out on overflow.-checkedSum :: String -> [Int] -> Int-checkedSum fun = go 0- where go !a (x:xs)- | ax >= 0 = go ax xs- | otherwise = overflowError fun- where ax = a + x- go a _ = a+{-# RULES+"ByteString concat [] -> mempty"+ concat [] = mempty+"ByteString concat [bs] -> bs" forall x.+ concat [x] = x+ #-}++-- | Add two non-negative numbers. Errors out on overflow.+checkedAdd :: String -> Int -> Int -> Int+checkedAdd fun x y+ | r >= 0 = r+ | otherwise = overflowError fun+ where r = x + y+{-# INLINE checkedAdd #-} ------------------------------------------------------------------------
Data/ByteString/Lazy.hs view
@@ -229,14 +229,12 @@ import Data.Monoid (Monoid(..)) #endif import Control.Monad (mplus)- import Data.Word (Word8) import Data.Int (Int64)-import System.IO (Handle,stdin,stdout,openBinaryFile,IOMode(..)+import System.IO (Handle,openBinaryFile,stdin,stdout,withBinaryFile,IOMode(..) ,hClose) import System.IO.Error (mkIOError, illegalOperationErrorType) import System.IO.Unsafe-import Control.Exception (bracket) import Foreign.ForeignPtr (withForeignPtr) import Foreign.Ptr@@ -284,17 +282,40 @@ -- avoid converting back and forth between strict and lazy bytestrings. -- toStrict :: ByteString -> S.ByteString-toStrict Empty = S.empty-toStrict (Chunk c Empty) = c-toStrict cs0 = S.unsafeCreate totalLen $ \ptr -> go cs0 ptr+toStrict = \cs -> goLen0 cs cs+ -- We pass the original [ByteString] (bss0) through as an argument through+ -- goLen0, goLen1, and goLen since we will need it again in goCopy. Passing+ -- it as an explicit argument avoids capturing it in these functions'+ -- closures which would result in unnecessary closure allocation. where- totalLen = S.checkedSum "Lazy.toStrict" . L.map S.length . toChunks $ cs0+ -- It's still possible that the result is empty+ goLen0 _ Empty = S.empty+ goLen0 cs0 (Chunk c cs) | S.null c = goLen0 cs0 cs+ goLen0 cs0 (Chunk c cs) = goLen1 cs0 c cs - go Empty !_ = return ()- go (Chunk (S.PS fp off len) cs) !destptr =+ -- It's still possible that the result is a single chunk+ goLen1 _ bs Empty = bs+ goLen1 cs0 bs (Chunk c cs)+ | S.null c = goLen1 cs0 bs cs+ | otherwise =+ goLen cs0 (S.checkedAdd "Lazy.concat" (S.length bs) (S.length c)) cs++ -- General case, just find the total length we'll need+ goLen cs0 !total (Chunk c cs) = goLen cs0 total' cs+ where+ total' = S.checkedAdd "Lazy.concat" total (S.length c)+ goLen cs0 total Empty =+ S.unsafeCreate total $ \ptr -> goCopy cs0 ptr++ -- Copy the data+ goCopy Empty !_ = return ()+ goCopy (Chunk (S.PS _ _ 0 ) cs) !ptr = goCopy cs ptr+ goCopy (Chunk (S.PS fp off len) cs) !ptr = do withForeignPtr fp $ \p -> do- S.memcpy destptr (p `plusPtr` off) len- go cs (destptr `plusPtr` len)+ S.memcpy ptr (p `plusPtr` off) len+ goCopy cs (ptr `plusPtr` len)+-- See the comment on Data.ByteString.Internal.concat for some background on+-- this implementation. ------------------------------------------------------------------------ @@ -478,7 +499,7 @@ -- (typically the right-identity of the operator), and a ByteString, -- reduces the ByteString using the binary operator, from right to left. foldr :: (Word8 -> a -> a) -> a -> ByteString -> a-foldr k z cs = foldrChunks (flip (S.foldr k)) z cs+foldr k z = foldrChunks (flip (S.foldr k)) z {-# INLINE foldr #-} -- | 'foldl1' is a variant of 'foldl' that has no starting value@@ -555,7 +576,7 @@ -- passing an accumulating parameter from left to right, and returning a -- final value of this accumulator together with the new ByteString. mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumL f s0 cs0 = go s0 cs0+mapAccumL f s0 = go s0 where go s Empty = (s, Empty) go s (Chunk c cs) = (s'', Chunk c' cs')@@ -567,7 +588,7 @@ -- passing an accumulating parameter from right to left, and returning a -- final value of this accumulator together with the new ByteString. mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumR f s0 cs0 = go s0 cs0+mapAccumR f s0 = go s0 where go s Empty = (s, Empty) go s (Chunk c cs) = (s'', Chunk c' cs')@@ -638,13 +659,13 @@ -- prepending to the ByteString and @b@ is used as the next element in a -- recursive call. unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString-unfoldr f s0 = unfoldChunk 32 s0- where unfoldChunk n s =- case S.unfoldrN n f s of+unfoldr f z = unfoldChunk 32 z+ where unfoldChunk n x =+ case S.unfoldrN n f x of (c, Nothing) | S.null c -> Empty | otherwise -> Chunk c Empty- (c, Just s') -> Chunk c (unfoldChunk (n*2) s')+ (c, Just x') -> Chunk c (unfoldChunk (n*2) x') -- --------------------------------------------------------------------- -- Substrings@@ -781,7 +802,6 @@ comb acc (s:[]) Empty = revChunks (s:acc) : [] comb acc (s:[]) (Chunk c cs) = comb (s:acc) (S.splitWith p c) cs comb acc (s:ss) cs = revChunks (s:acc) : comb [] ss cs- {-# INLINE splitWith #-} -- | /O(n)/ Break a 'ByteString' into pieces separated by the byte@@ -807,7 +827,7 @@ where comb :: [P.ByteString] -> [P.ByteString] -> ByteString -> [ByteString] comb acc (s:[]) Empty = revChunks (s:acc) : [] comb acc (s:[]) (Chunk c cs) = comb (s:acc) (S.split w c) cs- comb acc (s:ss) cs = revChunks (s:acc) : comb [] ss cs+ comb acc (s:ss) cs = revChunks (s:acc) : comb [] ss cs {-# INLINE split #-} -- | The 'group' function takes a ByteString and returns a list of@@ -859,7 +879,7 @@ -- 'ByteString's and concatenates the list after interspersing the first -- argument between each element of the list. intercalate :: ByteString -> [ByteString] -> ByteString-intercalate s = concat . (L.intersperse s)+intercalate s = concat . L.intersperse s -- --------------------------------------------------------------------- -- Indexing ByteStrings@@ -893,7 +913,8 @@ -- -- > elemIndexEnd c xs == -- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)-+--+-- @since 0.10.6.0 elemIndexEnd :: Word8 -> ByteString -> Maybe Int64 elemIndexEnd w = elemIndexEnd' 0 where@@ -1040,6 +1061,8 @@ -- | /O(n)/ The 'stripPrefix' function takes two ByteStrings and returns 'Just' -- the remainder of the second iff the first is its prefix, and otherwise -- 'Nothing'.+--+-- @since 0.10.8.0 stripPrefix :: ByteString -> ByteString -> Maybe ByteString stripPrefix Empty bs = Just bs stripPrefix _ Empty = Nothing@@ -1111,7 +1134,7 @@ inits :: ByteString -> [ByteString] inits = (Empty :) . inits' where inits' Empty = []- inits' (Chunk c cs) = L.map (\c' -> Chunk c' Empty) (L.tail (S.inits c))+ inits' (Chunk c cs) = L.map (`Chunk` Empty) (L.tail (S.inits c)) ++ L.map (Chunk c) (inits' cs) -- | /O(n)/ Return all final segments of the given 'ByteString', longest first.@@ -1166,7 +1189,7 @@ loop = do c <- S.hGetSome h k -- only blocks if there is no data available if S.null c- then do hClose h >> return Empty+ then hClose h >> return Empty else do cs <- lazyRead return (Chunk c cs) @@ -1244,24 +1267,27 @@ readFile :: FilePath -> IO ByteString readFile f = openBinaryFile f ReadMode >>= hGetContents +modifyFile :: IOMode -> FilePath -> ByteString -> IO ()+modifyFile mode f txt = withBinaryFile f mode (`hPut` txt)+ -- | Write a 'ByteString' to a file. -- writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\hdl -> hPut hdl txt)+writeFile = modifyFile WriteMode -- | Append a 'ByteString' to a file. -- appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\hdl -> hPut hdl txt)+appendFile = modifyFile AppendMode -- | getContents. Equivalent to hGetContents stdin. Will read /lazily/ -- getContents :: IO ByteString getContents = hGetContents stdin --- | Outputs a 'ByteString' to the specified 'Handle'.+-- | Outputs a 'ByteString' to the specified 'Handle'. The chunks will be+-- written one at a time. Other threads might write to the 'Handle' between the+-- writes, and hence 'hPut' alone might not be suitable for concurrent writes. -- hPut :: Handle -> ByteString -> IO () hPut h cs = foldrChunks (\c rest -> S.hPut h c >> rest) (return ()) cs
Data/ByteString/Lazy/Char8.hs view
@@ -204,7 +204,8 @@ ,stripPrefix,stripSuffix ,hGetContents, hGet, hPut, getContents ,hGetNonBlocking, hPutNonBlocking- ,putStr, hPutStr, interact)+ ,putStr, hPutStr, interact+ ,readFile,writeFile,appendFile) -- Functions we need to wrap. import qualified Data.ByteString.Lazy as L@@ -225,8 +226,7 @@ ,readFile,writeFile,appendFile,replicate,getContents,getLine,putStr,putStrLn ,zip,zipWith,unzip,notElem,repeat,iterate,interact,cycle) -import System.IO (Handle,stdout,hClose,openBinaryFile,IOMode(..))-import Control.Exception (bracket)+import System.IO (Handle, stdout) ------------------------------------------------------------------------ @@ -735,7 +735,7 @@ -- after appending a terminating newline to each. unlines :: [ByteString] -> ByteString unlines [] = empty-unlines ss = (concat $ List.intersperse nl ss) `append` nl -- half as much space+unlines ss = concat (List.intersperse nl ss) `append` nl -- half as much space where nl = singleton '\n' -- | 'words' breaks a ByteString up into a list of words, which@@ -781,10 +781,10 @@ {-# INLINE end #-} end _ 0 _ _ _ = Nothing- end neg _ n c cs = e `seq` e+ end neg _ n c cs = e where n' = if neg then negate n else n c' = chunk c cs- e = n' `seq` c' `seq` Just $! (n',c')+ e = n' `seq` c' `seq` Just (n',c') -- in n' `seq` c' `seq` JustS n' c' @@ -840,30 +840,16 @@ end n c cs = let c' = chunk c cs in c' `seq` (n, c') --- | Read an entire file /lazily/ into a 'ByteString'.-readFile :: FilePath -> IO ByteString-readFile f = openBinaryFile f ReadMode >>= hGetContents --- | Write a 'ByteString' to a file.-writeFile :: FilePath -> ByteString -> IO ()-writeFile f txt = bracket (openBinaryFile f WriteMode) hClose- (\hdl -> hPut hdl txt)---- | Append a 'ByteString' to a file.-appendFile :: FilePath -> ByteString -> IO ()-appendFile f txt = bracket (openBinaryFile f AppendMode) hClose- (\hdl -> hPut hdl txt)-- -- | Write a ByteString to a handle, appending a newline byte -- hPutStrLn :: Handle -> ByteString -> IO () hPutStrLn h ps = hPut h ps >> hPut h (L.singleton 0x0a) -- | Write a ByteString to stdout, appending a newline byte+-- putStrLn :: ByteString -> IO () putStrLn = hPutStrLn stdout- -- --------------------------------------------------------------------- -- Internal utilities
Data/ByteString/Lazy/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} #if __GLASGOW_HASKELL__ >= 703 {-# LANGUAGE Unsafe #-}@@ -73,6 +73,7 @@ -- data ByteString = Empty | Chunk {-# UNPACK #-} !S.ByteString ByteString deriving (Typeable)+-- See 'invariant' function later in this module for internal invariants. instance Eq ByteString where (==) = eq@@ -125,8 +126,7 @@ (bs, cs') -> Chunk bs (packChunks (min (n * 2) smallChunkSize) cs') packChars :: [Char] -> ByteString-packChars cs0 =- packChunks 32 cs0+packChars cs0 = packChunks 32 cs0 where packChunks n cs = case S.packUptoLenChars n cs of (bs, []) -> chunk bs Empty@@ -218,9 +218,9 @@ eq _ Empty = False eq (Chunk a as) (Chunk b bs) = case compare (S.length a) (S.length b) of- LT -> a == (S.take (S.length a) b) && eq as (Chunk (S.drop (S.length a) b) bs)- EQ -> a == b && eq as bs- GT -> (S.take (S.length b) a) == b && eq (Chunk (S.drop (S.length b) a) as) bs+ LT -> a == S.take (S.length a) b && eq as (Chunk (S.drop (S.length a) b) bs)+ EQ -> a == b && eq as bs+ GT -> S.take (S.length b) a == b && eq (Chunk (S.drop (S.length b) a) as) bs cmp :: ByteString -> ByteString -> Ordering cmp Empty Empty = EQ
Data/ByteString/Short/Internal.hs view
@@ -149,7 +149,7 @@ mconcat = concat instance NFData ShortByteString where- rnf (SBS {}) = ()+ rnf SBS{} = () instance Show ShortByteString where showsPrec p ps r = showsPrec p (unpackChars ps) r@@ -161,7 +161,7 @@ fromString = packChars instance Data ShortByteString where- gfoldl f z txt = z packBytes `f` (unpackBytes txt)+ gfoldl f z txt = z packBytes `f` unpackBytes txt toConstr _ = error "Data.ByteString.Short.ShortByteString.toConstr" gunfold _ _ = error "Data.ByteString.Short.ShortByteString.gunfold" dataTypeOf _ = mkNoRepType "Data.ByteString.Short.ShortByteString"@@ -320,8 +320,7 @@ -- (5 words per list element, 8 bytes per word, 100 elements = 4000 bytes) unpackAppendCharsLazy :: ShortByteString -> [Char] -> [Char]-unpackAppendCharsLazy sbs cs0 =- go 0 (length sbs) cs0+unpackAppendCharsLazy sbs cs0 = go 0 (length sbs) cs0 where sz = 100 @@ -331,8 +330,7 @@ where remainder = go (off+sz) (len-sz) cs unpackAppendBytesLazy :: ShortByteString -> [Word8] -> [Word8]-unpackAppendBytesLazy sbs ws0 =- go 0 (length sbs) ws0+unpackAppendBytesLazy sbs ws0 = go 0 (length sbs) ws0 where sz = 100 @@ -347,8 +345,7 @@ -- buffer and loops down until we hit the sentinal: unpackAppendCharsStrict :: ShortByteString -> Int -> Int -> [Char] -> [Char]-unpackAppendCharsStrict !sbs off len cs =- go (off-1) (off-1 + len) cs+unpackAppendCharsStrict !sbs off len cs = go (off-1) (off-1 + len) cs where go !sentinal !i !acc | i == sentinal = acc@@ -356,8 +353,7 @@ in go sentinal (i-1) (c:acc) unpackAppendBytesStrict :: ShortByteString -> Int -> Int -> [Word8] -> [Word8]-unpackAppendBytesStrict !sbs off len ws =- go (off-1) (off-1 + len) ws+unpackAppendBytesStrict !sbs off len ws = go (off-1) (off-1 + len) ws where go !sentinal !i !acc | i == sentinal = acc
Data/ByteString/Unsafe.hs view
@@ -260,6 +260,10 @@ -- to guarantee that the @ByteString@ is indeed null terminated. If in -- doubt, use @useAsCString@. --+-- * The memory may freed at any point after the subcomputation+-- terminates, so the pointer to the storage must *not* be used+-- after this.+-- unsafeUseAsCString :: ByteString -> (CString -> IO a) -> IO a unsafeUseAsCString (PS ps s _) ac = withForeignPtr ps $ \p -> ac (castPtr p `plusPtr` s)
bytestring.cabal view
@@ -1,5 +1,5 @@ Name: bytestring-Version: 0.10.8.1+Version: 0.10.8.2 Synopsis: Fast, compact, strict and lazy byte strings with a list interface Description: An efficient compact, immutable byte string type (both strict and lazy)@@ -200,7 +200,7 @@ deepseq, QuickCheck >= 2.4, byteorder == 1.0.*,- dlist >= 0.5 && < 0.8,+ dlist >= 0.5 && < 0.9, directory, mtl >= 2.0 && < 2.3, HUnit,
tests/Properties.hs view
@@ -2313,7 +2313,7 @@ , testProperty "reverse" prop_reverse , testProperty "reverse1" prop_reverse1 , testProperty "reverse2" prop_reverse2- --, testProperty "transpose" prop_transpose+-- , testProperty "transpose" prop_transpose , testProperty "foldl" prop_foldl , testProperty "foldl/reverse" prop_foldl_1 , testProperty "foldr" prop_foldr@@ -2331,7 +2331,7 @@ , testProperty "all" prop_all , testProperty "maximum" prop_maximum , testProperty "minimum" prop_minimum- , testProperty "replicate 1" prop_replicate1+-- , testProperty "replicate 1" prop_replicate1 , testProperty "replicate 2" prop_replicate2 , testProperty "take" prop_take1 , testProperty "drop" prop_drop1