将Lazy ByteString转换为严格的ByteString

Mat*_*ner 20 haskell strict lazy-evaluation chunking bytestring

我有一个懒惰ByteString的函数,我希望有严格的ByteStrings返回列表(懒惰应该转移到输出的列表类型).

import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
csVals :: L.ByteString -> [B.ByteString]
Run Code Online (Sandbox Code Playgroud)

我想因各种原因这样做,有几个lexing函数需要严格的ByteStrings,我可以保证ByteStrings输出中csVal的输出严格s 非常小.

如何在ByteString没有分块的情况下进行"严格化" ?

Update0

我想采取一个懒惰ByteString,并使一个严格ByteString包含其所有数据.

och*_*les 36

bytestring包现在导出一个toStrict函数:

http://hackage.haskell.org/packages/archive/bytestring/0.10.2.0/doc/html/Data-ByteString-Lazy.html#v:toStrict

这可能不是你想要的,但它肯定回答了这篇文章标题中的问题:)


Sal*_*Sal 17

就像@sclv在上面的注释中所说的那样,lazy bytestring只是一个严格的字节串列表.有两种方法可以将惰性ByteString转换为strict(源:haskell邮件列表讨论添加到严格函数) - 来自以下电子邮件线程的相关代码:

一,相关图书馆:

import qualified Data.ByteString               as B
import qualified Data.ByteString.Internal      as BI
import qualified Data.ByteString.Lazy          as BL
import qualified Data.ByteString.Lazy.Internal as BLI
import           Foreign.ForeignPtr
import           Foreign.Ptr
Run Code Online (Sandbox Code Playgroud)

方法1(与@sclv相同):

toStrict1 :: BL.ByteString -> B.ByteString
toStrict1 = B.concat . BL.toChunks
Run Code Online (Sandbox Code Playgroud)

方法2:

toStrict2 :: BL.ByteString -> B.ByteString
toStrict2 BLI.Empty = B.empty
toStrict2 (BLI.Chunk c BLI.Empty) = c
toStrict2 lb = BI.unsafeCreate len $ go lb
  where
    len = BLI.foldlChunks (\l sb -> l + B.length sb) 0 lb

    go  BLI.Empty                   _   = return ()
    go (BLI.Chunk (BI.PS fp s l) r) ptr =
        withForeignPtr fp $ \p -> do
            BI.memcpy ptr (p `plusPtr` s) (fromIntegral l)
            go r (ptr `plusPtr` l)
Run Code Online (Sandbox Code Playgroud)

如果需要考虑性能,我建议您查看上面的电子邮件主题.它也有标准基准.在这些基准测试中,toStrict2比toStrict1更快.


iva*_*anm 5

如果有问题的惰性ByteString是<=严格ByteString的最大大小:

toStrict = fromMaybe SB.empty . listToMaybe . toChunks
Run Code Online (Sandbox Code Playgroud)

toChunks 使每个块尽可能大(除了可能是最后一个).

如果你懒惰的ByteString的大小比严格的ByteString大,那么这是不可能的:这正是lazy ByteStrings的用途.