diff --git a/Data/ByteString.hs b/Data/ByteString.hs index 801afcea8..34530bb46 100644 --- a/Data/ByteString.hs +++ b/Data/ByteString.hs @@ -295,7 +295,7 @@ finiteBitSize = bitSize -- | /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 +352,13 @@ unpackFoldr bs k z = foldr k z bs -- | /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 +369,15 @@ infixl 5 `snoc` -- | /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 -> withForeignPtr 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 -> withForeignPtr 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 +386,54 @@ snoc (PS x s l) c = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do -- | /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 $ withForeignPtr 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 $ withForeignPtr x - $ \p -> peekByteOff p s, - PS x (s+1) (l-1)) + $ \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 $ - withForeignPtr 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 $ - withForeignPtr x $ \p -> peekByteOff p (s+l-1)) + withForeignPtr x $ \p -> peekByteOff p (l-1)) {-# INLINE unsnoc #-} -- | /O(n)/ Append two ByteStrings @@ -447,8 +447,8 @@ append = mappend -- | /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 $ withForeignPtr 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 +461,18 @@ map f (PS fp s len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> -- | /O(n)/ 'reverse' @xs@ efficiently returns the elements of @xs@ in reverse order. reverse :: ByteString -> ByteString -reverse (PS x s l) = unsafeCreate l $ \p -> withForeignPtr 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 -> withForeignPtr x $ \f -> - c_intersperse p (f `plusPtr` s) (fromIntegral l) c + c_intersperse p f (fromIntegral l) c -- | The 'transpose' function transposes the rows and columns of its -- 'ByteString' argument. @@ -487,9 +487,9 @@ transpose ps = P.map pack . List.transpose . P.map unpack $ ps -- ByteString using the binary operator, from left to right. -- foldl :: (a -> Word8 -> a) -> a -> ByteString -> a -foldl f z (PS fp off len) = +foldl f z (BS fp len) = let p = unsafeForeignPtrToPtr fp - in go (p `plusPtr` (off+len-1)) (p `plusPtr` (off-1)) + in go (p `plusPtr` (len-1)) (p `plusPtr` (-1)) where -- not tail recursive; traverses array right to left go !p !q | p == q = z @@ -503,9 +503,9 @@ foldl f z (PS fp off len) = -- | 'foldl'' is like 'foldl', but strict in the accumulator. -- foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a -foldl' f v (PS fp off len) = +foldl' f v (BS fp len) = accursedUnutterablePerformIO $ withForeignPtr fp $ \p -> - go v (p `plusPtr` off) (p `plusPtr` (off+len)) + go v p (p `plusPtr` len) where -- tail recursive; traverses array left to right go !z !p !q | p == q = return z @@ -517,9 +517,9 @@ foldl' f v (PS fp off len) = -- (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) = +foldr k z (BS fp len) = let p = unsafeForeignPtrToPtr fp - in go (p `plusPtr` off) (p `plusPtr` (off+len)) + in go p (p `plusPtr` len) where -- not tail recursive; traverses array left to right go !p !q | p == q = z @@ -532,9 +532,9 @@ foldr k z (PS fp off len) = -- | 'foldr'' is like 'foldr', but strict in the accumulator. foldr' :: (Word8 -> a -> a) -> a -> ByteString -> a -foldr' k v (PS fp off len) = +foldr' k v (BS fp len) = accursedUnutterablePerformIO $ withForeignPtr fp $ \p -> - go v (p `plusPtr` (off+len-1)) (p `plusPtr` (off-1)) + go v (p `plusPtr` (len-1)) (p `plusPtr` (-1)) where -- tail recursive; traverses array right to left go !z !p !q | p == q = return z @@ -592,9 +592,9 @@ concatMap f = concat . foldr ((:) . f) [] -- | /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 $ withForeignPtr x $ \ptr -> - go (ptr `plusPtr` s) (ptr `plusPtr` (s+l)) +any _ (BS _ 0) = False +any f (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \ptr -> + go ptr (ptr `plusPtr` l) where go !p !q | p == q = return False | otherwise = do c <- peek p @@ -607,9 +607,9 @@ any f (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr x $ \ptr -> -- | /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 $ withForeignPtr x $ \ptr -> - go (ptr `plusPtr` s) (ptr `plusPtr` (s+l)) +all _ (BS _ 0) = True +all f (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \ptr -> + go ptr (ptr `plusPtr` l) where go !p !q | p == q = return True -- end of list | otherwise = do c <- peek p @@ -624,20 +624,20 @@ all f (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr x $ \ptr -> -- 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 $ withForeignPtr x $ \p -> - c_maximum (p `plusPtr` s) (fromIntegral l) + 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 $ withForeignPtr x $ \p -> - c_minimum (p `plusPtr` s) (fromIntegral l) + c_minimum p (fromIntegral l) {-# INLINE minimum #-} ------------------------------------------------------------------------ @@ -647,10 +647,10 @@ minimum xs@(PS x s l) -- 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 $ withForeignPtr fp $ \a -> do +mapAccumL f acc (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> do gp <- mallocByteString len - acc' <- withForeignPtr gp $ \p -> mapAccumL_ acc 0 (a `plusPtr` o) p - return (acc', PS gp 0 len) + acc' <- withForeignPtr gp $ \p -> mapAccumL_ acc 0 a p + return (acc', BS gp len) where mapAccumL_ !s !n !p1 !p2 | n >= len = return s @@ -666,10 +666,10 @@ mapAccumL f acc (PS fp o len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -- 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 $ withForeignPtr fp $ \a -> do +mapAccumR f acc (BS fp len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> do gp <- mallocByteString len - acc' <- withForeignPtr gp $ \p -> mapAccumR_ acc (len-1) (a `plusPtr` o) p - return $! (acc', PS gp 0 len) + acc' <- withForeignPtr gp $ \p -> mapAccumR_ acc (len-1) a p + return $! (acc', BS gp len) where mapAccumR_ !s !n !p !q | n < 0 = return s @@ -694,10 +694,10 @@ mapAccumR f acc (PS fp o len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -- scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString -scanl f v (PS fp s len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> +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) + scanl_ v 0 a (q `plusPtr` 1) where scanl_ !z !n !p !q | n >= len = return () @@ -724,10 +724,10 @@ scanl1 f ps -- | scanr is the right-to-left dual of scanl. scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString -scanr f v (PS fp s len) = unsafeDupablePerformIO $ withForeignPtr fp $ \a -> +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 + scanr_ v (len-1) a q where scanr_ !z !n !p !q | n < 0 = return () @@ -808,27 +808,27 @@ unfoldrN i f x0 -- | /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@, @@ -924,10 +924,10 @@ span p ps = break (not . p) ps -- > span (==99) "abcd" == spanByte 99 "abcd" -- fromEnum 'c' == 99 -- spanByte :: Word8 -> ByteString -> (ByteString, ByteString) -spanByte c ps@(PS x s l) = +spanByte c ps@(BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> - go (p `plusPtr` s) 0 + go p 0 where go !p !i | i >= l = return (ps, empty) | otherwise = do c' <- peekByteOff p i @@ -976,8 +976,8 @@ spanEnd p ps = splitAt (findFromEndUntil (not.p) ps) ps -- > splitWith (==97) [] == [] -- splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString] -splitWith _pred (PS _ _ 0) = [] -splitWith pred_ (PS fp off len) = splitWith0 pred# off len fp +splitWith _pred (BS _ 0) = [] +splitWith pred_ (BS fp len) = splitWith0 pred# 0 len fp where pred# c# = pred_ (W8# c#) splitWith0 !pred' !off' !len' !fp' = @@ -992,11 +992,11 @@ splitWith pred_ (PS fp off len) = splitWith0 pred# off len fp -> IO [ByteString] splitLoop pred' p idx' off' len' fp' - | idx' >= len' = return [PS fp' off' idx'] + | idx' >= len' = return [BS (plusForeignPtr fp' off') idx'] | otherwise = do w <- peekElemOff p (off'+idx') if pred' (case w of W8# w# -> w#) - then return (PS fp' off' idx' : + then return (BS (plusForeignPtr fp' off') idx' : splitWith0 pred' (off'+idx'+1) (len'-idx'-1) fp') else splitLoop pred' p (idx'+1) off' len' fp' {-# INLINE splitWith #-} @@ -1018,18 +1018,18 @@ splitWith pred_ (PS fp off len) = splitWith0 pred# off len fp -- 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 $ withForeignPtr x $ \p -> - memchr (p `plusPtr` (s+n)) + memchr (p `plusPtr` n) w (fromIntegral (l-n)) in if q == nullPtr - then [PS x (s+n) (l-n)] + then [BS (plusForeignPtr x n) (l-n)] else let i = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> - return (q `minusPtr` (p `plusPtr` s)) - in PS x (s+n) (i-n) : loop (i+1) + return (q `minusPtr` p) + in BS (plusForeignPtr x n) (i-n) : loop (i+1) {-# INLINE split #-} @@ -1075,12 +1075,12 @@ intercalate s = concat . List.intersperse s -- 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 -> +intercalateWithByte c f@(BS ffp l) g@(BS fgp m) = unsafeCreate len $ \ptr -> withForeignPtr ffp $ \fp -> withForeignPtr fgp $ \gp -> do - memcpy ptr (fp `plusPtr` s) (fromIntegral l) + 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 #-} @@ -1102,10 +1102,9 @@ index ps n -- 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 $ withForeignPtr 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,15 +1123,15 @@ elemIndexEnd = findIndexEnd . (==) -- 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 $ withForeignPtr x $ \p -> - memchr (p `plusPtr` (n+s)) + memchr (p `plusPtr` n) w (fromIntegral (l - n)) in if q == nullPtr then [] else let i = accursedUnutterablePerformIO $ withForeignPtr x $ \p -> - return (q `minusPtr` (p `plusPtr` s)) + return (q `minusPtr` p) in i : loop (i+1) {-# INLINE elemIndices #-} @@ -1142,15 +1141,15 @@ elemIndices w (PS x s l) = loop 0 -- -- But more efficiently than using length on the intermediate list. count :: Word8 -> ByteString -> Int -count w (PS x s m) = accursedUnutterablePerformIO $ withForeignPtr 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 @@ -1165,7 +1164,7 @@ findIndex k (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr x $ \f -> -- -- @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 @@ -1200,10 +1199,10 @@ notElem c ps = not (elem c ps) -- 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 (f `plusPtr` l) return $! t `minusPtr` p -- actual length where go !f !t !end | f == end = return t @@ -1263,8 +1262,8 @@ partition f s = unsafeDupablePerformIO $ 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 +1292,12 @@ partition f s = unsafeDupablePerformIO $ -- |/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 $ withForeignPtr x1 $ \p1 -> withForeignPtr x2 $ \p2 -> do - i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral l1) + i <- memcmp p1 p2 (fromIntegral l1) return $! i == 0 -- | /O(n)/ The 'stripPrefix' function takes two ByteStrings and returns 'Just' @@ -1307,7 +1306,7 @@ isPrefixOf (PS x1 s1 l1) (PS x2 s2 l2) -- -- @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 @@ -1321,19 +1320,19 @@ stripPrefix bs1@(PS _ _ l1) bs2 -- However, the real implemenation 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 $ withForeignPtr x1 $ \p1 -> withForeignPtr x2 $ \p2 -> do - i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2 `plusPtr` (l2 - l1)) (fromIntegral l1) + 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 @@ -1500,10 +1499,10 @@ zipWith f ps qs -- 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 $ zipWith_ 0 a b where zipWith_ :: Int -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> IO () zipWith_ !n !p1 !p2 !r @@ -1533,7 +1532,7 @@ unzip ls = (pack (P.map fst ls), pack (P.map snd ls)) -- | /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] @@ -1547,10 +1546,10 @@ tails p | null p = [empty] -- | /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) = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do _ <- memset (castPtr arr) 0 (256 * fromIntegral (sizeOf (undefined :: CSize))) - withForeignPtr 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 @@ -1579,10 +1578,10 @@ sort (PS input s l) = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do -- 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 +1589,7 @@ useAsCString (PS fp o l) action = -- 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 +1621,8 @@ packCStringLen (_, len) = -- is needed in the rest of the program. -- copy :: ByteString -> ByteString -copy (PS x s l) = unsafeCreate l $ \p -> withForeignPtr 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 +1695,8 @@ mkBigPS _ pss = return $! concat (P.reverse pss) -- | Outputs a 'ByteString' to the specified 'Handle'. hPut :: Handle -> ByteString -> IO () -hPut _ (PS _ _ 0) = return () -hPut h (PS ps s l) = withForeignPtr 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,8 +1707,8 @@ hPut h (PS ps s l) = withForeignPtr ps $ \p-> hPutBuf h (p `plusPtr` s) l -- function does not work correctly; it behaves identically to 'hPut'. -- hPutNonBlocking :: Handle -> ByteString -> IO ByteString -hPutNonBlocking h bs@(PS ps s l) = do - bytesWritten <- withForeignPtr 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 @@ -1834,7 +1833,7 @@ hGetContentsSizeHint hnd = readChunks chunks sz sz' = do fp <- mallocByteString sz readcount <- withForeignPtr fp $ \buf -> hGetBuf hnd buf sz - let chunk = PS fp 0 readcount + 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,10 +1891,10 @@ appendFile = modifyFile AppendMode -- | '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) = +findIndexOrEnd k (BS x l) = accursedUnutterablePerformIO $ withForeignPtr x $ \f -> - go (f `plusPtr` s) 0 + go f 0 where go !ptr !n | n >= l = return l | otherwise = do w <- peek ptr @@ -1923,7 +1922,7 @@ moduleErrorMsg fun msg = "Data.ByteString." ++ fun ++ ':':' ':msg -- 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)) diff --git a/Data/ByteString/Builder/Internal.hs b/Data/ByteString/Builder/Internal.hs index 52ffc3c61..af71fce8b 100644 --- a/Data/ByteString/Builder/Internal.hs +++ b/Data/ByteString/Builder/Internal.hs @@ -203,7 +203,7 @@ newBuffer size = do {-# 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 :: Int -> S.ByteString -> Builder 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 @@ byteStringCopy = \bs -> builder $ byteStringCopyStep bs {-# 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 @@ byteStringCopyStep (S.PS ifp ioff isize) !k0 br0@(BufferRange op ope) | 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 @@ buildStepToCIOS !(AllocationStrategy nextBuffer bufSize trim) = -- 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 diff --git a/Data/ByteString/Builder/Prim.hs b/Data/ByteString/Builder/Prim.hs index 3aee823f6..7526b6308 100644 --- a/Data/ByteString/Builder/Prim.hs +++ b/Data/ByteString/Builder/Prim.hs @@ -638,10 +638,10 @@ primMapByteStringBounded w = \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 diff --git a/Data/ByteString/Builder/Prim/Internal/Base16.hs b/Data/ByteString/Builder/Prim/Internal/Base16.hs index e27424f07..aa80dd176 100644 --- a/Data/ByteString/Builder/Prim/Internal/Base16.hs +++ b/Data/ByteString/Builder/Prim/Internal/Base16.hs @@ -48,7 +48,7 @@ import Foreign 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) diff --git a/Data/ByteString/Char8.hs b/Data/ByteString/Char8.hs index 6a01e6582..c3b0c4758 100644 --- a/Data/ByteString/Char8.hs +++ b/Data/ByteString/Char8.hs @@ -817,12 +817,12 @@ unsafeHead = w2c . B.unsafeHead -- > break isSpace == breakSpace -- breakSpace :: ByteString -> (ByteString,ByteString) -breakSpace (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr 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 #-} @@ -840,9 +840,9 @@ firstspace !ptr !n !m -- -- @since 0.10.12.0 dropSpace :: ByteString -> ByteString -dropSpace (PS x s l) = accursedUnutterablePerformIO $ withForeignPtr 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 diff --git a/Data/ByteString/Internal.hs b/Data/ByteString/Internal.hs index 60c83233b..4f88f4415 100644 --- a/Data/ByteString/Internal.hs +++ b/Data/ByteString/Internal.hs @@ -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,7 +30,12 @@ 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, @@ -50,6 +58,8 @@ module Data.ByteString.Internal ( -- * 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 @@ -76,7 +86,10 @@ module Data.ByteString.Internal ( -- * Deprecated and unmentionable accursedUnutterablePerformIO, -- :: IO a -> a - inlinePerformIO -- :: IO a -> a + inlinePerformIO, -- :: IO a -> a + + -- * Exported compatibility shim + plusForeignPtr ) where import Prelude hiding (concat, null) @@ -106,6 +119,7 @@ import Data.List.NonEmpty (NonEmpty ((:|))) import Data.Monoid (Monoid(..)) #endif + import Control.DeepSeq (NFData(rnf)) import Data.String (IsString(..)) @@ -140,11 +154,37 @@ import GHC.IOBase (IO(IO),RawBuffer,unsafeDupablePerformIO) import GHC.ForeignPtr (ForeignPtr(ForeignPtr) ,newForeignPtr_, mallocPlainForeignPtrBytes) +#if MIN_VERSION_base(4,10,0) +import GHC.ForeignPtr (plusForeignPtr) +#else +import GHC.Types (Int (..)) +import GHC.Prim (plusAddr#) +#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 @@ -154,11 +194,31 @@ import GHC.Ptr (Ptr(..), castPtr) -- "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 @@ -172,7 +232,7 @@ instance Semigroup ByteString where #endif instance Monoid ByteString where - mempty = PS nullForeignPtr 0 0 + mempty = BS nullForeignPtr 0 #if MIN_VERSION_base(4,9,0) mappend = (<>) #else @@ -181,7 +241,7 @@ instance Monoid ByteString where mconcat = concat instance NFData ByteString where - rnf PS{} = () + rnf BS{} = () instance Show ByteString where showsPrec p ps r = showsPrec p (unpackChars ps) r @@ -264,7 +324,7 @@ unsafePackAddress :: Addr# -> IO ByteString unsafePackAddress addr# = do 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# @@ -305,22 +365,22 @@ unpackChars :: ByteString -> [Char] 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 @@ -328,9 +388,9 @@ unpackAppendCharsLazy (PS fp off len) cs -- 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 @@ -338,9 +398,9 @@ unpackAppendBytesStrict (PS fp off len) xs = 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 @@ -366,14 +426,25 @@ fromForeignPtr :: ForeignPtr Word8 -> 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 @@ -398,7 +469,7 @@ create :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString 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' @@ -408,7 +479,7 @@ createUptoN :: Int -> (Ptr Word8 -> IO Int) -> IO ByteString 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 @@ -419,7 +490,7 @@ createUptoN' :: Int -> (Ptr Word8 -> IO (Int, a)) -> IO (ByteString, a) 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 @@ -436,7 +507,7 @@ createAndTrim l f = do 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 #-} @@ -446,7 +517,7 @@ createAndTrim' l f = do 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) @@ -461,32 +532,32 @@ mallocByteString = mallocPlainForeignPtrBytes -- 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 $ withForeignPtr fp1 $ \p1 -> withForeignPtr fp2 $ \p2 -> do - i <- memcmp (p1 `plusPtr` off1) (p2 `plusPtr` off2) (min len1 len2) + 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 - withForeignPtr fp1 $ \p1 -> memcpy destptr1 (p1 `plusPtr` off1) len1 - withForeignPtr 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 @@ -509,26 +580,26 @@ concat = \bss0 -> goLen0 bss0 bss0 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 - withForeignPtr 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 #-} diff --git a/Data/ByteString/Lazy.hs b/Data/ByteString/Lazy.hs index 773894322..9051f07b5 100644 --- a/Data/ByteString/Lazy.hs +++ b/Data/ByteString/Lazy.hs @@ -310,10 +310,10 @@ toStrict = \cs -> goLen0 cs cs -- 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 + 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 `plusPtr` off) len + S.memcpy ptr p len goCopy cs (ptr `plusPtr` len) -- See the comment on Data.ByteString.Internal.concat for some background on -- this implementation. @@ -465,10 +465,10 @@ intersperse _ Empty = Empty 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) = + 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. @@ -1371,9 +1371,9 @@ revChunks cs = L.foldl' (flip chunk) Empty cs -- | '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 diff --git a/Data/ByteString/Lazy/Internal.hs b/Data/ByteString/Lazy/Internal.hs index 3cc83d01b..13be6c3ad 100644 --- a/Data/ByteString/Lazy/Internal.hs +++ b/Data/ByteString/Lazy/Internal.hs @@ -168,12 +168,12 @@ unpackChars (Chunk c cs) = S.unpackAppendCharsLazy c (unpackChars cs) -- 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 +182,8 @@ checkInvariant (Chunk c@(S.PS _ _ len) cs) -- | 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. diff --git a/Data/ByteString/Short/Internal.hs b/Data/ByteString/Short/Internal.hs index f81164957..3d6dd32fe 100644 --- a/Data/ByteString/Short/Internal.hs +++ b/Data/ByteString/Short/Internal.hs @@ -66,7 +66,6 @@ import Foreign.C.Types (CSize(..), CInt(..), CLong(..)) 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) @@ -250,10 +249,10 @@ toShort :: ByteString -> ShortByteString 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 +271,7 @@ fromShortIO sbs = do 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 +280,7 @@ fromShortIO sbs = do let ptr = unsafeForeignPtrToPtr fptr stToIO (copyByteArrayToAddr (asBA sbs) 0 ptr len) touchForeignPtr fptr - return (PS fptr 0 len) + return (BS fptr len) #endif diff --git a/Data/ByteString/Unsafe.hs b/Data/ByteString/Unsafe.hs index a10d27be5..01a8121d0 100644 --- a/Data/ByteString/Unsafe.hs +++ b/Data/ByteString/Unsafe.hs @@ -51,7 +51,7 @@ module Data.ByteString.Unsafe ( 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 @@ import GHC.Ptr (Ptr(..)) -- 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 @@ unsafeLast (PS x s l) = assert (l > 0) $ -- 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 @@ unsafeDrop n (PS x s l) = assert (0 <= n && n <= l) $ PS x (s+n) (l-n) 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 @@ unsafePackAddressLen len addr# = do 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 @@ unsafePackCStringFinalizer p l f = do -- 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 :: CString -> IO ByteString 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 @@ unsafePackCString cstr = do 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 :: CString -> IO ByteString 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 @@ unsafePackMallocCString cstr = do 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 @@ unsafePackMallocCStringLen (cstr, len) = do -- 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 @@ unsafeUseAsCString (PS ps s _) ac = withForeignPtr ps $ \p -> ac (castPtr p `plu -- -- 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) diff --git a/bytestring.cabal b/bytestring.cabal index b2e82d826..d7cae1517 100644 --- a/bytestring.cabal +++ b/bytestring.cabal @@ -1,5 +1,5 @@ Name: bytestring -Version: 0.10.12.0 +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)