私自身の質問に答える:を作成しました。これはbreakSubstring
からData.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
[email protected](_, 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 #-}
は厳密バイト文字列へ及びからの変換、または 'breakSubstring'(それが使用する' take'と 'isPrefixOfの定義をコピーしています'' Lazy bytestringsのために利用可能です)適切な解決策はありますか? – user2407038
@ user2407038 strictからtoへの変換はオプションではありません。私は現在、厳密なバイトストリングを使用しており、メモリ使用量のために怠惰なバイトストリングに切り替えることを試みています。 [breakSubString](https://github.com/haskell/bytestring/blob/master/Data/ByteString.hs#L1350)関数は、レイジー・バイトストリングでは使用できないいくつかの 'unsafeX'関数を使用します。たぶん、私は通常の機能を使用することができます。 –