From 191aa9242e4d3547c2bf1e9d1b758bc0a3a4c8ee Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Sat, 22 Jan 2022 16:03:43 +0100 Subject: [PATCH] Implement intercalate manually --- Data/ByteString/Short/Internal.hs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Data/ByteString/Short/Internal.hs b/Data/ByteString/Short/Internal.hs index af79c7f55..7d1ce0662 100644 --- a/Data/ByteString/Short/Internal.hs +++ b/Data/ByteString/Short/Internal.hs @@ -136,7 +136,7 @@ module Data.ByteString.Short.Internal ( useAsCStringLen, ) where -import Data.ByteString.Internal (ByteString(..), accursedUnutterablePerformIO, memchr) +import Data.ByteString.Internal (ByteString(..), accursedUnutterablePerformIO, memchr, checkedAdd) import qualified Data.ByteString.Internal as BS import Data.Bifunctor ( first, bimap ) @@ -700,7 +700,24 @@ reverse = \sbs -> -- -- @since 0.11.3.0 intercalate :: ShortByteString -> [ShortByteString] -> ShortByteString -intercalate s = concat . List.intersperse s +intercalate _ [] = mempty +intercalate _ [x] = x -- This branch exists for laziness, not speed +intercalate inc (sbs:t) = create totalLen (\mba -> + let l = length sbs + in copyByteArray (asBA sbs) 0 mba 0 l >> go mba l t) + where + go :: MBA s -> Int -> [ShortByteString] -> ST s () + go _ _ [] = pure () + go mba !off (chunk:chunks) = do + let lc = length chunk + copyByteArray ba 0 mba off lba + copyByteArray (asBA chunk) 0 mba (off + lba) lc + go mba (off + lc + lba) chunks + + totalLen = List.foldl' (\acc chunk -> acc +! length inc +! length chunk) (length sbs) t + (+!) = checkedAdd "intercalate" + ba = asBA inc + lba = length inc {-# INLINE intercalate #-}