foldr, -- :: (Word8 -> a -> a) -> a -> ByteString -> a
foldl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+ foldl', -- :: (a -> Word8 -> a) -> a -> ByteString -> a
-- ** Special folds
concat, -- :: [ByteString] -> ByteString
-- * Generating and unfolding ByteStrings
replicate, -- :: Int -> Word8 -> ByteString
- unfoldrN, -- :: (Word8 -> Maybe (Word8, Word8)) -> Word8 -> ByteString
+ unfoldrN, -- :: (a -> Maybe (Word8, a)) -> a -> ByteString
-- * Substrings
#endif
noAL, NoAL, loopArr, loopAcc, loopSndAcc,
- loopU, mapEFL, filterEFL, foldEFL, fuseEFL,
+ loopU, mapEFL, filterEFL, foldEFL, foldEFL', fuseEFL,
filterF, mapF
) where
-- | /O(1)/ 'length' returns the length of a ByteString as an 'Int'.
length :: ByteString -> Int
length (PS _ _ l) = l
-{-# INLINE length #-}
+
+#if defined(__GLASGOW_HASKELL__)
+{-# INLINE [1] length #-}
+#endif
+
+{-#
+
+-- Translate length into a loop.
+-- Performace ok, but allocates too much, so disable for now.
+
+ "length/loop" forall f acc s .
+ length (loopArr (loopU f acc s)) = foldl' (const . (+1)) (0::Int) (loopArr (loopU f acc s))
+
+ #-}
-- | /O(n)/ 'cons' is analogous to (:) for lists, but of different
-- complexity, as it requires a memcpy.
cons :: Word8 -> ByteString -> ByteString
cons c (PS x s l) = create (l+1) $ \p -> withForeignPtr x $ \f -> do
- memcpy (p `plusPtr` 1) (f `plusPtr` s) (fromIntegral l)
poke p c
+ memcpy (p `plusPtr` 1) (f `plusPtr` s) (fromIntegral l)
{-# INLINE cons #-}
-- todo fuse
lgo (f z c) (p `plusPtr` 1) q
-}
+-- | 'foldl\'' is like foldl, but strict in the accumulator.
+foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a
+foldl' f z = loopAcc . loopU (foldEFL' f) z
+{-# 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.
-- The following equation connects the depth-limited unfoldr to the List unfoldr:
--
-- > unfoldrN n == take n $ List.unfoldr
-unfoldrN :: Int -> (Word8 -> Maybe (Word8, Word8)) -> Word8 -> ByteString
+unfoldrN :: Int -> (a -> Maybe (Word8, a)) -> a -> ByteString
unfoldrN i f w = inlinePerformIO $ generate i $ \p -> go p w 0
where
STRICT3(go)
-- constant strings created when compiled:
errorEmptyList :: String -> a
errorEmptyList fun = error ("Data.ByteString." ++ fun ++ ": empty ByteString")
-{-# INLINE errorEmptyList #-}
+{-# NOINLINE errorEmptyList #-}
-- 'findIndexOrEnd' is a variant of findIndex, that returns the length
-- of the string if no element is found, rather than Nothing.
{-# INLINE [1] foldEFL #-}
#endif
+-- | A strict foldEFL.
+foldEFL' :: (acc -> Word8 -> acc) -> (acc -> Word8 -> (acc, Maybe Word8))
+foldEFL' f = \a e -> let a' = f a e in a' `seq` (a', Nothing)
+#if defined(__GLASGOW_HASKELL__)
+{-# INLINE [1] foldEFL' #-}
+#endif
+
-- | No accumulator
noAL :: NoAL
noAL = NoAL
------------------------------------------------------------------------
+--
+-- size, and then percentage.
+--
+
-- | Iteration over over ByteStrings
loopU :: (acc -> Word8 -> (acc, Maybe Word8)) -- ^ mapping & folding, once per elem
-> acc -- ^ initial acc value
(ptr,n,acc) <- withForeignPtr fp $ \p -> do
(acc, i') <- go (a `plusPtr` s) p start
if i' == i
- then return (fp,i,acc) -- no realloc for map
+ then return (fp,i',acc) -- no realloc for map
else do fp_ <- mallocByteString (i'+1) -- realloc
withForeignPtr fp_ $ \p' -> do
memcpy p' p (fromIntegral i') -- can't avoid this, right?
{-# RULES
-"Array fusion!" forall em1 em2 start1 start2 arr.
+"loop/loop fusion!" forall em1 em2 start1 start2 arr.
loopU em2 start2 (loopArr (loopU em1 start1 arr)) =
loopSndAcc (loopU (em1 `fuseEFL` em2) (start1, start2) arr)
foldr, -- :: (Char -> a -> a) -> a -> ByteString -> a
foldl1, -- :: (Char -> Char -> Char) -> ByteString -> Char
foldr1, -- :: (Char -> Char -> Char) -> ByteString -> Char
+ foldl', -- :: (a -> Char -> a) -> a -> ByteString -> a
-- ** Special folds
concat, -- :: [ByteString] -> ByteString
-- * Generating and unfolding ByteStrings
replicate, -- :: Int -> Char -> ByteString
- unfoldrN, -- :: (Char -> Maybe (Char, Char)) -> Char -> ByteString
+ unfoldrN, -- :: (a -> Maybe (Char, a)) -> a -> ByteString
-- * Substrings
unpackList,
#endif
noAL, NoAL, loopArr, loopAcc, loopSndAcc,
- loopU, mapEFL, filterEFL, foldEFL, fuseEFL,
+ loopU, mapEFL, filterEFL, foldEFL, foldEFL', fuseEFL,
filterF, mapF
) where
,unpackList
#endif
,noAL, NoAL, loopArr, loopAcc, loopSndAcc
- ,loopU, mapEFL, filterEFL, foldEFL, fuseEFL
+ ,loopU, mapEFL, filterEFL, foldEFL, foldEFL', fuseEFL
,useAsCString, unsafeUseAsCString
)
foldl f = B.foldl (\a c -> f a (w2c c))
{-# INLINE foldl #-}
+-- | 'foldl\'' is like foldl, but strict in the accumulator.
+foldl' :: (a -> Char -> a) -> a -> ByteString -> a
+foldl' f = B.foldl' (\a c -> f a (w2c c))
+{-# INLINE foldl' #-}
+
-- | 'foldr', applied to a binary operator, a starting value
-- (typically the right-identity of the operator), and a packed string,
-- reduces the packed string using the binary operator, from right to left.
--
-- > unfoldrN n == take n $ List.unfoldr
--
-unfoldrN :: Int -> (Char -> Maybe (Char, Char)) -> Char -> ByteString
-unfoldrN n f w = B.unfoldrN n ((k `fmap`) . f . w2c) (c2w w)
- where k (i,j) = (c2w i, c2w j) -- (c2w *** c2w)
+unfoldrN :: Int -> (a -> Maybe (Char, a)) -> a -> ByteString
+unfoldrN n f w = B.unfoldrN n ((k `fmap`) . f) w
+ where k (i,j) = (c2w i, j)
{-# INLINE unfoldrN #-}
-- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,