bytestring 0.10.12.1 → 0.11.0.0
raw patch · 21 files changed
+1167/−710 lines, 21 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.ByteString: breakByte :: Word8 -> ByteString -> (ByteString, ByteString)
- Data.ByteString: findSubstring :: ByteString -> ByteString -> Maybe Int
- Data.ByteString: findSubstrings :: ByteString -> ByteString -> [Int]
- Data.ByteString: hPutStrLn :: Handle -> ByteString -> IO ()
- Data.ByteString: putStrLn :: ByteString -> IO ()
- Data.ByteString.Char8: findSubstring :: ByteString -> ByteString -> Maybe Int
- Data.ByteString.Char8: findSubstrings :: ByteString -> ByteString -> [Int]
- Data.ByteString.Internal: PS :: {-# UNPACK #-} !ForeignPtr Word8 -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> ByteString
- Data.ByteString.Internal: inlinePerformIO :: IO a -> a
- Data.ByteString.Internal: unsafeWithForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
- Data.ByteString.Lazy: putStrLn :: ByteString -> IO ()
- Data.ByteString.Lazy.Builder.ASCII: byteStringHexFixed :: ByteString -> Builder
- Data.ByteString.Lazy.Builder.ASCII: lazyByteStringHexFixed :: ByteString -> Builder
+ Data.ByteString: (!?) :: ByteString -> Int -> Maybe Word8
+ Data.ByteString: fromStrict :: ByteString -> ByteString
+ Data.ByteString: indexMaybe :: ByteString -> Int -> Maybe Word8
+ Data.ByteString: toStrict :: ByteString -> ByteString
+ Data.ByteString.Builder.Prim: cstring :: Addr# -> Builder
+ Data.ByteString.Builder.Prim: cstringUtf8 :: Addr# -> Builder
+ Data.ByteString.Char8: (!?) :: ByteString -> Int -> Maybe Char
+ Data.ByteString.Char8: fromStrict :: ByteString -> ByteString
+ Data.ByteString.Char8: indexMaybe :: ByteString -> Int -> Maybe Char
+ Data.ByteString.Char8: toStrict :: ByteString -> ByteString
+ Data.ByteString.Internal: BS :: {-# UNPACK #-} !ForeignPtr Word8 -> {-# UNPACK #-} !Int -> ByteString
+ Data.ByteString.Internal: c_sort :: Ptr Word8 -> CSize -> IO ()
+ Data.ByteString.Internal: fromForeignPtr0 :: ForeignPtr Word8 -> Int -> ByteString
+ Data.ByteString.Internal: pattern PS :: ForeignPtr Word8 -> Int -> Int -> ByteString
+ Data.ByteString.Internal: plusForeignPtr :: () => ForeignPtr a -> Int -> ForeignPtr b
+ Data.ByteString.Internal: toForeignPtr0 :: ByteString -> (ForeignPtr Word8, Int)
+ Data.ByteString.Internal: unsafePackLiteral :: Addr# -> ByteString
+ Data.ByteString.Lazy: (!?) :: ByteString -> Int64 -> Maybe Word8
+ Data.ByteString.Lazy: indexMaybe :: ByteString -> Int64 -> Maybe Word8
+ Data.ByteString.Lazy.Char8: (!?) :: ByteString -> Int64 -> Maybe Char
+ Data.ByteString.Lazy.Char8: indexMaybe :: ByteString -> Int64 -> Maybe Char
+ Data.ByteString.Lazy.Internal: fromStrict :: ByteString -> ByteString
+ Data.ByteString.Lazy.Internal: toStrict :: ByteString -> ByteString
+ Data.ByteString.Short: (!?) :: ShortByteString -> Int -> Maybe Word8
+ Data.ByteString.Short: indexMaybe :: ShortByteString -> Int -> Maybe Word8
+ Data.ByteString.Short.Internal: (!?) :: ShortByteString -> Int -> Maybe Word8
+ Data.ByteString.Short.Internal: indexMaybe :: ShortByteString -> Int -> Maybe Word8
- Data.ByteString.Internal: c_count :: Ptr Word8 -> CULong -> Word8 -> IO CULong
+ Data.ByteString.Internal: c_count :: Ptr Word8 -> CSize -> Word8 -> IO CSize
- Data.ByteString.Internal: c_intersperse :: Ptr Word8 -> Ptr Word8 -> CULong -> Word8 -> IO ()
+ Data.ByteString.Internal: c_intersperse :: Ptr Word8 -> Ptr Word8 -> CSize -> Word8 -> IO ()
- Data.ByteString.Internal: c_maximum :: Ptr Word8 -> CULong -> IO Word8
+ Data.ByteString.Internal: c_maximum :: Ptr Word8 -> CSize -> IO Word8
- Data.ByteString.Internal: c_minimum :: Ptr Word8 -> CULong -> IO Word8
+ Data.ByteString.Internal: c_minimum :: Ptr Word8 -> CSize -> IO Word8
- Data.ByteString.Internal: c_reverse :: Ptr Word8 -> Ptr Word8 -> CULong -> IO ()
+ Data.ByteString.Internal: c_reverse :: Ptr Word8 -> Ptr Word8 -> CSize -> IO ()
Files
- Changelog.md +23/−4
- Data/ByteString.hs +484/−366
- Data/ByteString/Builder.hs +29/−3
- Data/ByteString/Builder/Internal.hs +5/−5
- Data/ByteString/Builder/Prim.hs +64/−4
- Data/ByteString/Builder/Prim/Internal/Base16.hs +1/−1
- Data/ByteString/Char8.hs +82/−30
- Data/ByteString/Internal.hs +164/−77
- Data/ByteString/Lazy.hs +137/−76
- Data/ByteString/Lazy/Builder.hs +0/−11
- Data/ByteString/Lazy/Builder/ASCII.hs +0/−26
- Data/ByteString/Lazy/Builder/Extras.hs +0/−11
- Data/ByteString/Lazy/Char8.hs +24/−1
- Data/ByteString/Lazy/Internal.hs +69/−17
- Data/ByteString/Short.hs +1/−1
- Data/ByteString/Short/Internal.hs +34/−18
- Data/ByteString/Unsafe.hs +20/−20
- README.md +5/−15
- bytestring.cabal +3/−9
- cbits/fpstring.c +15/−8
- include/fpstring.h +7/−7
Changelog.md view
@@ -1,8 +1,27 @@-[0.10.12.1] – January 2021--* [Replace `withForeignPtr` with `unsafeWithForeignPtr` where appropriate](https://github.com/haskell/bytestring/pull/333)+[0.11.0.0] — September 2020+ * [Change internal representation of `ByteString`, removing offset](https://github.com/haskell/bytestring/pull/175)+ * The old `PS` constructor has been turned into a pattern synonym that is available with GHC >= 8.0 for backwards compatibility. Consider adding `if !impl(ghc >=8.0) { build-depends: bytestring < 0.11 }` to packages, which use `PS` and still support GHC < 8.0.+ * [Fill `ForeignPtrContents` of `nullForeignPtr` with `FinalPtr` instead of a bottom](https://github.com/haskell/bytestring/pull/284)+ * While `bytestring-0.11` is compatible with GHC >= 7.0, note that `bytestring < 0.11` will be unbuildable with GHC >= 9.0.+ * [Remove deprecated functions `findSubstring` and `findSubstrings`](https://github.com/haskell/bytestring/pull/181)+ * [Speed up sorting of short strings](https://github.com/haskell/bytestring/pull/267)+ * [Improve handling of literal strings in `Data.ByteString.Builder`](https://github.com/haskell/bytestring/pull/132)+ * [Compute length at compile time for literal strings](https://github.com/haskell/bytestring/pull/191)+ * This improves optimization opportunities for functions that scrutinize the length of a `ByteString`.+ * [Add `indexMaybe` and synonym `(!?)` for indexing that returns `Maybe`](https://github.com/haskell/bytestring/pull/261)+ * [Add rewrite rules for `{take,drop}While ({=,/}= x)`](https://github.com/haskell/bytestring/pull/275)+ * [Add rewrite rules for `any (== x)` and `all (/= x)`](https://github.com/haskell/bytestring/pull/273)+ * [Add rewrite rules for `findInd{ex,ices} (== x)`](https://github.com/haskell/bytestring/pull/270)+ * [Improve folds to pass fewer arguments on each recursive invocation](https://github.com/haskell/bytestring/pull/273)+ * [Improve performance of `findIndices`](https://github.com/haskell/bytestring/pull/270)+ * [Re-export `Data.ByteString.Lazy.{from,to}Strict` from `Data.ByteString`](https://github.com/haskell/bytestring/pull/281)+ * [Remove deprecated modules and functions](https://github.com/haskell/bytestring/pull/286)+ * Use `Data.ByteString.Builder{,.Extra}` instead of `Data.ByteString.Lazy.Builder{,.ASCII,.Extras}`.+ * Use `Data.ByteString.Char8.{,h}putStrLn` instead of `Data.ByteString.{,h}putStrLn` and `Data.ByteString.Lazy.Char8.putStrLn` instead of `Data.ByteString.Char8.putStrLn`.+ * Use `Data.ByteString.break (== x)` instead of `Data.ByteString.breakByte x`.+ * Use `Data.ByteString.Internal.accursedUnutterablePerformIO` instead of `Data.ByteString.Internal.inlinePerformIO`. -[0.10.12.1]: https://github.com/haskell/bytestring/compare/0.10.12.0...0.10.12.1+[0.11.0.0]: https://github.com/haskell/bytestring/compare/0.10.12.0...0.11.0.0 [0.10.12.0] – August 2020
Data/ByteString.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash, UnboxedTuples,- NamedFieldPuns, BangPatterns #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE NamedFieldPuns #-} {-# OPTIONS_HADDOCK prune #-} #if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-}@@ -50,6 +50,8 @@ singleton, -- :: Word8 -> ByteString pack, -- :: [Word8] -> ByteString unpack, -- :: ByteString -> [Word8]+ fromStrict, -- :: ByteString -> Lazy.ByteString+ toStrict, -- :: Lazy.ByteString -> ByteString -- * Basic interface cons, -- :: Word8 -> ByteString -> ByteString@@ -138,8 +140,6 @@ -- ** Search for arbitrary substrings breakSubstring, -- :: ByteString -> ByteString -> (ByteString,ByteString)- findSubstring, -- :: ByteString -> ByteString -> Maybe Int- findSubstrings, -- :: ByteString -> ByteString -> [Int] -- * Searching ByteStrings @@ -154,6 +154,8 @@ -- * Indexing ByteStrings index, -- :: ByteString -> Int -> Word8+ indexMaybe, -- :: ByteString -> Int -> Maybe Word8+ (!?), -- :: ByteString -> Int -> Maybe Word8 elemIndex, -- :: Word8 -> ByteString -> Maybe Int elemIndices, -- :: Word8 -> ByteString -> [Int] elemIndexEnd, -- :: Word8 -> ByteString -> Maybe Int@@ -188,7 +190,6 @@ getLine, -- :: IO ByteString getContents, -- :: IO ByteString putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO () interact, -- :: (ByteString -> ByteString) -> IO () -- ** Files@@ -205,10 +206,6 @@ hPut, -- :: Handle -> ByteString -> IO () hPutNonBlocking, -- :: Handle -> ByteString -> IO ByteString hPutStr, -- :: Handle -> ByteString -> IO ()- hPutStrLn, -- :: Handle -> ByteString -> IO ()-- breakByte- ) where import qualified Prelude as P@@ -233,12 +230,12 @@ #endif import Data.ByteString.Internal+import Data.ByteString.Lazy.Internal (fromStrict, toStrict) import Data.ByteString.Unsafe import qualified Data.List as List import Data.Word (Word8)-import Data.Maybe (isJust) import Control.Exception (IOException, catch, finally, assert, throwIO) import Control.Monad (when)@@ -282,7 +279,6 @@ import Data.Char (ord) import Foreign.Marshal.Utils (copyBytes) -import GHC.Prim (Word#) import GHC.Base (build) import GHC.Word hiding (Word8) @@ -295,7 +291,7 @@ -- | /O(1)/ The empty 'ByteString' empty :: ByteString-empty = PS nullForeignPtr 0 0+empty = BS nullForeignPtr 0 -- | /O(1)/ Convert a 'Word8' into a 'ByteString' singleton :: Word8 -> ByteString@@ -352,13 +348,13 @@ -- | /O(1)/ Test whether a ByteString is empty. null :: ByteString -> Bool-null (PS _ _ l) = assert (l >= 0) $ l <= 0+null (BS _ l) = assert (l >= 0) $ l <= 0 {-# INLINE null #-} -- --------------------------------------------------------------------- -- | /O(1)/ 'length' returns the length of a ByteString as an 'Int'. length :: ByteString -> Int-length (PS _ _ l) = assert (l >= 0) l+length (BS _ l) = assert (l >= 0) l {-# INLINE length #-} ------------------------------------------------------------------------@@ -369,15 +365,15 @@ -- | /O(n)/ 'cons' is analogous to (:) for lists, but of different -- complexity, as it requires making a copy. cons :: Word8 -> ByteString -> ByteString-cons c (PS x s l) = unsafeCreate (l+1) $ \p -> unsafeWithForeignPtr x $ \f -> do+cons c (BS x l) = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do poke p c- memcpy (p `plusPtr` 1) (f `plusPtr` s) (fromIntegral l)+ memcpy (p `plusPtr` 1) f (fromIntegral l) {-# INLINE cons #-} -- | /O(n)/ Append a byte to the end of a 'ByteString' snoc :: ByteString -> Word8 -> ByteString-snoc (PS x s l) c = unsafeCreate (l+1) $ \p -> unsafeWithForeignPtr x $ \f -> do- memcpy p (f `plusPtr` s) (fromIntegral l)+snoc (BS x l) c = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do+ memcpy p f (fromIntegral l) poke (p `plusPtr` l) c {-# INLINE snoc #-} @@ -386,54 +382,54 @@ -- | /O(1)/ Extract the first element of a ByteString, which must be non-empty. -- An exception will be thrown in the case of an empty ByteString. head :: ByteString -> Word8-head (PS x s l)+head (BS x l) | l <= 0 = errorEmptyList "head"- | otherwise = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> peekByteOff p s+ | otherwise = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peek p {-# INLINE head #-} -- | /O(1)/ Extract the elements after the head of a ByteString, which must be non-empty. -- An exception will be thrown in the case of an empty ByteString. tail :: ByteString -> ByteString-tail (PS p s l)+tail (BS p l) | l <= 0 = errorEmptyList "tail"- | otherwise = PS p (s+1) (l-1)+ | otherwise = BS (plusForeignPtr p 1) (l-1) {-# INLINE tail #-} -- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing -- if it is empty. uncons :: ByteString -> Maybe (Word8, ByteString)-uncons (PS x s l)+uncons (BS x l) | l <= 0 = Nothing- | otherwise = Just (accursedUnutterablePerformIO $ unsafeWithForeignPtr x- $ \p -> peekByteOff p s,- PS x (s+1) (l-1))+ | otherwise = Just (accursedUnutterablePerformIO $ withForeignPtr x+ $ \p -> peek p,+ BS (plusForeignPtr x 1) (l-1)) {-# INLINE uncons #-} -- | /O(1)/ Extract the last element of a ByteString, which must be finite and non-empty. -- An exception will be thrown in the case of an empty ByteString. last :: ByteString -> Word8-last ps@(PS x s l)+last ps@(BS x l) | null ps = errorEmptyList "last" | otherwise = accursedUnutterablePerformIO $- unsafeWithForeignPtr x $ \p -> peekByteOff p (s+l-1)+ withForeignPtr x $ \p -> peekByteOff p (l-1) {-# INLINE last #-} -- | /O(1)/ Return all the elements of a 'ByteString' except the last one. -- An exception will be thrown in the case of an empty ByteString. init :: ByteString -> ByteString-init ps@(PS p s l)+init ps@(BS p l) | null ps = errorEmptyList "init"- | otherwise = PS p s (l-1)+ | otherwise = BS p (l-1) {-# INLINE init #-} -- | /O(1)/ Extract the 'init' and 'last' of a ByteString, returning Nothing -- if it is empty. unsnoc :: ByteString -> Maybe (ByteString, Word8)-unsnoc (PS x s l)+unsnoc (BS x l) | l <= 0 = Nothing- | otherwise = Just (PS x s (l-1),+ | otherwise = Just (BS x (l-1), accursedUnutterablePerformIO $- unsafeWithForeignPtr x $ \p -> peekByteOff p (s+l-1))+ withForeignPtr x $ \p -> peekByteOff p (l-1)) {-# INLINE unsnoc #-} -- | /O(n)/ Append two ByteStrings@@ -447,8 +443,8 @@ -- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each -- element of @xs@. map :: (Word8 -> Word8) -> ByteString -> ByteString-map f (PS fp s len) = unsafeDupablePerformIO $ unsafeWithForeignPtr fp $ \a ->- create len $ map_ 0 (a `plusPtr` s)+map f (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a ->+ create len $ map_ 0 a where map_ :: Int -> Ptr Word8 -> Ptr Word8 -> IO () map_ !n !p1 !p2@@ -461,18 +457,18 @@ -- | /O(n)/ 'reverse' @xs@ efficiently returns the elements of @xs@ in reverse order. reverse :: ByteString -> ByteString-reverse (PS x s l) = unsafeCreate l $ \p -> unsafeWithForeignPtr x $ \f ->- c_reverse p (f `plusPtr` s) (fromIntegral l)+reverse (BS x l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->+ c_reverse p f (fromIntegral l) -- | /O(n)/ The 'intersperse' function takes a 'Word8' and a -- 'ByteString' and \`intersperses\' that byte between the elements of -- the 'ByteString'. It is analogous to the intersperse function on -- Lists. intersperse :: Word8 -> ByteString -> ByteString-intersperse c ps@(PS x s l)+intersperse c ps@(BS x l) | length ps < 2 = ps- | otherwise = unsafeCreate (2*l-1) $ \p -> unsafeWithForeignPtr x $ \f ->- c_intersperse p (f `plusPtr` s) (fromIntegral l) c+ | otherwise = unsafeCreate (2*l-1) $ \p -> withForeignPtr x $ \f ->+ c_intersperse p f (fromIntegral l) c -- | The 'transpose' function transposes the rows and columns of its -- 'ByteString' argument.@@ -487,59 +483,62 @@ -- ByteString using the binary operator, from left to right. -- foldl :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl f z (PS fp off len) =- let p = unsafeForeignPtrToPtr fp- in go (p `plusPtr` (off+len-1)) (p `plusPtr` (off-1))- where- -- not tail recursive; traverses array right to left- go !p !q | p == q = z- | otherwise = let !x = accursedUnutterablePerformIO $ do- x' <- peek p- touchForeignPtr fp- return x'- in f (go (p `plusPtr` (-1)) q) x+foldl f z (BS fp len) = go (end `plusPtr` len)+ where+ end = (unsafeForeignPtrToPtr fp) `plusPtr` (-1)+ -- not tail recursive; traverses array right to left+ go !p | p == end = z+ | otherwise = let !x = accursedUnutterablePerformIO $ do+ x' <- peek p+ touchForeignPtr fp+ return x'+ in f (go (p `plusPtr` (-1))) x {-# INLINE foldl #-} -- | 'foldl'' is like 'foldl', but strict in the accumulator. -- foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a-foldl' f v (PS fp off len) =- accursedUnutterablePerformIO $ unsafeWithForeignPtr fp $ \p ->- go v (p `plusPtr` off) (p `plusPtr` (off+len))- where- -- tail recursive; traverses array left to right- go !z !p !q | p == q = return z- | otherwise = do x <- peek p- go (f z x) (p `plusPtr` 1) q+foldl' f v (BS fp len) =+ accursedUnutterablePerformIO $ withForeignPtr fp g+ where+ g ptr = go v ptr+ where+ end = ptr `plusPtr` len+ -- tail recursive; traverses array left to right+ go !z !p | p == end = return z+ | otherwise = do x <- peek p+ go (f z x) (p `plusPtr` 1) {-# INLINE foldl' #-} -- | 'foldr', applied to a binary operator, a starting value -- (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 (PS fp off len) =- let p = unsafeForeignPtrToPtr fp- in go (p `plusPtr` off) (p `plusPtr` (off+len))- where- -- not tail recursive; traverses array left to right- go !p !q | p == q = z- | otherwise = let !x = accursedUnutterablePerformIO $ do- x' <- peek p- touchForeignPtr fp- return x'- in k x (go (p `plusPtr` 1) q)+foldr k z (BS fp len) = go ptr+ where+ ptr = unsafeForeignPtrToPtr fp+ end = ptr `plusPtr` len+ -- not tail recursive; traverses array left to right+ go !p | p == end = z+ | otherwise = let !x = accursedUnutterablePerformIO $ do+ x' <- peek p+ touchForeignPtr fp+ return x'+ in k x (go (p `plusPtr` 1)) {-# INLINE foldr #-} -- | 'foldr'' is like 'foldr', but strict in the accumulator. foldr' :: (Word8 -> a -> a) -> a -> ByteString -> a-foldr' k v (PS fp off len) =- accursedUnutterablePerformIO $ unsafeWithForeignPtr fp $ \p ->- go v (p `plusPtr` (off+len-1)) (p `plusPtr` (off-1))- where- -- tail recursive; traverses array right to left- go !z !p !q | p == q = return z- | otherwise = do x <- peek p- go (k x z) (p `plusPtr` (-1)) q+foldr' k v (BS fp len) =+ accursedUnutterablePerformIO $ withForeignPtr fp g+ where+ g ptr = go v (end `plusPtr` len)+ where+ end = ptr `plusPtr` (-1)+ -- tail recursive; traverses array right to left+ go !z !p | p == end = return z+ | otherwise = do x <- peek p+ go (k x z) (p `plusPtr` (-1)) {-# INLINE foldr' #-} -- | 'foldl1' is a variant of 'foldl' that has no starting value@@ -592,52 +591,95 @@ -- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if -- any element of the 'ByteString' satisfies the predicate. any :: (Word8 -> Bool) -> ByteString -> Bool-any _ (PS _ _ 0) = False-any f (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \ptr ->- go (ptr `plusPtr` s) (ptr `plusPtr` (s+l))- where- go !p !q | p == q = return False- | otherwise = do c <- peek p- if f c then return True- else go (p `plusPtr` 1) q-{-# INLINE any #-}+any _ (BS _ 0) = False+any f (BS x len) = accursedUnutterablePerformIO $ withForeignPtr x g+ where+ g ptr = go ptr+ where+ end = ptr `plusPtr` len+ go !p | p == end = return False+ | otherwise = do c <- peek p+ if f c then return True+ else go (p `plusPtr` 1)+{-# INLINE [1] any #-} +#if MIN_VERSION_base(4,9,0)+{-# RULES+"ByteString specialise any (x ==)" forall x.+ any (x `eqWord8`) = anyByte x+"ByteString specialise any (== x)" forall x.+ any (`eqWord8` x) = anyByte x+ #-}+#else+{-# RULES+"ByteString specialise any (x ==)" forall x.+ any (x ==) = anyByte x+"ByteString specialise any (== x)" forall x.+ any (== x) = anyByte x+ #-}+#endif++-- | Is any element of 'ByteString' equal to c?+anyByte :: Word8 -> ByteString -> Bool+anyByte c (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> do+ q <- memchr p c (fromIntegral l)+ return $! q /= nullPtr+{-# INLINE anyByte #-}+ -- todo fuse -- | /O(n)/ Applied to a predicate and a 'ByteString', 'all' determines -- if all elements of the 'ByteString' satisfy the predicate. all :: (Word8 -> Bool) -> ByteString -> Bool-all _ (PS _ _ 0) = True-all f (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \ptr ->- go (ptr `plusPtr` s) (ptr `plusPtr` (s+l))- where- go !p !q | p == q = return True -- end of list- | otherwise = do c <- peek p- if f c- then go (p `plusPtr` 1) q- else return False-{-# INLINE all #-}+all _ (BS _ 0) = True+all f (BS x len) = accursedUnutterablePerformIO $ withForeignPtr x g+ where+ g ptr = go ptr+ where+ end = ptr `plusPtr` len+ go !p | p == end = return True -- end of list+ | otherwise = do c <- peek p+ if f c+ then go (p `plusPtr` 1)+ else return False+{-# INLINE [1] all #-} +#if MIN_VERSION_base(4,9,0)+{-# RULES+"ByteString specialise all (x /=)" forall x.+ all (x `neWord8`) = not . anyByte x+"ByteString specialise all (/= x)" forall x.+ all (`neWord8` x) = not . anyByte x+ #-}+#else+{-# RULES+"ByteString specialise all (x /=)" forall x.+ all (x /=) = not . anyByte x+"ByteString specialise all (/= x)" forall x.+ all (/= x) = not . anyByte x+ #-}+#endif+ ------------------------------------------------------------------------ -- | /O(n)/ 'maximum' returns the maximum value from a 'ByteString' -- This function will fuse. -- An exception will be thrown in the case of an empty ByteString. maximum :: ByteString -> Word8-maximum xs@(PS x s l)+maximum xs@(BS x l) | null xs = errorEmptyList "maximum"- | otherwise = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- c_maximum (p `plusPtr` s) (fromIntegral l)+ | otherwise = accursedUnutterablePerformIO $ withForeignPtr x $ \p ->+ c_maximum p (fromIntegral l) {-# INLINE maximum #-} -- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString' -- This function will fuse. -- An exception will be thrown in the case of an empty ByteString. minimum :: ByteString -> Word8-minimum xs@(PS x s l)+minimum xs@(BS x l) | null xs = errorEmptyList "minimum"- | otherwise = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- c_minimum (p `plusPtr` s) (fromIntegral l)+ | otherwise = accursedUnutterablePerformIO $ withForeignPtr x $ \p ->+ c_minimum p (fromIntegral l) {-# INLINE minimum #-} ------------------------------------------------------------------------@@ -647,18 +689,20 @@ -- passing an accumulating parameter from left to right, and returning a -- final value of this accumulator together with the new list. mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)-mapAccumL f acc (PS fp o len) = unsafeDupablePerformIO $ unsafeWithForeignPtr fp $ \a -> do+mapAccumL f acc (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> do gp <- mallocByteString len- acc' <- unsafeWithForeignPtr gp $ \p -> mapAccumL_ acc 0 (a `plusPtr` o) p- return (acc', PS gp 0 len)+ acc' <- withForeignPtr gp (go a)+ return (acc', BS gp len) where- mapAccumL_ !s !n !p1 !p2- | n >= len = return s- | otherwise = do- x <- peekByteOff p1 n- let (s', y) = f s x- pokeByteOff p2 n y- mapAccumL_ s' (n+1) p1 p2+ go src dst = mapAccumL_ acc 0+ where+ mapAccumL_ !s !n+ | n >= len = return s+ | otherwise = do+ x <- peekByteOff src n+ let (s', y) = f s x+ pokeByteOff dst n y+ mapAccumL_ s' (n+1) {-# INLINE mapAccumL #-} -- | The 'mapAccumR' function behaves like a combination of 'map' and@@ -666,18 +710,19 @@ -- 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 acc (PS fp o len) = unsafeDupablePerformIO $ unsafeWithForeignPtr fp $ \a -> do+mapAccumR f acc (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> do gp <- mallocByteString len- acc' <- unsafeWithForeignPtr gp $ \p -> mapAccumR_ acc (len-1) (a `plusPtr` o) p- return $! (acc', PS gp 0 len)+ acc' <- withForeignPtr gp (go a)+ return $! (acc', BS gp len) where- mapAccumR_ !s !n !p !q- | n < 0 = return s- | otherwise = do- x <- peekByteOff p n+ go src dst = mapAccumR_ acc (len-1)+ where+ mapAccumR_ !s (-1) = return s+ mapAccumR_ !s !n = do+ x <- peekByteOff src n let (s', y) = f s x- pokeByteOff q n y- mapAccumR_ s' (n-1) p q+ pokeByteOff dst n y+ mapAccumR_ s' (n-1) {-# INLINE mapAccumR #-} -- ---------------------------------------------------------------------@@ -690,22 +735,32 @@ -- -- Note that ----- > last (scanl f z xs) == foldl f z xs.+-- > head (scanl f z xs) == z+-- > last (scanl f z xs) == foldl f z xs ---scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString--scanl f v (PS fp s len) = unsafeDupablePerformIO $ unsafeWithForeignPtr fp $ \a ->+scanl+ :: (Word8 -> Word8 -> Word8)+ -- ^ accumulator -> element -> new accumulator+ -> Word8+ -- ^ starting value of accumulator+ -> ByteString+ -- ^ input of length n+ -> ByteString+ -- ^ output of length n+1+scanl f v (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> create (len+1) $ \q -> do poke q v- scanl_ v 0 (a `plusPtr` s) (q `plusPtr` 1)+ go a (q `plusPtr` 1) where- scanl_ !z !n !p !q- | n >= len = return ()- | otherwise = do- x <- peekByteOff p n- let z' = f z x- pokeByteOff q n z'- scanl_ z' (n+1) p q+ go src dst = scanl_ v 0+ where+ scanl_ !z !n+ | n >= len = return ()+ | otherwise = do+ x <- peekByteOff src n+ let z' = f z x+ pokeByteOff dst n z'+ scanl_ z' (n+1) {-# INLINE scanl #-} -- n.b. haskell's List scan returns a list one bigger than the@@ -722,20 +777,39 @@ | otherwise = scanl f (unsafeHead ps) (unsafeTail ps) {-# INLINE scanl1 #-} --- | scanr is the right-to-left dual of scanl.-scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString-scanr f v (PS fp s len) = unsafeDupablePerformIO $ unsafeWithForeignPtr fp $ \a ->+-- | 'scanr' is similar to 'foldr', but returns a list of successive+-- reduced values from the right.+--+-- > scanr f z [..., x{n-1}, xn] == [..., x{n-1} `f` (xn `f` z), xn `f` z, z]+--+-- Note that+--+-- > head (scanr f z xs) == foldr f z xs+-- > last (scanr f z xs) == z+--+scanr+ :: (Word8 -> Word8 -> Word8)+ -- ^ element -> accumulator -> new accumulator+ -> Word8+ -- ^ starting value of accumulator+ -> ByteString+ -- ^ input of length n+ -> ByteString+ -- ^ output of length n+1+scanr f v (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> create (len+1) $ \q -> do poke (q `plusPtr` len) v- scanr_ v (len-1) (a `plusPtr` s) q+ go a q where- scanr_ !z !n !p !q- | n < 0 = return ()- | otherwise = do- x <- peekByteOff p n- let z' = f x z- pokeByteOff q n z'- scanr_ z' (n-1) p q+ go p q = scanr_ v (len-1)+ where+ scanr_ !z !n+ | n < 0 = return ()+ | otherwise = do+ x <- peekByteOff p n+ let z' = f x z+ pokeByteOff q n z'+ scanr_ z' (n-1) {-# INLINE scanr #-} -- | 'scanr1' is a variant of 'scanr' that has no starting value argument.@@ -753,12 +827,13 @@ -- -- > replicate w c = unfoldr w (\u -> Just (u,u)) c ----- This implemenation uses @memset(3)@+-- This implementation uses @memset(3)@ replicate :: Int -> Word8 -> ByteString replicate w c | w <= 0 = empty | otherwise = unsafeCreate w $ \ptr -> memset ptr c (fromIntegral w) >> return ()+{-# INLINE replicate #-} -- | /O(n)/, where /n/ is the length of the result. The 'unfoldr' -- function is analogous to the List \'unfoldr\'. 'unfoldr' builds a@@ -808,52 +883,107 @@ -- | /O(1)/ 'take' @n@, applied to a ByteString @xs@, returns the prefix -- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@. take :: Int -> ByteString -> ByteString-take n ps@(PS x s l)+take n ps@(BS x l) | n <= 0 = empty | n >= l = ps- | otherwise = PS x s n+ | otherwise = BS x n {-# INLINE take #-} -- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@ -- elements, or @[]@ if @n > 'length' xs@. drop :: Int -> ByteString -> ByteString-drop n ps@(PS x s l)+drop n ps@(BS x l) | n <= 0 = ps | n >= l = empty- | otherwise = PS x (s+n) (l-n)+ | otherwise = BS (plusForeignPtr x n) (l-n) {-# INLINE drop #-} -- | /O(1)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@. splitAt :: Int -> ByteString -> (ByteString, ByteString)-splitAt n ps@(PS x s l)+splitAt n ps@(BS x l) | n <= 0 = (empty, ps) | n >= l = (ps, empty)- | otherwise = (PS x s n, PS x (s+n) (l-n))+ | otherwise = (BS x n, BS (plusForeignPtr x n) (l-n)) {-# INLINE splitAt #-} --- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.+-- | Similar to 'P.takeWhile',+-- returns the longest (possibly empty) prefix of elements+-- satisfying the predicate. takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString takeWhile f ps = unsafeTake (findIndexOrEnd (not . f) ps) ps-{-# INLINE takeWhile #-}+{-# INLINE [1] takeWhile #-} --- | 'takeWhileEnd', applied to a predicate @p@ and a ByteString @xs@, returns--- the longest suffix (possibly empty) of @xs@ of elements that satisfy @p@.+#if MIN_VERSION_base(4,9,0)+{-# RULES+"ByteString specialise takeWhile (x /=)" forall x.+ takeWhile (x `neWord8`) = fst . breakByte x+"ByteString specialise takeWhile (/= x)" forall x.+ takeWhile (`neWord8` x) = fst . breakByte x+"ByteString specialise takeWhile (x ==)" forall x.+ takeWhile (x `eqWord8`) = fst . spanByte x+"ByteString specialise takeWhile (== x)" forall x.+ takeWhile (`eqWord8` x) = fst . spanByte x+ #-}+#else+{-# RULES+"ByteString specialise takeWhile (x /=)" forall x.+ takeWhile (x /=) = fst . breakByte x+"ByteString specialise takeWhile (/= x)" forall x.+ takeWhile (/= x) = fst . breakByte x+"ByteString specialise takeWhile (x ==)" forall x.+ takeWhile (x ==) = fst . spanByte x+"ByteString specialise takeWhile (== x)" forall x.+ takeWhile (== x) = fst . spanByte x+ #-}+#endif++-- | Returns the longest (possibly empty) suffix of elements+-- satisfying the predicate. --+-- @'takeWhileEnd' p@ is equivalent to @'reverse' . 'takeWhile' p . 'reverse'@.+-- -- @since 0.10.12.0 takeWhileEnd :: (Word8 -> Bool) -> ByteString -> ByteString takeWhileEnd f ps = unsafeDrop (findFromEndUntil (not . f) ps) ps {-# INLINE takeWhileEnd #-} --- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.+-- | Similar to 'P.dropWhile',+-- drops the longest (possibly empty) prefix of elements+-- satisfying the predicate and returns the remainder. dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString dropWhile f ps = unsafeDrop (findIndexOrEnd (not . f) ps) ps-{-# INLINE dropWhile #-}+{-# INLINE [1] dropWhile #-} --- | 'dropWhileEnd' @p xs@ returns the prefix remaining after 'takeWhileEnd' @p--- xs@.+#if MIN_VERSION_base(4,9,0)+{-# RULES+"ByteString specialise dropWhile (x /=)" forall x.+ dropWhile (x `neWord8`) = snd . breakByte x+"ByteString specialise dropWhile (/= x)" forall x.+ dropWhile (`neWord8` x) = snd . breakByte x+"ByteString specialise dropWhile (x ==)" forall x.+ dropWhile (x `eqWord8`) = snd . spanByte x+"ByteString specialise dropWhile (== x)" forall x.+ dropWhile (`eqWord8` x) = snd . spanByte x+ #-}+#else+{-# RULES+"ByteString specialise dropWhile (x /=)" forall x.+ dropWhile (x /=) = snd . breakByte x+"ByteString specialise dropWhile (/= x)" forall x.+ dropWhile (/= x) = snd . breakByte x+"ByteString specialise dropWhile (x ==)" forall x.+ dropWhile (x ==) = snd . spanByte x+"ByteString specialise dropWhile (== x)" forall x.+ dropWhile (== x) = snd . spanByte x+ #-}+#endif++-- | Similar to 'P.dropWhileEnd',+-- drops the longest (possibly empty) suffix of elements+-- satisfying the predicate and returns the remainder. --+-- @'dropWhileEnd' p@ is equivalent to @'reverse' . 'dropWhile' p . 'reverse'@.+-- -- @since 0.10.12.0 dropWhileEnd :: (Word8 -> Bool) -> ByteString -> ByteString dropWhileEnd f ps = unsafeTake (findFromEndUntil (not . f) ps) ps@@ -861,8 +991,12 @@ -- instead of findIndexOrEnd, we could use memchr here. --- | 'break' @p@ is equivalent to @'span' ('not' . p)@.+-- | Similar to 'P.break',+-- returns the longest (possibly empty) prefix of elements which __do not__+-- satisfy the predicate and the remainder of the string. --+-- 'break' @p@ is equivalent to @'span' (not . p)@ and to @('takeWhile' (not . p) &&& 'dropWhile' (not . p))@.+-- -- Under GHC, a rewrite rule will transform break (==) into a -- call to the specialised breakByte: --@@ -903,16 +1037,21 @@ Nothing -> (p,empty) Just n -> (unsafeTake n p, unsafeDrop n p) {-# INLINE breakByte #-}-{-# DEPRECATED breakByte "It is an internal function and should never have been exported. Use 'break (== x)' instead. (There are rewrite rules that handle this special case of 'break'.)" #-} --- | 'breakEnd' behaves like 'break' but from the end of the 'ByteString'+-- | Returns the longest (possibly empty) suffix of elements which __do not__+-- satisfy the predicate and the remainder of the string. ----- breakEnd p == spanEnd (not.p)+-- 'breakEnd' @p@ is equivalent to @'spanEnd' (not . p)@ and to @('takeWhileEnd' (not . p) &&& 'dropWhileEnd' (not . p))@.+-- breakEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString) breakEnd p ps = splitAt (findFromEndUntil p ps) ps --- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@+-- | Similar to 'P.span',+-- returns the longest (possibly empty) prefix of elements+-- satisfying the predicate and the remainder of the string.+--+-- 'span' @p@ is equivalent to @'break' (not . p)@ and to @('takeWhile' p &&& 'dropWhile' p)@.+-- span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString) span p ps = break (not . p) ps {-# INLINE [1] span #-}@@ -924,16 +1063,16 @@ -- > span (==99) "abcd" == spanByte 99 "abcd" -- fromEnum 'c' == 99 -- spanByte :: Word8 -> ByteString -> (ByteString, ByteString)-spanByte c ps@(PS x s l) =- accursedUnutterablePerformIO $- unsafeWithForeignPtr x $ \p ->- go (p `plusPtr` s) 0+spanByte c ps@(BS x l) =+ accursedUnutterablePerformIO $ withForeignPtr x g where- go !p !i | i >= l = return (ps, empty)- | otherwise = do c' <- peekByteOff p i- if c /= c'- then return (unsafeTake i ps, unsafeDrop i ps)- else go p (i+1)+ g p = go 0+ where+ go !i | i >= l = return (ps, empty)+ | otherwise = do c' <- peekByteOff p i+ if c /= c'+ then return (unsafeTake i ps, unsafeDrop i ps)+ else go (i+1) {-# INLINE spanByte #-} -- See bytestring #70@@ -953,16 +1092,20 @@ #-} #endif --- | 'spanEnd' behaves like 'span' but from the end of the 'ByteString'.+-- | Returns the longest (possibly empty) suffix of elements+-- satisfying the predicate and the remainder of the string.+--+-- 'spanEnd' @p@ is equivalent to @'breakEnd' (not . p)@ and to @('takeWhileEnd' p &&& 'dropWhileEnd' p)@.+-- -- We have ----- > spanEnd (not.isSpace) "x y z" == ("x y ","z")+-- > spanEnd (not . isSpace) "x y z" == ("x y ", "z") -- -- and -- -- > spanEnd (not . isSpace) ps -- > ==--- > let (x,y) = span (not.isSpace) (reverse ps) in (reverse y, reverse x)+-- > let (x, y) = span (not . isSpace) (reverse ps) in (reverse y, reverse x) -- spanEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString) spanEnd p ps = splitAt (findFromEndUntil (not.p) ps) ps@@ -973,32 +1116,30 @@ -- separators result in an empty component in the output. eg. -- -- > splitWith (==97) "aabbaca" == ["","","bb","c",""] -- fromEnum 'a' == 97--- > splitWith (==97) [] == []+-- > splitWith undefined "" == [] -- and not [""] -- splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]-splitWith _pred (PS _ _ 0) = []-splitWith pred_ (PS fp off len) = splitWith0 pred# off len fp- where pred# c# = pred_ (W8# c#)-- splitWith0 !pred' !off' !len' !fp' =+splitWith _ (BS _ 0) = []+splitWith predicate (BS fp len) = splitWith0 0 len fp+ where splitWith0 !off' !len' !fp' = accursedUnutterablePerformIO $- unsafeWithForeignPtr fp $ \p ->- splitLoop pred' p 0 off' len' fp'+ withForeignPtr fp $ \p ->+ splitLoop p 0 off' len' fp' - splitLoop :: (Word# -> Bool)- -> Ptr Word8+ splitLoop :: Ptr Word8 -> Int -> Int -> Int -> ForeignPtr Word8 -> IO [ByteString]-- splitLoop pred' p idx' off' len' fp'- | idx' >= len' = return [PS fp' off' idx']- | otherwise = do- w <- peekElemOff p (off'+idx')- if pred' (case w of W8# w# -> w#)- then return (PS fp' off' idx' :- splitWith0 pred' (off'+idx'+1) (len'-idx'-1) fp')- else splitLoop pred' p (idx'+1) off' len' fp'+ splitLoop p idx2 off' len' fp' = go idx2+ where+ go idx'+ | idx' >= len' = return [BS (plusForeignPtr fp' off') idx']+ | otherwise = do+ w <- peekElemOff p (off'+idx')+ if predicate w+ then return (BS (plusForeignPtr fp' off') idx' :+ splitWith0 (off'+idx'+1) (len'-idx'-1) fp')+ else go (idx'+1) {-# INLINE splitWith #-} -- | /O(n)/ Break a 'ByteString' into pieces separated by the byte@@ -1007,6 +1148,7 @@ -- > split 10 "a\nb\nd\ne" == ["a","b","d","e"] -- fromEnum '\n' == 10 -- > split 97 "aXaXaXa" == ["","X","X","X",""] -- fromEnum 'a' == 97 -- > split 120 "x" == ["",""] -- fromEnum 'x' == 120+-- > split undefined "" == [] -- and not [""] -- -- and --@@ -1018,18 +1160,18 @@ -- are slices of the original. -- split :: Word8 -> ByteString -> [ByteString]-split _ (PS _ _ 0) = []-split w (PS x s l) = loop 0+split _ (BS _ 0) = []+split w (BS x l) = loop 0 where loop !n =- let q = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- memchr (p `plusPtr` (s+n))+ let q = accursedUnutterablePerformIO $ withForeignPtr x $ \p ->+ memchr (p `plusPtr` n) w (fromIntegral (l-n)) in if q == nullPtr- then [PS x (s+n) (l-n)]- else let i = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- return (q `minusPtr` (p `plusPtr` s))- in PS x (s+n) (i-n) : loop (i+1)+ then [BS (plusForeignPtr x n) (l-n)]+ else let i = accursedUnutterablePerformIO $ withForeignPtr x $ \p ->+ return (q `minusPtr` p)+ in BS (plusForeignPtr x n) (i-n) : loop (i+1) {-# INLINE split #-} @@ -1075,12 +1217,12 @@ -- with a char. Around 4 times faster than the generalised join. -- intercalateWithByte :: Word8 -> ByteString -> ByteString -> ByteString-intercalateWithByte c f@(PS ffp s l) g@(PS fgp t m) = unsafeCreate len $ \ptr ->- unsafeWithForeignPtr ffp $ \fp ->- unsafeWithForeignPtr fgp $ \gp -> do- memcpy ptr (fp `plusPtr` s) (fromIntegral l)+intercalateWithByte c f@(BS ffp l) g@(BS fgp m) = unsafeCreate len $ \ptr ->+ withForeignPtr ffp $ \fp ->+ withForeignPtr fgp $ \gp -> do+ memcpy ptr fp (fromIntegral l) poke (ptr `plusPtr` l) c- memcpy (ptr `plusPtr` (l + 1)) (gp `plusPtr` t) (fromIntegral m)+ memcpy (ptr `plusPtr` (l + 1)) gp (fromIntegral m) where len = length f + length g + 1 {-# INLINE intercalateWithByte #-}@@ -1097,15 +1239,35 @@ | otherwise = ps `unsafeIndex` n {-# INLINE index #-} +-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+indexMaybe :: ByteString -> Int -> Maybe Word8+indexMaybe ps n+ | n < 0 = Nothing+ | n >= length ps = Nothing+ | otherwise = Just $! ps `unsafeIndex` n+{-# INLINE indexMaybe #-}++-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+(!?) :: ByteString -> Int -> Maybe Word8+(!?) = indexMaybe+{-# INLINE (!?) #-}+ -- | /O(n)/ The 'elemIndex' function returns the index of the first -- element in the given 'ByteString' which is equal to the query -- element, or 'Nothing' if there is no such element. -- This implementation uses memchr(3). elemIndex :: Word8 -> ByteString -> Maybe Int-elemIndex c (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> do- let p' = p `plusPtr` s- q <- memchr p' c (fromIntegral l)- return $! if q == nullPtr then Nothing else Just $! q `minusPtr` p'+elemIndex c (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> do+ q <- memchr p c (fromIntegral l)+ return $! if q == nullPtr then Nothing else Just $! q `minusPtr` p {-# INLINE elemIndex #-} -- | /O(n)/ The 'elemIndexEnd' function returns the last index of the@@ -1124,16 +1286,14 @@ -- the indices of all elements equal to the query element, in ascending order. -- This implementation uses memchr(3). elemIndices :: Word8 -> ByteString -> [Int]-elemIndices w (PS x s l) = loop 0+elemIndices w (BS x l) = loop 0 where- loop !n = let q = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- memchr (p `plusPtr` (n+s))- w (fromIntegral (l - n))- in if q == nullPtr- then []- else let i = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- return (q `minusPtr` (p `plusPtr` s))- in i : loop (i+1)+ loop !n = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> do+ q <- memchr (p `plusPtr` n) w (fromIntegral (l - n))+ if q == nullPtr+ then return []+ else let !i = q `minusPtr` p+ in return $ i : loop (i + 1) {-# INLINE elemIndices #-} -- | count returns the number of times its argument appears in the ByteString@@ -1142,22 +1302,22 @@ -- -- But more efficiently than using length on the intermediate list. count :: Word8 -> ByteString -> Int-count w (PS x s m) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p ->- fmap fromIntegral $ c_count (p `plusPtr` s) (fromIntegral m) w+count w (BS x m) = accursedUnutterablePerformIO $ withForeignPtr x $ \p ->+ fmap fromIntegral $ c_count p (fromIntegral m) w {-# INLINE count #-} -- | /O(n)/ The 'findIndex' function takes a predicate and a 'ByteString' and -- returns the index of the first element in the ByteString -- satisfying the predicate. findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int-findIndex k (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr x $ \f -> go (f `plusPtr` s) 0+findIndex k (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \f -> go f 0 where go !ptr !n | n >= l = return Nothing | otherwise = do w <- peek ptr if k w then return (Just n) else go (ptr `plusPtr` 1) (n+1)-{-# INLINE findIndex #-}+{-# INLINE [1] findIndex #-} -- | /O(n)/ The 'findIndexEnd' function takes a predicate and a 'ByteString' and -- returns the index of the last element in the ByteString@@ -1165,7 +1325,7 @@ -- -- @since 0.10.12.0 findIndexEnd :: (Word8 -> Bool) -> ByteString -> Maybe Int-findIndexEnd k (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr x $ \ f -> go (f `plusPtr` s) (l-1)+findIndexEnd k (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \ f -> go f (l-1) where go !ptr !n | n < 0 = return Nothing | otherwise = do w <- peekByteOff ptr n@@ -1179,10 +1339,30 @@ findIndices :: (Word8 -> Bool) -> ByteString -> [Int] findIndices p ps = loop 0 ps where- loop !n !qs | null qs = []- | p (unsafeHead qs) = n : loop (n+1) (unsafeTail qs)- | otherwise = loop (n+1) (unsafeTail qs)+ loop !n !qs = case findIndex p qs of+ Just !i ->+ let !j = n+i+ in j : loop (j+1) (unsafeDrop (i+1) qs)+ Nothing -> []+{-# INLINE [1] findIndices #-} ++#if MIN_VERSION_base(4,9,0)+{-# RULES+"ByteString specialise findIndex (x ==)" forall x. findIndex (x`eqWord8`) = elemIndex x+"ByteString specialise findIndex (== x)" forall x. findIndex (`eqWord8`x) = elemIndex x+"ByteString specialise findIndices (x ==)" forall x. findIndices (x`eqWord8`) = elemIndices x+"ByteString specialise findIndices (== x)" forall x. findIndices (`eqWord8`x) = elemIndices x+ #-}+#else+{-# RULES+"ByteString specialise findIndex (x ==)" forall x. findIndex (x==) = elemIndex x+"ByteString specialise findIndex (== x)" forall x. findIndex (==x) = elemIndex x+"ByteString specialise findIndices (x ==)" forall x. findIndices (x==) = elemIndices x+"ByteString specialise findIndices (== x)" forall x. findIndices (==x) = elemIndices x+ #-}+#endif+ -- --------------------------------------------------------------------- -- Searching ByteStrings @@ -1200,18 +1380,21 @@ -- returns a ByteString containing those characters that satisfy the -- predicate. filter :: (Word8 -> Bool) -> ByteString -> ByteString-filter k ps@(PS x s l)+filter k ps@(BS x l) | null ps = ps | otherwise = unsafePerformIO $ createAndTrim l $ \p -> withForeignPtr x $ \f -> do- t <- go (f `plusPtr` s) p (f `plusPtr` (s + l))+ t <- go' f p return $! t `minusPtr` p -- actual length- where- go !f !t !end | f == end = return t- | otherwise = do- w <- peek f- if k w- then poke t w >> go (f `plusPtr` 1) (t `plusPtr` 1) end- else go (f `plusPtr` 1) t end+ where+ go' pf pt = go pf pt+ where+ end = pf `plusPtr` l+ go !f !t | f == end = return t+ | otherwise = do+ w <- peek f+ if k w+ then poke t w >> go (f `plusPtr` 1) (t `plusPtr` 1)+ else go (f `plusPtr` 1) t {-# INLINE filter #-} {-@@ -1263,8 +1446,8 @@ mid <- sep 0 p end rev mid end let i = mid `minusPtr` p- return (PS fp' 0 i,- PS fp' i (len - i))+ return (BS fp' i,+ BS (plusForeignPtr fp' i) (len - i)) where len = length s incr = (`plusPtr` 1)@@ -1293,12 +1476,12 @@ -- |/O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True' -- if the first is a prefix of the second. isPrefixOf :: ByteString -> ByteString -> Bool-isPrefixOf (PS x1 s1 l1) (PS x2 s2 l2)+isPrefixOf (BS x1 l1) (BS x2 l2) | l1 == 0 = True | l2 < l1 = False- | otherwise = accursedUnutterablePerformIO $ unsafeWithForeignPtr x1 $ \p1 ->- unsafeWithForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral l1)+ | otherwise = accursedUnutterablePerformIO $ withForeignPtr x1 $ \p1 ->+ withForeignPtr x2 $ \p2 -> do+ i <- memcmp p1 p2 (fromIntegral l1) return $! i == 0 -- | /O(n)/ The 'stripPrefix' function takes two ByteStrings and returns 'Just'@@ -1307,7 +1490,7 @@ -- -- @since 0.10.8.0 stripPrefix :: ByteString -> ByteString -> Maybe ByteString-stripPrefix bs1@(PS _ _ l1) bs2+stripPrefix bs1@(BS _ l1) bs2 | bs1 `isPrefixOf` bs2 = Just (unsafeDrop l1 bs2) | otherwise = Nothing @@ -1318,29 +1501,28 @@ -- -- > isSuffixOf x y == reverse x `isPrefixOf` reverse y ----- However, the real implemenation uses memcmp to compare the end of the+-- However, the real implementation uses memcmp to compare the end of the -- string only, with no reverse required.. isSuffixOf :: ByteString -> ByteString -> Bool-isSuffixOf (PS x1 s1 l1) (PS x2 s2 l2)+isSuffixOf (BS x1 l1) (BS x2 l2) | l1 == 0 = True | l2 < l1 = False- | otherwise = accursedUnutterablePerformIO $ unsafeWithForeignPtr x1 $ \p1 ->- unsafeWithForeignPtr x2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2 `plusPtr` (l2 - l1)) (fromIntegral l1)+ | otherwise = accursedUnutterablePerformIO $ withForeignPtr x1 $ \p1 ->+ withForeignPtr x2 $ \p2 -> do+ i <- memcmp p1 (p2 `plusPtr` (l2 - l1)) (fromIntegral l1) return $! i == 0 -- | /O(n)/ The 'stripSuffix' function takes two ByteStrings and returns 'Just' -- the remainder of the second iff the first is its suffix, and otherwise -- 'Nothing'. stripSuffix :: ByteString -> ByteString -> Maybe ByteString-stripSuffix bs1@(PS _ _ l1) bs2@(PS _ _ l2)+stripSuffix bs1@(BS _ l1) bs2@(BS _ l2) | bs1 `isSuffixOf` bs2 = Just (unsafeTake (l2 - l1) bs2) | otherwise = Nothing --- | Check whether one string is a substring of another. @isInfixOf--- p s@ is equivalent to @not (null (findSubstrings p s))@.+-- | Check whether one string is a substring of another. isInfixOf :: ByteString -> ByteString -> Bool-isInfixOf p s = isJust (findSubstring p s)+isInfixOf p s = null p || not (null $ snd $ breakSubstring p s) -- | Break a string on a substring, returning a pair of the part of the -- string prior to the match, and the rest of the string.@@ -1349,14 +1531,6 @@ -- -- > break (== c) l == breakSubstring (singleton c) l ----- and:------ > findSubstring s l ==--- > if null s then Just 0--- > else case breakSubstring s l of--- > (x,y) | null y -> Nothing--- > | otherwise -> Just (length x)--- -- For example, to tokenise a string, dropping delimiters: -- -- > tokenise x y = h : if null t then [] else tokenise x (drop (length x) t)@@ -1426,51 +1600,6 @@ w' = mask .&. ((w `shiftL` 8) .|. b) {-# INLINE shift #-} --- | Get the first index of a substring in another string,--- or 'Nothing' if the string is not found.--- @findSubstring p s@ is equivalent to @listToMaybe (findSubstrings p s)@.-findSubstring :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to seach in.- -> Maybe Int-findSubstring pat src- | null pat && null src = Just 0- | null b = Nothing- | otherwise = Just (length a)- where (a, b) = breakSubstring pat src--{-# DEPRECATED findSubstring "findSubstring is deprecated in favour of breakSubstring." #-}---- | Find the indices of all non-overlapping occurences of a substring in a--- string.------ Note, prior to @0.10.6.0@ this function returned the indices of all--- possibly-overlapping matches.-findSubstrings :: ByteString -- ^ String to search for.- -> ByteString -- ^ String to seach in.- -> [Int]-findSubstrings pat src- | null pat = [0 .. ls]- | otherwise = search 0- where- lp = length pat- ls = length src- search !n- | (n > ls - lp) || null b = []- | otherwise = let k = n + length a- in k : search (k + lp)- where- (a, b) = breakSubstring pat (unsafeDrop n src)---- In--- [0.10.6.0](<https://github.com/haskell/bytestring/commit/2160e091e215fecc9177d55a37cd50fc253ba86a?w=1>)--- 'findSubstrings' was refactored to call an improved 'breakString'--- implementation, but the refactored code no longer matches overlapping--- strings. The behaviour change appears to be inadvertent, but the function--- had already been deprecated for more than seven years. At this time--- (@0.10.10.1@), the deprecation was twelve years in the past.----{-# DEPRECATED findSubstrings "findSubstrings is deprecated in favour of breakSubstring." #-}- -- --------------------------------------------------------------------- -- Zipping @@ -1500,19 +1629,21 @@ -- performed on the result of zipWith. -- zipWith' :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString-zipWith' f (PS fp s l) (PS fq t m) = unsafeDupablePerformIO $+zipWith' f (BS fp l) (BS fq m) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> withForeignPtr fq $ \b ->- create len $ zipWith_ 0 (a `plusPtr` s) (b `plusPtr` t)+ create len $ go a b where- zipWith_ :: Int -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> IO ()- zipWith_ !n !p1 !p2 !r- | n >= len = return ()- | otherwise = do- x <- peekByteOff p1 n- y <- peekByteOff p2 n- pokeByteOff r n (f x y)- zipWith_ (n+1) p1 p2 r+ go p1 p2 = zipWith_ 0+ where+ zipWith_ :: Int -> Ptr Word8 -> IO ()+ zipWith_ !n !r+ | n >= len = return ()+ | otherwise = do+ x <- peekByteOff p1 n+ y <- peekByteOff p2 n+ pokeByteOff r n (f x y)+ zipWith_ (n+1) r len = min l m {-# INLINE zipWith' #-}@@ -1533,24 +1664,29 @@ -- | /O(n)/ Return all initial segments of the given 'ByteString', shortest first. inits :: ByteString -> [ByteString]-inits (PS x s l) = [PS x s n | n <- [0..l]]+inits (BS x l) = [BS x n | n <- [0..l]] -- | /O(n)/ Return all final segments of the given 'ByteString', longest first. tails :: ByteString -> [ByteString] tails p | null p = [empty] | otherwise = p : tails (unsafeTail p) --- less efficent spacewise: tails (PS x s l) = [PS x (s+n) (l-n) | n <- [0..l]]+-- less efficent spacewise: tails (BS x l) = [BS (plusForeignPtr x n) (l-n) | n <- [0..l]] -- --------------------------------------------------------------------- -- ** Ordered 'ByteString's -- | /O(n)/ Sort a ByteString efficiently, using counting sort. sort :: ByteString -> ByteString-sort (PS input s l) = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do+sort (BS input l)+ -- qsort outperforms counting sort for small arrays+ | l <= 20 = unsafeCreate l $ \ptr -> withForeignPtr input $ \inp -> do+ memcpy ptr inp (fromIntegral l)+ c_sort ptr (fromIntegral l)+ | otherwise = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do _ <- memset (castPtr arr) 0 (256 * fromIntegral (sizeOf (undefined :: CSize)))- unsafeWithForeignPtr input (\x -> countOccurrences arr (x `plusPtr` s) l)+ withForeignPtr input (\x -> countOccurrences arr x l) let go 256 !_ = return () go i !ptr = do n <- peekElemOff arr i@@ -1558,9 +1694,8 @@ go (i + 1) (ptr `plusPtr` fromIntegral n) go 0 p where- -- | Count the number of occurrences of each byte.+ -- Count the number of occurrences of each byte. -- Used by 'sort'- -- countOccurrences :: Ptr CSize -> Ptr Word8 -> Int -> IO () countOccurrences !counts !str !len = go 0 where@@ -1579,10 +1714,10 @@ -- 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 =+useAsCString (BS fp l) action = allocaBytes (l+1) $ \buf -> withForeignPtr fp $ \p -> do- memcpy buf (p `plusPtr` o) (fromIntegral l)+ memcpy buf p (fromIntegral l) pokeByteOff buf l (0::Word8) action (castPtr buf) @@ -1590,7 +1725,7 @@ -- 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)+useAsCStringLen p@(BS _ l) f = useAsCString p $ \cstr -> f (cstr,l) ------------------------------------------------------------------------ @@ -1622,8 +1757,8 @@ -- is needed in the rest of the program. -- copy :: ByteString -> ByteString-copy (PS x s l) = unsafeCreate l $ \p -> unsafeWithForeignPtr x $ \f ->- memcpy p (f `plusPtr` s) (fromIntegral l)+copy (BS x l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->+ memcpy p f (fromIntegral l) -- --------------------------------------------------------------------- -- Line IO@@ -1696,8 +1831,8 @@ -- | Outputs a 'ByteString' to the specified 'Handle'. hPut :: Handle -> ByteString -> IO ()-hPut _ (PS _ _ 0) = return ()-hPut h (PS ps s l) = unsafeWithForeignPtr ps $ \p-> hPutBuf h (p `plusPtr` s) l+hPut _ (BS _ 0) = return ()+hPut h (BS ps l) = withForeignPtr ps $ \p-> hPutBuf h p l -- | Similar to 'hPut' except that it will never block. Instead it returns -- any tail that did not get written. This tail may be 'empty' in the case that@@ -1708,35 +1843,18 @@ -- function does not work correctly; it behaves identically to 'hPut'. -- hPutNonBlocking :: Handle -> ByteString -> IO ByteString-hPutNonBlocking h bs@(PS ps s l) = do- bytesWritten <- unsafeWithForeignPtr ps $ \p-> hPutBufNonBlocking h (p `plusPtr` s) l+hPutNonBlocking h bs@(BS ps l) = do+ bytesWritten <- withForeignPtr ps $ \p-> hPutBufNonBlocking h p l return $! drop bytesWritten bs -- | A synonym for @hPut@, for compatibility hPutStr :: Handle -> ByteString -> IO () hPutStr = hPut --- | Write a ByteString to a handle, appending a newline byte-hPutStrLn :: Handle -> ByteString -> IO ()-hPutStrLn h ps- | length ps < 1024 = hPut h (ps `snoc` 0x0a)- | otherwise = hPut h ps >> hPut h (singleton (0x0a)) -- don't copy- -- | Write a ByteString to stdout putStr :: ByteString -> IO () putStr = hPut stdout --- | Write a ByteString to stdout, appending a newline byte-putStrLn :: ByteString -> IO ()-putStrLn = hPutStrLn stdout--{-# DEPRECATED hPutStrLn- "Use Data.ByteString.Char8.hPutStrLn instead. (Functions that rely on ASCII encodings belong in Data.ByteString.Char8)"- #-}-{-# DEPRECATED putStrLn- "Use Data.ByteString.Char8.putStrLn instead. (Functions that rely on ASCII encodings belong in Data.ByteString.Char8)"- #-}- ------------------------------------------------------------------------ -- Low level IO @@ -1833,8 +1951,8 @@ where readChunks chunks sz sz' = do fp <- mallocByteString sz- readcount <- unsafeWithForeignPtr fp $ \buf -> hGetBuf hnd buf sz- let chunk = PS fp 0 readcount+ readcount <- withForeignPtr fp $ \buf -> hGetBuf hnd buf sz+ let chunk = BS fp readcount -- We rely on the hGetBuf behaviour (not hGetBufSome) where it reads up -- to the size we ask for, or EOF. So short reads indicate EOF. if readcount < sz && sz > 0@@ -1892,16 +2010,16 @@ -- | 'findIndexOrEnd' is a variant of findIndex, that returns the length -- of the string if no element is found, rather than Nothing. findIndexOrEnd :: (Word8 -> Bool) -> ByteString -> Int-findIndexOrEnd k (PS x s l) =- accursedUnutterablePerformIO $- withForeignPtr x $ \f ->- go (f `plusPtr` s) 0+findIndexOrEnd k (BS x l) =+ accursedUnutterablePerformIO $ withForeignPtr x g where- go !ptr !n | n >= l = return l- | otherwise = do w <- peek ptr- if k w- then return n- else go (ptr `plusPtr` 1) (n+1)+ g ptr = go 0+ where+ go !n | n >= l = return l+ | otherwise = do w <- peek $ ptr `plusPtr` n+ if k w+ then return n+ else go (n+1) {-# INLINE findIndexOrEnd #-} -- Common up near identical calls to `error' to reduce the number@@ -1923,7 +2041,7 @@ -- Find from the end of the string using predicate findFromEndUntil :: (Word8 -> Bool) -> ByteString -> Int-findFromEndUntil f ps@(PS x s l)+findFromEndUntil f ps@(BS x l) | null ps = 0 | f (unsafeLast ps) = l- | otherwise = findFromEndUntil f (PS x s (l - 1))+ | otherwise = findFromEndUntil f (BS x (l - 1))
Data/ByteString/Builder.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, BangPatterns #-}+{-# LANGUAGE CPP, BangPatterns, MagicHash #-} {-# OPTIONS_GHC -fno-warn-unused-imports -fno-warn-orphans #-} #if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-}@@ -263,6 +263,8 @@ import Data.String (IsString(..)) import System.IO (Handle) import Foreign+import GHC.Base (unpackCString#, unpackCStringUtf8#,+ unpackFoldrCString#, build) -- HADDOCK only imports import qualified Data.ByteString as S (concat)@@ -432,10 +434,20 @@ char8 = P.primFixed P.char8 -- | Char8 encode a 'String'.-{-# INLINE string8 #-}+{-# INLINE [1] string8 #-} -- phased to allow P.cstring rewrite string8 :: String -> Builder string8 = P.primMapListFixed P.char8 +-- GHC desugars string literals with unpackCString# which the simplifier tends+-- to promptly turn into build (unpackFoldrCString# s), so we match on both.+{-# RULES+"string8/unpackCString#" forall s.+ string8 (unpackCString# s) = P.cstring s++"string8/unpackFoldrCString#" forall s.+ string8 (build (unpackFoldrCString# s)) = P.cstring s+ #-}+ ------------------------------------------------------------------------------ -- UTF-8 encoding ------------------------------------------------------------------------------@@ -446,9 +458,23 @@ charUtf8 = P.primBounded P.charUtf8 -- | UTF-8 encode a 'String'.-{-# INLINE stringUtf8 #-}+--+-- Note that 'stringUtf8' performs no codepoint validation and consequently may+-- emit invalid UTF-8 if asked (e.g. single surrogates).+{-# INLINE [1] stringUtf8 #-} -- phased to allow P.cstring rewrite stringUtf8 :: String -> Builder stringUtf8 = P.primMapListBounded P.charUtf8++{-# RULES+"stringUtf8/unpackCStringUtf8#" forall s.+ stringUtf8 (unpackCStringUtf8# s) = P.cstringUtf8 s++"stringUtf8/unpackCString#" forall s.+ stringUtf8 (unpackCString# s) = P.cstring s++"stringUtf8/unpackFoldrCString#" forall s.+ stringUtf8 (build (unpackFoldrCString# s)) = P.cstring s+ #-} instance IsString Builder where fromString = stringUtf8
Data/ByteString/Builder/Internal.hs view
@@ -203,7 +203,7 @@ {-# INLINE byteStringFromBuffer #-} byteStringFromBuffer :: Buffer -> S.ByteString byteStringFromBuffer (Buffer fpbuf (BufferRange op _)) =- S.PS fpbuf 0 (op `minusPtr` unsafeForeignPtrToPtr fpbuf)+ S.BS fpbuf (op `minusPtr` unsafeForeignPtrToPtr fpbuf) -- | Prepend the filled part of a 'Buffer' to a lazy 'L.ByteString' -- trimming it if necessary.@@ -859,7 +859,7 @@ byteStringThreshold maxCopySize = \bs -> builder $ step bs where- step !bs@(S.PS _ _ len) !k br@(BufferRange !op _)+ step !bs@(S.BS _ len) !k br@(BufferRange !op _) | len <= maxCopySize = byteStringCopyStep bs k br | otherwise = return $ insertChunk op bs k @@ -875,7 +875,7 @@ {-# INLINE byteStringCopyStep #-} byteStringCopyStep :: S.ByteString -> BuildStep a -> BuildStep a-byteStringCopyStep (S.PS ifp ioff isize) !k0 br0@(BufferRange op ope)+byteStringCopyStep (S.BS ifp isize) !k0 br0@(BufferRange op ope) -- Ensure that the common case is not recursive and therefore yields -- better code. | op' <= ope = do copyBytes op ip isize@@ -884,7 +884,7 @@ | otherwise = do wrappedBytesCopyStep (BufferRange ip ipe) k br0 where op' = op `plusPtr` isize- ip = unsafeForeignPtrToPtr ifp `plusPtr` ioff+ ip = unsafeForeignPtrToPtr ifp ipe = ip `plusPtr` isize k br = do touchForeignPtr ifp -- input consumed: OK to release here k0 br@@ -1149,7 +1149,7 @@ -- FIXME: We could reuse the trimmed buffer here. return $ Yield1 bs (mkCIOS False) | otherwise =- return $ Yield1 (S.PS fpbuf 0 chunkSize) (mkCIOS False)+ return $ Yield1 (S.BS fpbuf chunkSize) (mkCIOS False) where chunkSize = op' `minusPtr` pbuf size = pe `minusPtr` pbuf
Data/ByteString/Builder/Prim.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP, BangPatterns, ScopedTypeVariables #-}+{-# LANGUAGE MagicHash, UnboxedTuples, PatternGuards #-} {-# 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)@@ -438,6 +439,9 @@ -- a decimal number with UTF-8 encoded characters. , charUtf8 + , cstring+ , cstringUtf8+ {- -- * Testing support -- | The following four functions are intended for testing use@@ -473,6 +477,7 @@ #if MIN_VERSION_base(4,4,0) #if MIN_VERSION_base(4,7,0) import Foreign+import Foreign.C.Types #else import Foreign hiding (unsafeForeignPtrToPtr) #endif@@ -480,6 +485,8 @@ #else import Foreign #endif+import GHC.Exts+import GHC.IO ------------------------------------------------------------------------------ -- Creating Builders from bounded primitives@@ -638,10 +645,10 @@ \bs -> builder $ step bs where bound = I.sizeBound w- step (S.PS ifp ioff isize) !k =- goBS (unsafeForeignPtrToPtr ifp `plusPtr` ioff)+ step (S.BS ifp isize) !k =+ goBS (unsafeForeignPtrToPtr ifp) where- !ipe = unsafeForeignPtrToPtr ifp `plusPtr` (ioff + isize)+ !ipe = unsafeForeignPtrToPtr ifp `plusPtr` isize goBS !ip0 !br@(BufferRange op0 ope) | ip0 >= ipe = do touchForeignPtr ifp -- input buffer consumed@@ -673,6 +680,60 @@ ------------------------------------------------------------------------------+-- Raw CString encoding+------------------------------------------------------------------------------++#if !MIN_VERSION_base(4,7,0)+-- eqWord# et al. return Bools prior to GHC 7.6+isTrue# :: Bool -> Bool+isTrue# x = x+#endif++-- | A null-terminated ASCII encoded 'CString'. Null characters are not representable.+cstring :: Addr# -> Builder+cstring =+ \addr0 -> builder $ step addr0+ where+ step :: Addr# -> BuildStep r -> BuildStep r+ step !addr !k !br@(BufferRange op0@(Ptr op0#) ope)+ | isTrue# (ch `eqWord#` 0##) = k br+ | op0 == ope =+ return $ bufferFull defaultChunkSize op0 (step addr k)+ | otherwise = do+ IO $ \s -> case writeWord8OffAddr# op0# 0# ch s of+ s' -> (# s', () #)+ let br' = BufferRange (op0 `plusPtr` 1) ope+ step (addr `plusAddr#` 1#) k br'+ where+ !ch = indexWord8OffAddr# addr 0#++-- | A null-terminated UTF-8 encoded 'CString'. Null characters can be encoded as+-- @0xc0 0x80@.+cstringUtf8 :: Addr# -> Builder+cstringUtf8 =+ \addr0 -> builder $ step addr0+ where+ step :: Addr# -> BuildStep r -> BuildStep r+ step !addr !k !br@(BufferRange op0@(Ptr op0#) ope)+ | isTrue# (ch `eqWord#` 0##) = k br+ | op0 == ope =+ return $ bufferFull defaultChunkSize op0 (step addr k)+ -- NULL is encoded as 0xc0 0x80+ | isTrue# (ch `eqWord#` 0xc0##)+ , isTrue# (indexWord8OffAddr# addr 1# `eqWord#` 0x80##) = do+ IO $ \s -> case writeWord8OffAddr# op0# 0# 0## s of+ s' -> (# s', () #)+ let br' = BufferRange (op0 `plusPtr` 1) ope+ step (addr `plusAddr#` 2#) k br'+ | otherwise = do+ IO $ \s -> case writeWord8OffAddr# op0# 0# ch s of+ s' -> (# s', () #)+ let br' = BufferRange (op0 `plusPtr` 1) ope+ step (addr `plusAddr#` 1#) k br'+ where+ !ch = indexWord8OffAddr# addr 0#++------------------------------------------------------------------------------ -- Char8 encoding ------------------------------------------------------------------------------ @@ -736,4 +797,3 @@ x3 = fromIntegral $ ((x `shiftR` 6) .&. 0x3F) + 0x80 x4 = fromIntegral $ (x .&. 0x3F) + 0x80 in f4 x1 x2 x3 x4-
Data/ByteString/Builder/Prim/Internal/Base16.hs view
@@ -48,7 +48,7 @@ newtype EncodingTable = EncodingTable (ForeignPtr Word8) tableFromList :: [Word8] -> EncodingTable-tableFromList xs = case S.pack xs of S.PS fp _ _ -> EncodingTable fp+tableFromList xs = case S.pack xs of S.BS fp _ -> EncodingTable fp unsafeIndex :: EncodingTable -> Int -> IO Word8 unsafeIndex (EncodingTable table) = peekElemOff (unsafeForeignPtrToPtr table)
Data/ByteString/Char8.hs view
@@ -52,6 +52,8 @@ singleton, -- :: Char -> ByteString pack, -- :: String -> ByteString unpack, -- :: ByteString -> String+ B.fromStrict, -- :: ByteString -> Lazy.ByteString+ B.toStrict, -- :: Lazy.ByteString -> ByteString -- * Basic interface cons, -- :: Char -> ByteString -> ByteString@@ -148,8 +150,6 @@ -- ** Search for arbitrary substrings breakSubstring, -- :: ByteString -> ByteString -> (ByteString,ByteString)- findSubstring, -- :: ByteString -> ByteString -> Maybe Int- findSubstrings, -- :: ByteString -> ByteString -> [Int] -- * Searching ByteStrings @@ -164,6 +164,8 @@ -- * Indexing ByteStrings index, -- :: ByteString -> Int -> Char+ indexMaybe, -- :: ByteString -> Int -> Maybe Char+ (!?), -- :: ByteString -> Int -> Maybe Char elemIndex, -- :: Char -> ByteString -> Maybe Int elemIndices, -- :: Char -> ByteString -> [Int] elemIndexEnd, -- :: Char -> ByteString -> Maybe Int@@ -249,7 +251,7 @@ ,concat,take,drop,splitAt,intercalate ,sort,isPrefixOf,isSuffixOf,isInfixOf ,stripPrefix,stripSuffix- ,findSubstring,findSubstrings,breakSubstring,copy,group+ ,breakSubstring,copy,group ,getLine, getContents, putStr, interact ,readFile, writeFile, appendFile@@ -271,6 +273,7 @@ import System.IO (Handle,stdout) import Foreign + ------------------------------------------------------------------------ -- | /O(1)/ Convert a 'Char' into a 'ByteString'@@ -461,7 +464,7 @@ -- -- > replicate w c = unfoldr w (\u -> Just (u,u)) c ----- This implemenation uses @memset(3)@+-- This implementation uses @memset(3)@ replicate :: Int -> Char -> ByteString replicate n = B.replicate n . c2w {-# INLINE replicate #-}@@ -597,6 +600,7 @@ -- > split '\n' "a\nb\nd\ne" == ["a","b","d","e"] -- > split 'a' "aXaXaXa" == ["","X","X","X",""] -- > split 'x' "x" == ["",""]+-- > split undefined "" == [] -- and not [""] -- -- and --@@ -617,6 +621,7 @@ -- separators result in an empty component in the output. eg. -- -- > splitWith (=='a') "aabbaca" == ["","","bb","c",""]+-- > splitWith undefined "" == [] -- and not [""] -- splitWith :: (Char -> Bool) -> ByteString -> [ByteString] splitWith f = B.splitWith (f . w2c)@@ -643,6 +648,24 @@ index = (w2c .) . B.index {-# INLINE index #-} +-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+indexMaybe :: ByteString -> Int -> Maybe Char+indexMaybe = (fmap w2c .) . B.indexMaybe+{-# INLINE indexMaybe #-}++-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+(!?) :: ByteString -> Int -> Maybe Char+(!?) = indexMaybe+{-# INLINE (!?) #-}+ -- | /O(n)/ The 'elemIndex' function returns the index of the first -- element in the given 'ByteString' which is equal (by memchr) to the -- query element, or 'Nothing' if there is no such element.@@ -672,13 +695,39 @@ -- returns the index of the first element in the ByteString satisfying the predicate. findIndex :: (Char -> Bool) -> ByteString -> Maybe Int findIndex f = B.findIndex (f . w2c)-{-# INLINE findIndex #-}+{-# INLINE [1] findIndex #-} -- | The 'findIndices' function extends 'findIndex', by returning the -- indices of all elements satisfying the predicate, in ascending order. findIndices :: (Char -> Bool) -> ByteString -> [Int] findIndices f = B.findIndices (f . w2c)+{-# INLINE [1] findIndices #-} +#if MIN_VERSION_base(4,9,0)+{-# RULES+"ByteString specialise findIndex (x==)" forall x.+ findIndex (x `eqChar`) = elemIndex x+"ByteString specialise findIndex (==x)" forall x.+ findIndex (`eqChar` x) = elemIndex x+"ByteString specialise findIndices (x==)" forall x.+ findIndices (x `eqChar`) = elemIndices x+"ByteString specialise findIndices (==x)" forall x.+ findIndices (`eqChar` x) = elemIndices x+ #-}+#else+{-# RULES+"ByteString specialise findIndex (x==)" forall x.+ findIndex (x==) = elemIndex x+"ByteString specialise findIndex (==x)" forall x.+ findIndex (==x) = elemIndex x+"ByteString specialise findIndices (x==)" forall x.+ findIndices (x==) = elemIndices x+"ByteString specialise findIndices (==x)" forall x.+ findIndices (==x) = elemIndices x+ #-}+#endif++ -- | count returns the number of times its argument appears in the ByteString -- -- > count = length . elemIndices@@ -816,12 +865,12 @@ -- > break isSpace == breakSpace -- breakSpace :: ByteString -> (ByteString,ByteString)-breakSpace (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> do- i <- firstspace (p `plusPtr` s) 0 l+breakSpace (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> do+ i <- firstspace p 0 l return $! case () of {_- | i == 0 -> (empty, PS x s l)- | i == l -> (PS x s l, empty)- | otherwise -> (PS x s i, PS x (s+i) (l-i))+ | i == 0 -> (empty, BS x l)+ | i == l -> (BS x l, empty)+ | otherwise -> (BS x i, BS (plusForeignPtr x i) (l-i)) } {-# INLINE breakSpace #-} @@ -839,9 +888,9 @@ -- -- @since 0.10.12.0 dropSpace :: ByteString -> ByteString-dropSpace (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> do- i <- firstnonspace (p `plusPtr` s) 0 l- return $! if i == l then empty else PS x (s+i) (l-i)+dropSpace (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> do+ i <- firstnonspace p 0 l+ return $! if i == l then empty else BS (plusForeignPtr x i) (l-i) {-# INLINE dropSpace #-} firstnonspace :: Ptr Word8 -> Int -> Int -> IO Int@@ -865,9 +914,9 @@ -- but it is more efficient than using multiple reverses. -- dropSpaceEnd :: ByteString -> ByteString-dropSpaceEnd (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> do- i <- lastnonspace (p `plusPtr` s) (l-1)- return $! if i == (-1) then empty else PS x s (i+1)+dropSpaceEnd (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> do+ i <- lastnonspace p (l-1)+ return $! if i == (-1) then empty else BS x (i+1) {-# INLINE dropSpaceEnd #-} lastnonspace :: Ptr Word8 -> Int -> IO Int@@ -891,20 +940,23 @@ where search = elemIndex '\n' {---- Just as fast, but more complex. Should be much faster, I thought.-lines :: ByteString -> [ByteString]-lines (PS _ _ 0) = []-lines (PS x s l) = accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> do- let ptr = p `plusPtr` s-- loop n = do- let q = memchr (ptr `plusPtr` n) 0x0a (fromIntegral (l-n))- if q == nullPtr- then return [PS x (s+n) (l-n)]- else do let i = q `minusPtr` ptr- ls <- loop (i+1)- return $! PS x (s+n) (i-n) : ls- loop 0+-- Could be faster, now passes tests...+lines (BS _ 0) = []+lines (BS x l) = go x l+ where+ nl = c2w '\n'+ -- It is important to remain lazy in the tail of the list. The caller+ -- might only want the first few lines.+ go !f !len = accursedUnutterablePerformIO $ withForeignPtr f $ \p -> do+ q <- memchr p nl $! fromIntegral len+ if q == nullPtr+ then return [BS f len]+ else do+ let !i = q `minusPtr` p+ !j = i + 1+ if j < len+ then return $ BS f i : go (plusForeignPtr f j) (len - j)+ else return [BS f i] -} -- | 'unlines' is an inverse operation to 'lines'. It joins lines,
Data/ByteString/Internal.hs view
@@ -2,6 +2,9 @@ {-# LANGUAGE UnliftedFFITypes, MagicHash, UnboxedTuples, DeriveDataTypeable #-} {-# LANGUAGE TypeFamilies #-}+#if __GLASGOW_HASKELL__ >= 800+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+#endif #if __GLASGOW_HASKELL__ >= 703 {-# LANGUAGE Unsafe #-} #endif@@ -27,14 +30,19 @@ module Data.ByteString.Internal ( -- * The @ByteString@ type and representation- ByteString(..), -- instances: Eq, Ord, Show, Read, Data, Typeable+ ByteString+ ( BS+#if __GLASGOW_HASKELL__ >= 800+ , PS -- backwards compatibility shim+#endif+ ), -- instances: Eq, Ord, Show, Read, Data, Typeable -- * Conversion with lists: packing and unpacking packBytes, packUptoLenBytes, unsafePackLenBytes, packChars, packUptoLenChars, unsafePackLenChars, unpackBytes, unpackAppendBytesLazy, unpackAppendBytesStrict, unpackChars, unpackAppendCharsLazy, unpackAppendCharsStrict,- unsafePackAddress,+ unsafePackAddress, unsafePackLiteral, -- * Low level imperative construction create, -- :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString@@ -50,6 +58,8 @@ -- * Conversion to and from ForeignPtrs fromForeignPtr, -- :: ForeignPtr Word8 -> Int -> Int -> ByteString toForeignPtr, -- :: ByteString -> (ForeignPtr Word8, Int, Int)+ fromForeignPtr0, -- :: ForeignPtr Word8 -> Int -> ByteString+ toForeignPtr0, -- :: ByteString -> (ForeignPtr Word8, Int) -- * Utilities nullForeignPtr, -- :: ForeignPtr Word8@@ -65,35 +75,34 @@ memset, -- :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8) -- * cbits functions- c_reverse, -- :: Ptr Word8 -> Ptr Word8 -> CInt -> IO ()- c_intersperse, -- :: Ptr Word8 -> Ptr Word8 -> CInt -> Word8 -> IO ()- c_maximum, -- :: Ptr Word8 -> CInt -> IO Word8- c_minimum, -- :: Ptr Word8 -> CInt -> IO Word8- c_count, -- :: Ptr Word8 -> CInt -> Word8 -> IO CInt+ c_reverse, -- :: Ptr Word8 -> Ptr Word8 -> CSize -> IO ()+ c_intersperse, -- :: Ptr Word8 -> Ptr Word8 -> CSize -> Word8 -> IO ()+ c_maximum, -- :: Ptr Word8 -> CSize -> IO Word8+ c_minimum, -- :: Ptr Word8 -> CSize -> IO Word8+ c_count, -- :: Ptr Word8 -> CSize -> Word8 -> IO CSize+ c_sort, -- :: Ptr Word8 -> CSize -> IO () -- * Chars w2c, c2w, isSpaceWord8, isSpaceChar8, -- * Deprecated and unmentionable accursedUnutterablePerformIO, -- :: IO a -> a- inlinePerformIO, -- :: IO a -> a- unsafeWithForeignPtr++ -- * Exported compatibility shim+ plusForeignPtr ) where import Prelude hiding (concat, null) import qualified Data.List as List import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-#if MIN_VERSION_base(4,15,0)-import GHC.ForeignPtr (unsafeWithForeignPtr)-#endif 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(..))+import Foreign.C.Types (CInt(..), CSize(..)) #else-import Foreign.C.Types (CInt, CSize, CULong)+import Foreign.C.Types (CInt, CSize) #endif import Foreign.C.String (CString)@@ -110,6 +119,7 @@ import Data.Monoid (Monoid(..)) #endif + import Control.DeepSeq (NFData(rnf)) import Data.String (IsString(..))@@ -144,17 +154,41 @@ import GHC.ForeignPtr (ForeignPtr(ForeignPtr) ,newForeignPtr_, mallocPlainForeignPtrBytes)-import GHC.Ptr (Ptr(..), castPtr)--#if !MIN_VERSION_base(4,15,0)-unsafeWithForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b-unsafeWithForeignPtr = withForeignPtr+#if MIN_VERSION_base(4,10,0)+import GHC.ForeignPtr (plusForeignPtr)+#else+import GHC.Types (Int (..))+import GHC.Prim (plusAddr#) #endif +#if __GLASGOW_HASKELL__ >= 811+import GHC.CString (cstringLength#)+import GHC.ForeignPtr (ForeignPtrContents(FinalPtr))+#endif+import GHC.Ptr (Ptr(..), castPtr) -- CFILES stuff is Hugs only {-# CFILES cbits/fpstring.c #-} +#if !MIN_VERSION_base(4,10,0)+-- |Advances the given address by the given offset in bytes.+--+-- The new 'ForeignPtr' shares the finalizer of the original,+-- equivalent from a finalization standpoint to just creating another+-- reference to the original. That is, the finalizer will not be+-- called before the new 'ForeignPtr' is unreachable, nor will it be+-- called an additional time due to this call, and the finalizer will+-- be called with the same address that it would have had this call+-- not happened, *not* the new address.+plusForeignPtr :: ForeignPtr a -> Int -> ForeignPtr b+plusForeignPtr (ForeignPtr addr guts) (I# offset) = ForeignPtr (plusAddr# addr offset) guts+{-# INLINE [0] plusForeignPtr #-}+{-# RULES+"ByteString plusForeignPtr/0" forall fp .+ plusForeignPtr fp 0 = fp+ #-}+#endif+ -- ----------------------------------------------------------------------------- -- | A space-efficient representation of a 'Word8' vector, supporting many@@ -164,11 +198,31 @@ -- "Data.ByteString.Char8" it can be interpreted as containing 8-bit -- characters. ---data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload- {-# UNPACK #-} !Int -- offset+data ByteString = BS {-# UNPACK #-} !(ForeignPtr Word8) -- payload {-# UNPACK #-} !Int -- length deriving (Typeable) ++#if __GLASGOW_HASKELL__ >= 800+-- |+-- @'PS' foreignPtr offset length@ represents a 'ByteString' with data+-- backed by a given @foreignPtr@, starting at a given @offset@ in bytes+-- and of a specified @length@.+--+-- This pattern is used to emulate the legacy 'ByteString' data+-- constructor, so that pre-existing code generally doesn't need to+-- change to benefit from the simplified 'BS' constructor and can+-- continue to function unchanged.+--+-- /Note:/ Matching with this constructor will always be given a 0 'offset',+-- as the base will be manipulated by 'plusForeignPtr' instead.+--+pattern PS :: ForeignPtr Word8 -> Int -> Int -> ByteString+pattern PS fp zero len <- BS fp (((,) 0) -> (zero, len)) where+ PS fp o len = BS (plusForeignPtr fp o) len+{-# COMPLETE PS #-}+#endif+ instance Eq ByteString where (==) = eq @@ -182,7 +236,7 @@ #endif instance Monoid ByteString where- mempty = PS nullForeignPtr 0 0+ mempty = BS nullForeignPtr 0 #if MIN_VERSION_base(4,9,0) mappend = (<>) #else@@ -191,7 +245,7 @@ mconcat = concat instance NFData ByteString where- rnf PS{} = ()+ rnf BS{} = () instance Show ByteString where showsPrec p ps r = showsPrec p (unpackChars ps) r@@ -210,6 +264,7 @@ -- | Beware: 'fromString' truncates multi-byte characters to octets. -- e.g. "枯朶に烏のとまりけり秋の暮" becomes �6k�nh~�Q��n� instance IsString ByteString where+ {-# INLINE fromString #-} fromString = packChars instance Data ByteString where@@ -231,7 +286,7 @@ {-# RULES "ByteString packChars/packAddress" forall s .- packChars (unpackCString# s) = accursedUnutterablePerformIO (unsafePackAddress s)+ packChars (unpackCString# s) = unsafePackLiteral s #-} unsafePackLenBytes :: Int -> [Word8] -> ByteString@@ -272,15 +327,34 @@ -- unsafePackAddress :: Addr# -> IO ByteString unsafePackAddress addr# = do+#if __GLASGOW_HASKELL__ >= 811+ return (BS (ForeignPtr addr# FinalPtr) (I# (cstringLength# addr#)))+#else p <- newForeignPtr_ (castPtr cstr) l <- c_strlen cstr- return $ PS p 0 (fromIntegral l)+ return $ BS p (fromIntegral l) where cstr :: CString cstr = Ptr addr#+#endif {-# INLINE unsafePackAddress #-} +-- | See 'unsafePackAddress'. This function has similar behavior. Prefer+-- this function when the address in known to be an @Addr#@ literal. In+-- that context, there is no need for the sequencing guarantees that 'IO'+-- provides. On GHC 9.0 and up, this function uses the @FinalPtr@ data+-- constructor for @ForeignPtrContents@.+unsafePackLiteral :: Addr# -> ByteString+unsafePackLiteral addr# =+#if __GLASGOW_HASKELL__ >= 811+ BS (ForeignPtr addr# FinalPtr) (I# (cstringLength# addr#))+#else+ let len = accursedUnutterablePerformIO (c_strlen (Ptr addr#))+ in BS (accursedUnutterablePerformIO (newForeignPtr_ (Ptr addr#))) (fromIntegral len)+#endif+{-# INLINE unsafePackLiteral #-} + packUptoLenBytes :: Int -> [Word8] -> (ByteString, [Word8]) packUptoLenBytes len xs0 = unsafeCreateUptoN' len $ \p -> go p len xs0@@ -315,22 +389,22 @@ unpackChars bs = unpackAppendCharsLazy bs [] unpackAppendBytesLazy :: ByteString -> [Word8] -> [Word8]-unpackAppendBytesLazy (PS fp off len) xs- | len <= 100 = unpackAppendBytesStrict (PS fp off len) xs- | otherwise = unpackAppendBytesStrict (PS fp off 100) remainder+unpackAppendBytesLazy (BS fp len) xs+ | len <= 100 = unpackAppendBytesStrict (BS fp len) xs+ | otherwise = unpackAppendBytesStrict (BS fp 100) remainder where- remainder = unpackAppendBytesLazy (PS fp (off+100) (len-100)) xs+ remainder = unpackAppendBytesLazy (BS (plusForeignPtr fp 100) (len-100)) xs -- Why 100 bytes you ask? Because on a 64bit machine the list we allocate -- takes just shy of 4k which seems like a reasonable amount. -- (5 words per list element, 8 bytes per word, 100 elements = 4000 bytes) unpackAppendCharsLazy :: ByteString -> [Char] -> [Char]-unpackAppendCharsLazy (PS fp off len) cs- | len <= 100 = unpackAppendCharsStrict (PS fp off len) cs- | otherwise = unpackAppendCharsStrict (PS fp off 100) remainder+unpackAppendCharsLazy (BS fp len) cs+ | len <= 100 = unpackAppendCharsStrict (BS fp len) cs+ | otherwise = unpackAppendCharsStrict (BS fp 100) remainder where- remainder = unpackAppendCharsLazy (PS fp (off+100) (len-100)) cs+ remainder = unpackAppendCharsLazy (BS (plusForeignPtr fp 100) (len-100)) cs -- For these unpack functions, since we're unpacking the whole list strictly we -- build up the result list in an accumulator. This means we have to build up@@ -338,9 +412,9 @@ -- buffer and loops down until we hit the sentinal: unpackAppendBytesStrict :: ByteString -> [Word8] -> [Word8]-unpackAppendBytesStrict (PS fp off len) xs =+unpackAppendBytesStrict (BS fp len) xs = accursedUnutterablePerformIO $ withForeignPtr fp $ \base ->- loop (base `plusPtr` (off-1)) (base `plusPtr` (off-1+len)) xs+ loop (base `plusPtr` (-1)) (base `plusPtr` (-1+len)) xs where loop !sentinal !p acc | p == sentinal = return acc@@ -348,9 +422,9 @@ loop sentinal (p `plusPtr` (-1)) (x:acc) unpackAppendCharsStrict :: ByteString -> [Char] -> [Char]-unpackAppendCharsStrict (PS fp off len) xs =+unpackAppendCharsStrict (BS fp len) xs = accursedUnutterablePerformIO $ withForeignPtr fp $ \base ->- loop (base `plusPtr` (off-1)) (base `plusPtr` (off-1+len)) xs+ loop (base `plusPtr` (-1)) (base `plusPtr` (-1+len)) xs where loop !sentinal !p acc | p == sentinal = return acc@@ -361,7 +435,11 @@ -- | The 0 pointer. Used to indicate the empty Bytestring. nullForeignPtr :: ForeignPtr Word8-nullForeignPtr = ForeignPtr nullAddr# (error "nullForeignPtr") --TODO: should ForeignPtrContents be strict?+#if __GLASGOW_HASKELL__ >= 811+nullForeignPtr = ForeignPtr nullAddr# FinalPtr+#else+nullForeignPtr = ForeignPtr nullAddr# (error "nullForeignPtr")+#endif -- --------------------------------------------------------------------- -- Low level constructors@@ -376,14 +454,25 @@ -> Int -- ^ Offset -> Int -- ^ Length -> ByteString-fromForeignPtr = PS+fromForeignPtr fp o len = BS (plusForeignPtr fp o) len {-# INLINE fromForeignPtr #-} +fromForeignPtr0 :: ForeignPtr Word8+ -> Int -- ^ Length+ -> ByteString+fromForeignPtr0 = BS+{-# INLINE fromForeignPtr0 #-}+ -- | /O(1)/ Deconstruct a ForeignPtr from a ByteString toForeignPtr :: ByteString -> (ForeignPtr Word8, Int, Int) -- ^ (ptr, offset, length)-toForeignPtr (PS ps s l) = (ps, s, l)+toForeignPtr (BS ps l) = (ps, 0, l) {-# INLINE toForeignPtr #-} +-- | /O(1)/ Deconstruct a ForeignPtr from a ByteString+toForeignPtr0 :: ByteString -> (ForeignPtr Word8, Int) -- ^ (ptr, length)+toForeignPtr0 (BS ps l) = (ps, l)+{-# INLINE toForeignPtr0 #-}+ -- | A way of creating ByteStrings outside the IO monad. The @Int@ -- argument gives the final size of the ByteString. unsafeCreate :: Int -> (Ptr Word8 -> IO ()) -> ByteString@@ -408,7 +497,7 @@ create l f = do fp <- mallocByteString l withForeignPtr fp $ \p -> f p- return $! PS fp 0 l+ return $! BS fp l {-# INLINE create #-} -- | Given a maximum size @l@ and an action @f@ that fills the 'ByteString'@@ -418,7 +507,7 @@ createUptoN l f = do fp <- mallocByteString l l' <- withForeignPtr fp $ \p -> f p- assert (l' <= l) $ return $! PS fp 0 l'+ assert (l' <= l) $ return $! BS fp l' {-# INLINE createUptoN #-} -- | Like 'createUpToN', but also returns an additional value created by the@@ -429,7 +518,7 @@ createUptoN' l f = do fp <- mallocByteString l (l', res) <- withForeignPtr fp $ \p -> f p- assert (l' <= l) $ return (PS fp 0 l', res)+ assert (l' <= l) $ return (BS fp l', res) {-# INLINE createUptoN' #-} -- | Given the maximum size needed and a function to make the contents@@ -446,7 +535,7 @@ withForeignPtr fp $ \p -> do l' <- f p if assert (l' <= l) $ l' >= l- then return $! PS fp 0 l+ then return $! BS fp l else create l' $ \p' -> memcpy p' p l' {-# INLINE createAndTrim #-} @@ -456,7 +545,7 @@ withForeignPtr fp $ \p -> do (off, l', res) <- f p if assert (l' <= l) $ l' >= l- then return (PS fp 0 l, res)+ then return (BS fp l, res) else do ps <- create l' $ \p' -> memcpy p' (p `plusPtr` off) l' return (ps, res)@@ -471,32 +560,32 @@ -- Implementations for Eq, Ord and Monoid instances eq :: ByteString -> ByteString -> Bool-eq a@(PS fp off len) b@(PS fp' off' len')- | len /= len' = False -- short cut on length- | fp == fp' && off == off' = True -- short cut for the same string- | otherwise = compareBytes a b == EQ+eq a@(BS fp len) b@(BS fp' len')+ | len /= len' = False -- short cut on length+ | fp == fp' = True -- short cut for the same string+ | otherwise = compareBytes a b == EQ {-# INLINE eq #-} -- ^ still needed compareBytes :: ByteString -> ByteString -> Ordering-compareBytes (PS _ _ 0) (PS _ _ 0) = EQ -- short cut for empty strings-compareBytes (PS fp1 off1 len1) (PS fp2 off2 len2) =+compareBytes (BS _ 0) (BS _ 0) = EQ -- short cut for empty strings+compareBytes (BS fp1 len1) (BS fp2 len2) = accursedUnutterablePerformIO $- unsafeWithForeignPtr fp1 $ \p1 ->- unsafeWithForeignPtr fp2 $ \p2 -> do- i <- memcmp (p1 `plusPtr` off1) (p2 `plusPtr` off2) (min len1 len2)+ withForeignPtr fp1 $ \p1 ->+ withForeignPtr fp2 $ \p2 -> do+ i <- memcmp p1 p2 (min len1 len2) return $! case i `compare` 0 of EQ -> len1 `compare` len2 x -> x append :: ByteString -> ByteString -> ByteString-append (PS _ _ 0) b = b-append a (PS _ _ 0) = a-append (PS fp1 off1 len1) (PS fp2 off2 len2) =+append (BS _ 0) b = b+append a (BS _ 0) = a+append (BS fp1 len1) (BS fp2 len2) = unsafeCreate (len1+len2) $ \destptr1 -> do let destptr2 = destptr1 `plusPtr` len1- unsafeWithForeignPtr fp1 $ \p1 -> memcpy destptr1 (p1 `plusPtr` off1) len1- unsafeWithForeignPtr fp2 $ \p2 -> memcpy destptr2 (p2 `plusPtr` off2) len2+ withForeignPtr fp1 $ \p1 -> memcpy destptr1 p1 len1+ withForeignPtr fp2 $ \p2 -> memcpy destptr2 p2 len2 concat :: [ByteString] -> ByteString concat = \bss0 -> goLen0 bss0 bss0@@ -519,26 +608,26 @@ where -- It's still possible that the result is empty goLen0 _ [] = mempty- goLen0 bss0 (PS _ _ 0 :bss) = goLen0 bss0 bss+ goLen0 bss0 (BS _ 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+ goLen1 bss0 bs (BS _ 0 :bss) = goLen1 bss0 bs bss+ goLen1 bss0 bs (BS _ len:bss) = goLen bss0 (checkedAdd "concat" len' len) bss+ where BS _ len' = bs -- General case, just find the total length we'll need- goLen bss0 !total (PS _ _ len:bss) = goLen bss0 total' bss+ goLen bss0 !total (BS _ 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- unsafeWithForeignPtr fp $ \p -> memcpy ptr (p `plusPtr` off) len+ goCopy (BS _ 0 :bss) !ptr = goCopy bss ptr+ goCopy (BS fp len:bss) !ptr = do+ withForeignPtr fp $ \p -> memcpy ptr p len goCopy bss (ptr `plusPtr` len) {-# NOINLINE concat #-} @@ -629,11 +718,6 @@ accursedUnutterablePerformIO :: IO a -> a accursedUnutterablePerformIO (IO m) = case m realWorld# of (# _, r #) -> r -inlinePerformIO :: IO a -> a-inlinePerformIO = accursedUnutterablePerformIO-{-# INLINE inlinePerformIO #-}-{-# DEPRECATED inlinePerformIO "If you think you know what you are doing, use 'System.IO.Unsafe.unsafePerformIO'. If you are sure you know what you are doing, use 'unsafeDupablePerformIO'. If you enjoy sharing an address space with a malevolent agent of chaos, try 'accursedUnutterablePerformIO'." #-}- -- --------------------------------------------------------------------- -- -- Standard C functions@@ -684,16 +768,19 @@ -- foreign import ccall unsafe "static fpstring.h fps_reverse" c_reverse- :: Ptr Word8 -> Ptr Word8 -> CULong -> IO ()+ :: Ptr Word8 -> Ptr Word8 -> CSize -> IO () foreign import ccall unsafe "static fpstring.h fps_intersperse" c_intersperse- :: Ptr Word8 -> Ptr Word8 -> CULong -> Word8 -> IO ()+ :: Ptr Word8 -> Ptr Word8 -> CSize -> Word8 -> IO () foreign import ccall unsafe "static fpstring.h fps_maximum" c_maximum- :: Ptr Word8 -> CULong -> IO Word8+ :: Ptr Word8 -> CSize -> IO Word8 foreign import ccall unsafe "static fpstring.h fps_minimum" c_minimum- :: Ptr Word8 -> CULong -> IO Word8+ :: Ptr Word8 -> CSize -> IO Word8 foreign import ccall unsafe "static fpstring.h fps_count" c_count- :: Ptr Word8 -> CULong -> Word8 -> IO CULong+ :: Ptr Word8 -> CSize -> Word8 -> IO CSize++foreign import ccall unsafe "static fpstring.h fps_sort" c_sort+ :: Ptr Word8 -> CSize -> IO ()
Data/ByteString/Lazy.hs view
@@ -151,8 +151,6 @@ -- ** Search for arbitrary substrings -- isSubstringOf, -- :: ByteString -> ByteString -> Bool--- findSubstring, -- :: ByteString -> ByteString -> Maybe Int--- findSubstrings, -- :: ByteString -> ByteString -> [Int] -- * Searching ByteStrings @@ -167,6 +165,8 @@ -- * Indexing ByteStrings index, -- :: ByteString -> Int64 -> Word8+ indexMaybe, -- :: ByteString -> Int64 -> Maybe Word8+ (!?), -- :: ByteString -> Int64 -> Maybe Word8 elemIndex, -- :: Word8 -> ByteString -> Maybe Int64 elemIndexEnd, -- :: Word8 -> ByteString -> Maybe Int64 elemIndices, -- :: Word8 -> ByteString -> [Int64]@@ -189,11 +189,11 @@ -- defrag, -- :: ByteString -> ByteString -- * I\/O with 'ByteString's+ -- $IOChunk -- ** Standard input and output getContents, -- :: IO ByteString putStr, -- :: ByteString -> IO ()- putStrLn, -- :: ByteString -> IO () interact, -- :: (ByteString -> ByteString) -> IO () -- ** Files@@ -271,53 +271,6 @@ toChunks :: ByteString -> [P.ByteString] toChunks cs = foldrChunks (:) [] cs --- |/O(1)/ Convert a strict 'ByteString' into a lazy 'ByteString'.-fromStrict :: P.ByteString -> ByteString-fromStrict bs | S.null bs = Empty- | otherwise = Chunk bs Empty---- |/O(n)/ Convert a lazy 'ByteString' into a strict 'ByteString'.------ Note that this is an /expensive/ operation that forces the whole lazy--- ByteString into memory and then copies all the data. If possible, try to--- avoid converting back and forth between strict and lazy bytestrings.----toStrict :: ByteString -> S.ByteString-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- -- 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-- -- 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- S.unsafeWithForeignPtr fp $ \p -> do- 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.- ------------------------------------------------------------------------ {-@@ -465,10 +418,10 @@ intersperse w (Chunk c cs) = Chunk (S.intersperse w c) (foldrChunks (Chunk . intersperse') Empty cs) where intersperse' :: P.ByteString -> P.ByteString- intersperse' (S.PS fp o l) =- S.unsafeCreate (2*l) $ \p' -> S.unsafeWithForeignPtr fp $ \p -> do+ intersperse' (S.BS fp l) =+ S.unsafeCreate (2*l) $ \p' -> withForeignPtr fp $ \p -> do poke p' w- S.c_intersperse (p' `plusPtr` 1) (p `plusPtr` o) (fromIntegral l) w+ S.c_intersperse (p' `plusPtr` 1) p (fromIntegral l) w -- | The 'transpose' function transposes the rows and columns of its -- 'ByteString' argument.@@ -606,8 +559,18 @@ -- -- Note that ----- > last (scanl f z xs) == foldl f z xs.-scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString+-- > head (scanl f z xs) == z+-- > last (scanl f z xs) == foldl f z xs+--+scanl+ :: (Word8 -> Word8 -> Word8)+ -- ^ accumulator -> element -> new accumulator+ -> Word8+ -- ^ starting value of accumulator+ -> ByteString+ -- ^ input of length n+ -> ByteString+ -- ^ output of length n+1 scanl f z = snd . foldl k (z,singleton z) where k (c,acc) a = let n = f c a in (n, acc `snoc` n)@@ -709,9 +672,9 @@ in (Chunk c cs', cs'') --- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,--- returns the longest prefix (possibly empty) of @xs@ of elements that--- satisfy @p@.+-- | Similar to 'P.takeWhile',+-- returns the longest (possibly empty) prefix of elements+-- satisfying the predicate. takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString takeWhile f cs0 = takeWhile' cs0 where takeWhile' Empty = Empty@@ -721,7 +684,9 @@ n | n < S.length c -> Chunk (S.take n c) Empty | otherwise -> Chunk c (takeWhile' cs) --- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.+-- | Similar to 'P.dropWhile',+-- drops the longest (possibly empty) prefix of elements+-- satisfying the predicate and returns the remainder. dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString dropWhile f cs0 = dropWhile' cs0 where dropWhile' Empty = Empty@@ -730,7 +695,12 @@ n | n < S.length c -> Chunk (S.drop n c) cs | otherwise -> dropWhile' cs --- | 'break' @p@ is equivalent to @'span' ('not' . p)@.+-- | Similar to 'P.break',+-- returns the longest (possibly empty) prefix of elements which __do not__+-- satisfy the predicate and the remainder of the string.+--+-- 'break' @p@ is equivalent to @'span' (not . p)@ and to @('takeWhile' (not . p) &&& 'dropWhile' (not . p))@.+-- break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString) break f cs0 = break' cs0 where break' Empty = (Empty, Empty)@@ -782,8 +752,12 @@ | otherwise -> (x' : [], x'' : xs) -} --- | 'span' @p xs@ breaks the ByteString into two segments. It is--- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@+-- | Similar to 'P.span',+-- returns the longest (possibly empty) prefix of elements+-- satisfying the predicate and the remainder of the string.+--+-- 'span' @p@ is equivalent to @'break' (not . p)@ and to @('takeWhile' p &&& 'dropWhile' p)@.+-- span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString) span p = break (not . p) @@ -793,7 +767,7 @@ -- separators result in an empty component in the output. eg. -- -- > splitWith (==97) "aabbaca" == ["","","bb","c",""] -- fromEnum 'a' == 97--- > splitWith (==97) [] == []+-- > splitWith undefined "" == [] -- and not [""] -- splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString] splitWith _ Empty = []@@ -811,6 +785,7 @@ -- > split 10 "a\nb\nd\ne" == ["a","b","d","e"] -- fromEnum '\n' == 10 -- > split 97 "aXaXaXa" == ["","X","X","X",""] -- fromEnum 'a' == 97 -- > split 120 "x" == ["",""] -- fromEnum 'x' == 120+-- > split undefined "" == [] -- and not [""] -- -- and --@@ -895,6 +870,29 @@ index' cs (n - fromIntegral (S.length c)) | otherwise = S.unsafeIndex c (fromIntegral n) +-- | /O(c)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+indexMaybe :: ByteString -> Int64 -> Maybe Word8+indexMaybe _ i | i < 0 = Nothing+indexMaybe cs0 i = index' cs0 i+ where index' Empty _ = Nothing+ index' (Chunk c cs) n+ | n >= fromIntegral (S.length c) =+ index' cs (n - fromIntegral (S.length c))+ | otherwise = Just $! S.unsafeIndex c (fromIntegral n)++-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+(!?) :: ByteString -> Int64 -> Maybe Word8+(!?) = indexMaybe+{-# INLINE (!?) #-}+ -- | /O(n)/ The 'elemIndex' function returns the index of the first -- element in the given 'ByteString' which is equal to the query -- element, or 'Nothing' if there is no such element.@@ -985,6 +983,7 @@ where findIndices' _ Empty = [] findIndices' n (Chunk c cs) = L.map ((+n).fromIntegral) (S.findIndices k c) ++ findIndices' (n + fromIntegral (S.length c)) cs+{-# INLINE findIndices #-} -- --------------------------------------------------------------------- -- Searching ByteStrings@@ -1247,7 +1246,8 @@ -- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks -- are read on demand, using the default chunk size. ----- Once EOF is encountered, the Handle is closed.+-- File handles are closed on EOF if all the file is read, or through+-- garbage collection otherwise. -- -- Note: the 'Handle' should be placed in binary mode with -- 'System.IO.hSetBinaryMode' for 'hGetContents' to@@ -1273,8 +1273,12 @@ hGetNonBlocking = hGetNonBlockingN defaultChunkSize -- | Read an entire file /lazily/ into a 'ByteString'.--- The Handle will be held open until EOF is encountered. --+-- The 'Handle' will be held open until EOF is encountered.+--+-- Note that this function's implementation relies on 'hGetContents'.+-- The reader is advised to read its documentation.+-- readFile :: FilePath -> IO ByteString readFile f = openBinaryFile f ReadMode >>= hGetContents @@ -1329,15 +1333,6 @@ putStr :: ByteString -> IO () putStr = hPut stdout --- | Write a ByteString to stdout, appending a newline byte----putStrLn :: ByteString -> IO ()-putStrLn ps = hPut stdout ps >> hPut stdout (singleton 0x0a)--{-# DEPRECATED putStrLn- "Use Data.ByteString.Lazy.Char8.putStrLn instead. (Functions that rely on ASCII encodings belong in Data.ByteString.Lazy.Char8)"- #-}- -- | The interact function takes a function of type @ByteString -> ByteString@ -- as its argument. The entire input from the standard input device is passed -- to this function as its argument, and the resulting string is output on the@@ -1371,9 +1366,9 @@ -- | 'findIndexOrEnd' is a variant of findIndex, that returns the length -- of the string if no element is found, rather than Nothing. findIndexOrEnd :: (Word8 -> Bool) -> P.ByteString -> Int-findIndexOrEnd k (S.PS x s l) =+findIndexOrEnd k (S.BS x l) = S.accursedUnutterablePerformIO $- withForeignPtr x $ \f -> go (f `plusPtr` s) 0+ withForeignPtr x $ \f -> go f 0 where go !ptr !n | n >= l = return l | otherwise = do w <- peek ptr@@ -1381,3 +1376,69 @@ then return n else go (ptr `plusPtr` 1) (n+1) {-# INLINE findIndexOrEnd #-}++-- $IOChunk+--+-- ⚠ Using lazy I\/O functions like 'readFile' or 'hGetContents'+-- means that the order of operations such as closing the file handle+-- is left at the discretion of the RTS.+-- Hence, the developer can face some issues when:+--+-- * The program reads a file and writes the same file. This means that the file+-- may be locked because the handler has not been released when 'writeFile' is executed.+-- * The program reads thousands of files, but due to lazy evaluation, the OS's file descriptor+-- limit is reached before the handlers can be released.+--+-- === Why?+--+-- Consider the following program:+--+-- > import qualified Data.ByteString.Lazy as BL+-- > main = do+-- > _ <- BL.readFile "foo.txt"+-- > BL.writeFile "foo.txt" mempty+--+-- Generally, in the 'IO' monad side effects happen+-- sequentially and in full. Therefore, one might reasonably expect that+-- reading the whole file via 'readFile' executes all three actions+-- (open the file handle, read its content, close the file handle) before+-- control moves to the following 'writeFile' action. This expectation holds+-- for the strict "Data.ByteString" API. However, the above lazy 'ByteString' variant+-- of the program fails with @openBinaryFile: resource busy (file is locked)@.+--+-- The reason for this is that "Data.ByteString.Lazy" is specifically designed+-- to handle large or unbounded streams of data incrementally, without requiring all the data+-- to be resident in memory at the same time. Incremental processing would not be possible+-- if 'readFile' were to follow the usual rules of 'IO': evaluating all side effects+-- would require reading the file in full and closing its handle before returning from 'readFile'. This is why+-- 'readFile' (and 'hGetContents' in general) is implemented+-- via 'unsafeInterleaveIO', which allows 'IO' side effects to be delayed and+-- interleaved with subsequent processing of the return value.+-- That's exactly what happens+-- in the example above: 'readFile' opens a file handle, but since the content+-- is not fully consumed, the file handle remains open, allowing the content to+-- read __on demand__ (never in this case, since the return value is ignored).+-- So when 'writeFile' is executed next, @foo.txt@ is still open for reading and+-- the RTS takes care to avoid simultaneously opening it for writing, instead+-- returning the error shown above.+--+-- === How to enforce the order of effects?+--+-- If the content is small enough to fit in memory,+-- consider using strict 'Data.ByteString.readFile',+-- potentially applying 'fromStrict' afterwards. E. g.,+--+-- > import qualified Data.ByteString as BS+-- > import qualified Data.ByteString.Lazy as BL+-- > main = do+-- > _ <- BS.readFile "foo.txt"+-- > BL.writeFile "foo.txt" mempty+--+-- If you are dealing with large or unbounded data streams,+-- consider reaching out for a specialised package, such as+-- <http://hackage.haskell.org/package/conduit conduit>,+-- <http://hackage.haskell.org/package/machines-bytestring machines-bytestring>,+-- <http://hackage.haskell.org/package/pipes-bytestring pipes-bytestring>,+-- <http://hackage.haskell.org/package/streaming-bytestring streaming-bytestring>,+-- <http://hackage.haskell.org/package/streamly-bytestring streamly-bytestring>,+-- etc.
− Data/ByteString/Lazy/Builder.hs
@@ -1,11 +0,0 @@---- | We decided to rename the Builder modules. Sorry about that.------ The old names will hang about for at least once release cycle and then later remove them.----module Data.ByteString.Lazy.Builder- {-# DEPRECATED "Use Data.ByteString.Builder instead" #-} (- module Data.ByteString.Builder-) where--import Data.ByteString.Builder
− Data/ByteString/Lazy/Builder/ASCII.hs
@@ -1,26 +0,0 @@---- | We decided to rename the Builder modules. Sorry about that.------ In additon, the ASCII module has been merged into the main--- "Data.ByteString.Builder" module.------ The old names will hang about for at least once release cycle and then later remove them.----module Data.ByteString.Lazy.Builder.ASCII- {-# DEPRECATED "Use Data.ByteString.Builder instead" #-} (- module Data.ByteString.Builder-, byteStringHexFixed-, lazyByteStringHexFixed-) where--import Data.ByteString.Builder-import qualified Data.ByteString as S-import qualified Data.ByteString.Lazy as L--byteStringHexFixed :: S.ByteString -> Builder-byteStringHexFixed = byteStringHex-{-# DEPRECATED byteStringHexFixed "Use byteStringHex instead" #-}--lazyByteStringHexFixed :: L.ByteString -> Builder-lazyByteStringHexFixed = lazyByteStringHex-{-# DEPRECATED lazyByteStringHexFixed "Use lazyByteStringHex instead" #-}
− Data/ByteString/Lazy/Builder/Extras.hs
@@ -1,11 +0,0 @@---- | We decided to rename the Builder modules. Sorry about that.------ The old names will hang about for at least once release cycle and then later remove them.----module Data.ByteString.Lazy.Builder.Extras- {-# DEPRECATED "Use Data.ByteString.Builder.Extra instead" #-} (- module Data.ByteString.Builder.Extra-) where--import Data.ByteString.Builder.Extra
Data/ByteString/Lazy/Char8.hs view
@@ -146,6 +146,8 @@ -- * Indexing ByteStrings index, -- :: ByteString -> Int64 -> Char+ indexMaybe, -- :: ByteString -> Int64 -> Maybe Char+ (!?), -- :: ByteString -> Int64 -> Maybe Char elemIndex, -- :: Char -> ByteString -> Maybe Int64 elemIndices, -- :: Char -> ByteString -> [Int64] findIndex, -- :: (Char -> Bool) -> ByteString -> Maybe Int64@@ -197,7 +199,7 @@ -- Functions transparently exported import Data.ByteString.Lazy- (fromChunks, toChunks, fromStrict, toStrict+ (fromChunks, toChunks ,empty,null,length,tail,init,append,reverse,transpose,cycle ,concat,take,drop,splitAt,intercalate ,isPrefixOf,isSuffixOf,group,inits,tails,copy@@ -493,6 +495,7 @@ -- > split '\n' "a\nb\nd\ne" == ["a","b","d","e"] -- > split 'a' "aXaXaXa" == ["","X","X","X"] -- > split 'x' "x" == ["",""]+-- > split undefined "" == [] -- and not [""] -- -- and --@@ -513,6 +516,7 @@ -- separators result in an empty component in the output. eg. -- -- > splitWith (=='a') "aabbaca" == ["","","bb","c",""]+-- > splitWith undefined "" == [] -- and not [""] -- splitWith :: (Char -> Bool) -> ByteString -> [ByteString] splitWith f = L.splitWith (f . w2c)@@ -527,6 +531,24 @@ index = (w2c .) . L.index {-# INLINE index #-} +-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+indexMaybe :: ByteString -> Int64 -> Maybe Char+indexMaybe = (fmap w2c .) . L.indexMaybe+{-# INLINE indexMaybe #-}++-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+(!?) :: ByteString -> Int64 -> Maybe Char+(!?) = indexMaybe+{-# INLINE (!?) #-}+ -- | /O(n)/ The 'elemIndex' function returns the index of the first -- element in the given 'ByteString' which is equal (by memchr) to the -- query element, or 'Nothing' if there is no such element.@@ -550,6 +572,7 @@ -- indices of all elements satisfying the predicate, in ascending order. findIndices :: (Char -> Bool) -> ByteString -> [Int64] findIndices f = L.findIndices (f . w2c)+{-# INLINE findIndices #-} -- | count returns the number of times its argument appears in the ByteString --
Data/ByteString/Lazy/Internal.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE TypeFamilies #-} #if __GLASGOW_HASKELL__ >= 703@@ -41,15 +42,18 @@ -- * Conversion with lists: packing and unpacking packBytes, packChars, unpackBytes, unpackChars,+ -- * Conversions with strict ByteString+ fromStrict, toStrict, ) where import Prelude hiding (concat) import qualified Data.ByteString.Internal as S-import qualified Data.ByteString as S (length, take, drop) -import Data.Word (Word8)+import Data.Word (Word8)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (plusPtr) import Foreign.Storable (Storable(sizeOf)) #if MIN_VERSION_base(4,13,0)@@ -168,12 +172,12 @@ -- invariant :: ByteString -> Bool invariant Empty = True-invariant (Chunk (S.PS _ _ len) cs) = len > 0 && invariant cs+invariant (Chunk (S.BS _ len) cs) = len > 0 && invariant cs -- | In a form that checks the invariant lazily. checkInvariant :: ByteString -> ByteString checkInvariant Empty = Empty-checkInvariant (Chunk c@(S.PS _ _ len) cs)+checkInvariant (Chunk c@(S.BS _ len) cs) | len > 0 = Chunk c (checkInvariant cs) | otherwise = error $ "Data.ByteString.Lazy: invariant violation:" ++ show (Chunk c cs)@@ -182,8 +186,8 @@ -- | Smart constructor for 'Chunk'. Guarantees the data type invariant. chunk :: S.ByteString -> ByteString -> ByteString-chunk c@(S.PS _ _ len) cs | len == 0 = cs- | otherwise = Chunk c cs+chunk c@(S.BS _ len) cs | len == 0 = cs+ | otherwise = Chunk c cs {-# INLINE chunk #-} -- | Consume the chunks of a lazy ByteString with a natural right fold.@@ -236,26 +240,26 @@ eq Empty Empty = True eq Empty _ = False 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+eq (Chunk a@(S.BS ap al) as) (Chunk b@(S.BS bp bl) bs) =+ case compare al bl of+ LT -> a == S.BS bp al && eq as (Chunk (S.BS (S.plusForeignPtr bp al) (bl - al)) bs)+ EQ -> a == b && eq as bs+ GT -> S.BS ap bl == b && eq (Chunk (S.BS (S.plusForeignPtr ap bl) (al - bl)) as) bs cmp :: ByteString -> ByteString -> Ordering cmp Empty Empty = EQ cmp Empty _ = LT cmp _ Empty = GT-cmp (Chunk a as) (Chunk b bs) =- case compare (S.length a) (S.length b) of- LT -> case compare a (S.take (S.length a) b) of- EQ -> cmp as (Chunk (S.drop (S.length a) b) bs)+cmp (Chunk a@(S.BS ap al) as) (Chunk b@(S.BS bp bl) bs) =+ case compare al bl of+ LT -> case compare a (S.BS bp al) of+ EQ -> cmp as (Chunk (S.BS (S.plusForeignPtr bp al) (bl - al)) bs) result -> result EQ -> case compare a b of EQ -> cmp as bs result -> result- GT -> case compare (S.take (S.length b) a) b of- EQ -> cmp (Chunk (S.drop (S.length b) a) as) bs+ GT -> case compare (S.BS ap bl) b of+ EQ -> cmp (Chunk (S.BS (S.plusForeignPtr ap bl) (al - bl)) as) bs result -> result append :: ByteString -> ByteString -> ByteString@@ -268,3 +272,51 @@ go (Chunk c cs) css = Chunk c (go cs css) to [] = Empty to (cs:css) = go cs css++------------------------------------------------------------------------+-- Conversions++-- |/O(1)/ Convert a strict 'ByteString' into a lazy 'ByteString'.+fromStrict :: S.ByteString -> ByteString+fromStrict (S.BS _ 0) = Empty+fromStrict bs = Chunk bs Empty++-- |/O(n)/ Convert a lazy 'ByteString' into a strict 'ByteString'.+--+-- Note that this is an /expensive/ operation that forces the whole lazy+-- ByteString into memory and then copies all the data. If possible, try to+-- avoid converting back and forth between strict and lazy bytestrings.+--+toStrict :: ByteString -> S.ByteString+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+ -- It's still possible that the result is empty+ goLen0 _ Empty = S.BS S.nullForeignPtr 0+ goLen0 cs0 (Chunk (S.BS _ 0) cs) = goLen0 cs0 cs+ goLen0 cs0 (Chunk c cs) = goLen1 cs0 c cs++ -- It's still possible that the result is a single chunk+ goLen1 _ bs Empty = bs+ goLen1 cs0 bs (Chunk (S.BS _ 0) cs) = goLen1 cs0 bs cs+ goLen1 cs0 (S.BS _ bl) (Chunk (S.BS _ cl) cs) =+ goLen cs0 (S.checkedAdd "Lazy.concat" bl cl) cs++ -- General case, just find the total length we'll need+ goLen cs0 !total (Chunk (S.BS _ cl) cs) =+ goLen cs0 (S.checkedAdd "Lazy.concat" total cl) cs+ goLen cs0 total Empty =+ S.unsafeCreate total $ \ptr -> goCopy cs0 ptr++ -- Copy the data+ goCopy Empty !_ = return ()+ goCopy (Chunk (S.BS _ 0 ) cs) !ptr = goCopy cs ptr+ goCopy (Chunk (S.BS fp len) cs) !ptr = do+ withForeignPtr fp $ \p -> do+ S.memcpy ptr p len+ goCopy cs (ptr `plusPtr` len)+-- See the comment on Data.ByteString.Internal.concat for some background on+-- this implementation.
Data/ByteString/Short.hs view
@@ -77,7 +77,7 @@ unpack, -- * Other operations- empty, null, length, index,+ empty, null, length, index, indexMaybe, (!?), -- * Low level conversions -- ** Packing 'Foreign.C.String.CString's and pointers
Data/ByteString/Short/Internal.hs view
@@ -31,7 +31,7 @@ unpack, -- * Other operations- empty, null, length, index, unsafeIndex,+ empty, null, length, index, indexMaybe, (!?), unsafeIndex, -- * Low level operations createFromPtr, copyToPtr,@@ -66,7 +66,6 @@ import Foreign.C.Types (CSize, CInt, CLong) #endif import Foreign.Marshal.Alloc (allocaBytes)-import Foreign.Ptr import Foreign.ForeignPtr (touchForeignPtr) #if MIN_VERSION_base(4,5,0) import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)@@ -103,11 +102,12 @@ import GHC.Word import Prelude ( Eq(..), Ord(..), Ordering(..), Read(..), Show(..)- , ($), error, (++), (.)+ , ($), ($!), error, (++), (.) , String, userError , Bool(..), (&&), otherwise , (+), (-), fromIntegral- , return )+ , return+ , Maybe(..) ) -- | A compact representation of a 'Word8' vector.@@ -215,6 +215,26 @@ | i >= 0 && i < length sbs = unsafeIndex sbs i | otherwise = indexError sbs i +-- | /O(1)/ 'ShortByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+indexMaybe :: ShortByteString -> Int -> Maybe Word8+indexMaybe sbs i+ | i >= 0 && i < length sbs = Just $! unsafeIndex sbs i+ | otherwise = Nothing+{-# INLINE indexMaybe #-}++-- | /O(1)/ 'ShortByteString' index, starting from 0, that returns 'Just' if:+--+-- > 0 <= n < length bs+--+-- @since 0.11.0.0+(!?) :: ShortByteString -> Int -> Maybe Word8+(!?) = indexMaybe+{-# INLINE (!?) #-}+ unsafeIndex :: ShortByteString -> Int -> Word8 unsafeIndex sbs = indexWord8Array (asBA sbs) @@ -250,10 +270,10 @@ toShort !bs = unsafeDupablePerformIO (toShortIO bs) toShortIO :: ByteString -> IO ShortByteString-toShortIO (PS fptr off len) = do+toShortIO (BS fptr len) = do mba <- stToIO (newByteArray len) let ptr = unsafeForeignPtrToPtr fptr- stToIO (copyAddrToByteArray (ptr `plusPtr` off) mba 0 len)+ stToIO (copyAddrToByteArray ptr mba 0 len) touchForeignPtr fptr BA# ba# <- stToIO (unsafeFreezeByteArray mba) return (SBS ba# LEN(len))@@ -272,7 +292,7 @@ stToIO (copyByteArray (asBA sbs) 0 mba 0 len) let fp = ForeignPtr (byteArrayContents# (unsafeCoerce# mba#)) (PlainPtr mba#)- return (PS fp 0 len)+ return (BS fp len) #else -- Before base 4.6 ForeignPtrContents is not exported from GHC.ForeignPtr -- so we cannot get direct access to the mbarr#@@ -281,7 +301,7 @@ let ptr = unsafeForeignPtrToPtr fptr stToIO (copyByteArrayToAddr (asBA sbs) 0 ptr len) touchForeignPtr fptr- return (PS fptr 0 len)+ return (BS fptr len) #endif @@ -553,7 +573,7 @@ #else copyAddrToByteArray# src dst dst_off len s =- unIO_ (memcpy_AddrToByteArray dst (clong dst_off) src 0 (csize len)) s+ unIO_ (memcpy_AddrToByteArray dst (csize dst_off) src 0 (csize len)) s copyAddrToByteArray0 :: Addr# -> MutableByteArray# s -> Int# -> State# RealWorld -> State# RealWorld@@ -567,14 +587,14 @@ = copyAddrToByteArray0 src dst len s #-} foreign import ccall unsafe "fpstring.h fps_memcpy_offsets"- memcpy_AddrToByteArray :: MutableByteArray# s -> CLong -> Addr# -> CLong -> CSize -> IO ()+ memcpy_AddrToByteArray :: MutableByteArray# s -> CSize -> Addr# -> CSize -> CSize -> IO () foreign import ccall unsafe "string.h memcpy" memcpy_AddrToByteArray0 :: MutableByteArray# s -> Addr# -> CSize -> IO () copyByteArrayToAddr# src src_off dst len s =- unIO_ (memcpy_ByteArrayToAddr dst 0 src (clong src_off) (csize len)) s+ unIO_ (memcpy_ByteArrayToAddr dst 0 src (csize src_off) (csize len)) s copyByteArrayToAddr0 :: ByteArray# -> Addr# -> Int# -> State# RealWorld -> State# RealWorld@@ -588,7 +608,7 @@ = copyByteArrayToAddr0 src dst len s #-} foreign import ccall unsafe "fpstring.h fps_memcpy_offsets"- memcpy_ByteArrayToAddr :: Addr# -> CLong -> ByteArray# -> CLong -> CSize -> IO ()+ memcpy_ByteArrayToAddr :: Addr# -> CSize -> ByteArray# -> CSize -> CSize -> IO () foreign import ccall unsafe "string.h memcpy" memcpy_ByteArrayToAddr0 :: Addr# -> ByteArray# -> CSize -> IO ()@@ -597,9 +617,6 @@ unIO_ :: IO () -> State# RealWorld -> State# RealWorld unIO_ io s = case unIO io s of (# s, _ #) -> s -clong :: Int# -> CLong-clong i# = fromIntegral (I# i#)- csize :: Int# -> CSize csize i# = fromIntegral (I# i#) #endif@@ -609,14 +626,13 @@ #else copyByteArray# src src_off dst dst_off len s = unST_ (unsafeIOToST- (memcpy_ByteArray dst (clong dst_off) src (clong src_off) (csize len))) s+ (memcpy_ByteArray dst (csize dst_off) src (csize src_off) (csize len))) s where unST (ST st) = st unST_ st s = case unST st s of (# s, _ #) -> s foreign import ccall unsafe "fpstring.h fps_memcpy_offsets"- memcpy_ByteArray :: MutableByteArray# s -> CLong- -> ByteArray# -> CLong -> CSize -> IO ()+ memcpy_ByteArray :: MutableByteArray# s -> CSize -> ByteArray# -> CSize -> CSize -> IO () #endif -- | /O(n)./ Construct a new @ShortByteString@ from a @CString@. The
Data/ByteString/Unsafe.hs view
@@ -51,7 +51,7 @@ import Data.ByteString.Internal import Foreign.ForeignPtr (newForeignPtr_, newForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr, plusPtr, castPtr)+import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (Storable(..)) import Foreign.C.String (CString, CStringLen)@@ -75,30 +75,30 @@ -- check for the empty case, so there is an obligation on the programmer -- to provide a proof that the ByteString is non-empty. unsafeHead :: ByteString -> Word8-unsafeHead (PS x s l) = assert (l > 0) $- accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peekByteOff p s+unsafeHead (BS x l) = assert (l > 0) $+ accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peek p {-# INLINE unsafeHead #-} -- | A variety of 'tail' for non-empty ByteStrings. 'unsafeTail' omits the -- check for the empty case. As with 'unsafeHead', the programmer must -- provide a separate proof that the ByteString is non-empty. unsafeTail :: ByteString -> ByteString-unsafeTail (PS ps s l) = assert (l > 0) $ PS ps (s+1) (l-1)+unsafeTail (BS ps l) = assert (l > 0) $ BS (plusForeignPtr ps 1) (l-1) {-# INLINE unsafeTail #-} -- | A variety of 'init' for non-empty ByteStrings. 'unsafeInit' omits the -- check for the empty case. As with 'unsafeHead', the programmer must -- provide a separate proof that the ByteString is non-empty. unsafeInit :: ByteString -> ByteString-unsafeInit (PS ps s l) = assert (l > 0) $ PS ps s (l-1)+unsafeInit (BS ps l) = assert (l > 0) $ BS ps (l-1) {-# INLINE unsafeInit #-} -- | A variety of 'last' for non-empty ByteStrings. 'unsafeLast' omits the -- check for the empty case. As with 'unsafeHead', the programmer must -- provide a separate proof that the ByteString is non-empty. unsafeLast :: ByteString -> Word8-unsafeLast (PS x s l) = assert (l > 0) $- accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+l-1)+unsafeLast (BS x l) = assert (l > 0) $+ accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peekByteOff p (l-1) {-# INLINE unsafeLast #-} -- | Unsafe 'ByteString' index (subscript) operator, starting from 0, returning a 'Word8'@@ -106,20 +106,20 @@ -- obligation on the programmer to ensure the bounds are checked in some -- other way. unsafeIndex :: ByteString -> Int -> Word8-unsafeIndex (PS x s l) i = assert (i >= 0 && i < l) $- accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+i)+unsafeIndex (BS x l) i = assert (i >= 0 && i < l) $+ accursedUnutterablePerformIO $ withForeignPtr x $ \p -> peekByteOff p i {-# INLINE unsafeIndex #-} -- | A variety of 'take' which omits the checks on @n@ so there is an -- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@. unsafeTake :: Int -> ByteString -> ByteString-unsafeTake n (PS x s l) = assert (0 <= n && n <= l) $ PS x s n+unsafeTake n (BS x l) = assert (0 <= n && n <= l) $ BS x n {-# INLINE unsafeTake #-} -- | A variety of 'drop' which omits the checks on @n@ so there is an -- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@. unsafeDrop :: Int -> ByteString -> ByteString-unsafeDrop n (PS x s l) = assert (0 <= n && n <= l) $ PS x (s+n) (l-n)+unsafeDrop n (BS x l) = assert (0 <= n && n <= l) $ BS (plusForeignPtr x n) (l-n) {-# INLINE unsafeDrop #-} @@ -143,7 +143,7 @@ unsafePackAddressLen :: Int -> Addr# -> IO ByteString unsafePackAddressLen len addr# = do p <- newForeignPtr_ (Ptr addr#)- return $ PS p 0 len+ return $ BS p len {-# INLINE unsafePackAddressLen #-} -- | /O(1)/ Construct a 'ByteString' given a Ptr Word8 to a buffer, a@@ -158,7 +158,7 @@ unsafePackCStringFinalizer :: Ptr Word8 -> Int -> IO () -> IO ByteString unsafePackCStringFinalizer p l f = do fp <- FC.newForeignPtr p f- return $ PS fp 0 l+ return $ BS fp l -- | Explicitly run the finaliser associated with a 'ByteString'. -- References to this value after finalisation may generate invalid memory@@ -170,7 +170,7 @@ -- ever generated from the underlying byte array are no longer live. -- unsafeFinalize :: ByteString -> IO ()-unsafeFinalize (PS p _ _) = FC.finalizeForeignPtr p+unsafeFinalize (BS p _) = FC.finalizeForeignPtr p ------------------------------------------------------------------------ -- Packing CStrings into ByteStrings@@ -188,7 +188,7 @@ unsafePackCString cstr = do fp <- newForeignPtr_ (castPtr cstr) l <- c_strlen cstr- return $! PS fp 0 (fromIntegral l)+ return $! BS fp (fromIntegral l) -- | /O(1)/ Build a 'ByteString' from a 'CStringLen'. This value will -- have /no/ finalizer associated with it, and will not be garbage@@ -202,7 +202,7 @@ unsafePackCStringLen :: CStringLen -> IO ByteString unsafePackCStringLen (ptr,len) = do fp <- newForeignPtr_ (castPtr ptr)- return $! PS fp 0 (fromIntegral len)+ return $! BS fp (fromIntegral len) -- | /O(n)/ Build a 'ByteString' from a malloced 'CString'. This value will -- have a @free(3)@ finalizer associated to it.@@ -219,7 +219,7 @@ unsafePackMallocCString cstr = do fp <- newForeignPtr c_free_finalizer (castPtr cstr) len <- c_strlen cstr- return $! PS fp 0 (fromIntegral len)+ return $! BS fp (fromIntegral len) -- | /O(1)/ Build a 'ByteString' from a malloced 'CStringLen'. This -- value will have a @free(3)@ finalizer associated to it.@@ -235,7 +235,7 @@ unsafePackMallocCStringLen :: CStringLen -> IO ByteString unsafePackMallocCStringLen (cstr, len) = do fp <- newForeignPtr c_free_finalizer (castPtr cstr)- return $! PS fp 0 len+ return $! BS fp len -- --------------------------------------------------------------------- @@ -265,7 +265,7 @@ -- after this. -- unsafeUseAsCString :: ByteString -> (CString -> IO a) -> IO a-unsafeUseAsCString (PS ps s _) ac = withForeignPtr ps $ \p -> ac (castPtr p `plusPtr` s)+unsafeUseAsCString (BS ps _) ac = withForeignPtr ps $ \p -> ac (castPtr p) -- | /O(1) construction/ Use a 'ByteString' with a function requiring a -- 'CStringLen'.@@ -284,4 +284,4 @@ -- -- If 'Data.ByteString.empty' is given, it will pass @('Foreign.Ptr.nullPtr', 0)@. unsafeUseAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a-unsafeUseAsCStringLen (PS ps s l) f = withForeignPtr ps $ \p -> f (castPtr p `plusPtr` s,l)+unsafeUseAsCStringLen (BS ps l) f = withForeignPtr ps $ \p -> f (castPtr p,l)
README.md view
@@ -1,9 +1,9 @@-## ByteString: Fast, Packed Strings of Bytes+# ByteString: Fast, Packed Strings of Bytes -[](http://travis-ci.org/haskell/bytestring)+[](http://travis-ci.org/haskell/bytestring) [](https://hackage.haskell.org/package/bytestring) [](https://matrix.hackage.haskell.org/package/bytestring) [](http://stackage.org/lts/package/bytestring) [](http://stackage.org/nightly/package/bytestring) This library provides the `Data.ByteString` module -- strict and lazy-byte arrays manipulable as strings -- providing very time/space-efficient +byte arrays manipulable as strings -- providing very time/space-efficient string and IO operations. For very large data requirements, or constraints on heap size,@@ -16,20 +16,10 @@ Requirements: * Cabal 1.10 or greater- * cabal-install- * GHC 6.12 or greater--Building:-```-cabal install-```--You can run the testsuite as follows:-``` -cabal test-```+ * GHC 7.0 or greater ### Authors+ `ByteString` was derived from the GHC `PackedString` library, originally written by Bryan O'Sullivan, and then by Simon Marlow. It was adapted and greatly extended for darcs by David Roundy and
bytestring.cabal view
@@ -1,5 +1,5 @@ Name: bytestring-Version: 0.10.12.1+Version: 0.11.0.0 Synopsis: Fast, compact, strict and lazy byte strings with a list interface Description: An efficient compact, immutable byte string type (both strict and lazy)@@ -51,7 +51,7 @@ Author: Don Stewart, Duncan Coutts-Maintainer: Haskell Bytestring Team <andrew.lelechenko@gmail.com>, Core Libraries Committee+Maintainer: Duncan Coutts <duncan@community.haskell.org> Homepage: https://github.com/haskell/bytestring Bug-reports: https://github.com/haskell/bytestring/issues Tested-With: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2,@@ -70,7 +70,7 @@ default: False library- build-depends: base >= 4.2 && < 5, ghc-prim, deepseq+ build-depends: base >= 4.3 && < 5, ghc-prim, deepseq exposed-modules: Data.ByteString Data.ByteString.Char8@@ -89,12 +89,6 @@ -- perhaps only exposed temporarily Data.ByteString.Builder.Internal Data.ByteString.Builder.Prim.Internal-- -- sigh, we decided to rename shortly after making- -- an initial release, so these are here for compat- Data.ByteString.Lazy.Builder- Data.ByteString.Lazy.Builder.Extras- Data.ByteString.Lazy.Builder.ASCII other-modules: Data.ByteString.Builder.ASCII Data.ByteString.Builder.Prim.Binary
cbits/fpstring.c view
@@ -32,7 +32,7 @@ #include "fpstring.h" /* copy a string in reverse */-void fps_reverse(unsigned char *q, unsigned char *p, unsigned long n) {+void fps_reverse(unsigned char *q, unsigned char *p, size_t n) { p += n-1; while (n-- != 0) *q++ = *p--;@@ -42,7 +42,7 @@ of the duplicated string */ void fps_intersperse(unsigned char *q, unsigned char *p,- unsigned long n,+ size_t n, unsigned char c) { while (n > 1) {@@ -55,7 +55,7 @@ } /* find maximum char in a packed string */-unsigned char fps_maximum(unsigned char *p, unsigned long len) {+unsigned char fps_maximum(unsigned char *p, size_t len) { unsigned char *q, c = *p; for (q = p; q < p + len; q++) if (*q > c)@@ -64,7 +64,7 @@ } /* find minimum char in a packed string */-unsigned char fps_minimum(unsigned char *p, unsigned long len) {+unsigned char fps_minimum(unsigned char *p, size_t len) { unsigned char *q, c = *p; for (q = p; q < p + len; q++) if (*q < c)@@ -73,8 +73,8 @@ } /* count the number of occurences of a char in a string */-unsigned long fps_count(unsigned char *p, unsigned long len, unsigned char w) {- unsigned long c;+size_t fps_count(unsigned char *p, size_t len, unsigned char w) {+ size_t c; for (c = 0; len-- != 0; ++p) if (*p == w) ++c;@@ -84,7 +84,14 @@ /* This wrapper is here so that we can copy a sub-range of a ByteArray#. We cannot construct a pointer to the interior of an unpinned ByteArray#, except by doing an unsafe ffi call, and adjusting the pointer C-side. */-void * fps_memcpy_offsets(void *dst, unsigned long dst_off,- const void *src, unsigned long src_off, size_t n) {+void * fps_memcpy_offsets(void *dst, size_t dst_off, const void *src, size_t src_off, size_t n) { return memcpy(dst + dst_off, src + src_off, n);+}++int fps_compare(const void *a, const void *b) {+ return (int)*(unsigned char*)a - (int)*(unsigned char*)b;+}++void fps_sort(unsigned char *p, size_t len) {+ return qsort(p, len, 1, fps_compare); }
include/fpstring.h view
@@ -1,9 +1,9 @@- #include <string.h>--void fps_reverse(unsigned char *dest, unsigned char *from, unsigned long len);-void fps_intersperse(unsigned char *dest, unsigned char *from, unsigned long len, unsigned char c);-unsigned char fps_maximum(unsigned char *p, unsigned long len);-unsigned char fps_minimum(unsigned char *p, unsigned long len);-unsigned long fps_count(unsigned char *p, unsigned long len, unsigned char w);+#include <stdlib.h> +void fps_reverse(unsigned char *dest, unsigned char *from, size_t len);+void fps_intersperse(unsigned char *dest, unsigned char *from, size_t len, unsigned char c);+unsigned char fps_maximum(unsigned char *p, size_t len);+unsigned char fps_minimum(unsigned char *p, size_t len);+size_t fps_count(unsigned char *p, size_t len, unsigned char w);+void fps_sort(unsigned char *p, size_t len);