Haskell 用另一个bytestring拆分懒惰的bytestring
如何用另一个bytestring(例如,Haskell 用另一个bytestring拆分懒惰的bytestring,haskell,lazy-evaluation,bytestring,Haskell,Lazy Evaluation,Bytestring,如何用另一个bytestring(例如,“\r\n”)拆分一个lazybytestring?我正在寻找如下函数: BSL.ByteString -> BSL.ByteString -> [BSL.ByteString] 我知道breakSubstring,但该函数仅适用于严格的byteststring。我也看到了这一点,但解决方案是使用严格的bytestring。回答我自己的问题:我创建了一个将breakSubstring添加到数据.bytestring.Lazy(改编自严格版本)
“\r\n”
)拆分一个lazybytestring?我正在寻找如下函数:
BSL.ByteString -> BSL.ByteString -> [BSL.ByteString]
我知道
breakSubstring
,但该函数仅适用于严格的byteststring。我也看到了这一点,但解决方案是使用严格的bytestring。回答我自己的问题:我创建了一个将breakSubstring
添加到数据.bytestring.Lazy
(改编自严格版本)中的
在合并拉取请求之前,可以使用以下代码:
{-# LANGUAGE BangPatterns #-}
module Lib (breakSubstring) where
import Data.Bits (finiteBitSize, shiftL, (.|.), (.&.))
import Data.Word (Word32)
import Prelude
import qualified Data.ByteString.Lazy as BSL
breakSubstring
:: BSL.ByteString
-> BSL.ByteString
-> (BSL.ByteString, BSL.ByteString)
breakSubstring pat =
case lp of
0 -> \src -> (BSL.empty, src)
1 -> BSL.break (== BSL.head pat)
_ -> if lp * 8 <= fromIntegral (finiteBitSize (0 :: Word))
then shift
else karpRabin
where
lp = BSL.length pat
karpRabin :: BSL.ByteString -> (BSL.ByteString, BSL.ByteString)
karpRabin src
| BSL.length src < lp = (src, BSL.empty)
| otherwise = search (rollingHash $ BSL.take lp src) lp
where
k = 2891336453 :: Word32
rollingHash = BSL.foldl' (\h b -> h * k + fromIntegral b) 0
hp = rollingHash pat
m = k ^ lp
get = fromIntegral . BSL.index src
search !hs !i
| hp == hs && pat == BSL.take lp b = u
| BSL.length src <= i = (src, BSL.empty)
| otherwise = search hs' (i + 1)
where
u@(_, b) = BSL.splitAt (i - lp) src
hs' = hs * k +
get i -
m * get (i - lp)
{-# INLINE karpRabin #-}
shift :: BSL.ByteString -> (BSL.ByteString, BSL.ByteString)
shift !src
| BSL.length src < lp = (src, BSL.empty)
| otherwise = search (intoWord $ BSL.take lp src) lp
where
intoWord :: BSL.ByteString -> Word
intoWord = BSL.foldl' (\w b -> (w `shiftL` 8) .|. fromIntegral b) 0
wp = intoWord pat
mask = (1 `shiftL` fromIntegral (8 * lp)) - 1
search !w !i
| w == wp = BSL.splitAt (i - lp) src
| BSL.length src <= i = (src, BSL.empty)
| otherwise = search w' (i + 1)
where
b = fromIntegral (BSL.index src i)
w' = mask .&. ((w `shiftL` 8) .|. b)
{-# INLINE shift #-}
{-#语言模式}
模块库(断开子字符串),其中
导入数据位(finiteBitSize、shiftL、(.|.)、(.&.)
导入数据。Word(Word32)
进口序曲
将限定数据.ByteString.Lazy导入为BSL
断开子串
::BSL.ByteString
->BSL.ByteString
->(BSL.ByteString,BSL.ByteString)
断续拍打=
案例lp
0->\src->(BSL.empty,src)
1->BSL.break(=BSL.head pat)
_->如果lp*8(BSL.ByteString,BSL.ByteString)
卡普拉宾
|BSL.length srch*k+来自积分b)0
hp=滚球手拍
m=k^lp
get=from积分。索引src
搜索!啊!!我
|hp==hs&&pat==BSL.take lp b=u
|BSL.length src(BSL.ByteString,BSL.ByteString)
轮班!src
|BSL.length srcWord
intoWord=BSL.foldl'(\w b->(w`shiftL`8)。|.from积分b)0
wp=单词pat
掩码=(1`shiftL`from积分(8*lp))-1
搜索!W我
|w==wp=BSL.splitAt(i-lp)src
|BSL.length src正在转换严格的bytestring,或复制breakSubstring
的定义(它使用可用于惰性bytestring的take
和isPrefixOf
)合适的解决方案?@user2407038转换为严格的bytestring和从严格的bytestring不是一个选项。由于内存的使用,我目前正在使用一个严格的bytestring并尝试切换到一个懒惰的bytestring。该函数使用了大量的unsafeX
函数,这些函数对lazy-bytestring不可用。也许我可以使用正常的函数。