Преобразуйте Ленивую ByteString в строгую ByteString - PullRequest
19 голосов
/ 19 октября 2011

У меня есть функция, которая принимает lazy ByteString, и я хочу иметь списки возврата строгого ByteStrings (лень следует перенести в тип спискавывод).

import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
csVals :: L.ByteString -> [B.ByteString]

Я хочу сделать это по разным причинам, несколько функций lexing требуют строгого ByteString с, и я могу гарантировать, что выведенные строгие ByteString свыходные данные csVal с выше очень малы.

Как я могу "охарактеризовать" ByteString с без дробления их?

Update0

Я хочу взять Ленивый ByteString и сделать один строгий ByteString, содержащий все его данные.

Ответы [ 5 ]

33 голосов
/ 29 ноября 2012

Пакет bytestring теперь экспортирует функцию toStrict:

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

Это может быть не совсем то, что вы хотите, но, безусловно, отвечает на вопрос в заголовкеэтот пост:)

16 голосов
/ 18 декабря 2011

Как сказал @sclv в комментариях выше, ленивая строка байтов - это просто список строгих строк байтов.Существует два подхода к преобразованию отложенного ByteString в строгий (источник: обсуждение списка рассылки haskell о добавлении функции toStrict ) - соответствующий код из цепочки сообщений ниже:

Во-первых, соответствующие библиотеки:

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

Подход 1 (такой же, как @sclv):

toStrict1 :: BL.ByteString -> B.ByteString
toStrict1 = B.concat . BL.toChunks

Подход 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)

Если производительность вызывает беспокойство, я рекомендую проверить ветку электронной почтывыше.Он также имеет критерий критерия.toStrict2 быстрее, чем toStrict1 в этих тестах.

5 голосов
/ 19 октября 2011

Если ленивая рассматриваемая строка ByteString <= максимальный размер строгой строки ByteString: </p>

toStrict = fromMaybe SB.empty . listToMaybe . toChunks

toChunks делает каждый блок максимально большим (за исключением, возможно, последнего).

Если размер вашего ленивого ByteString больше , чем может быть строгий ByteString, то это невозможно: это именно то, для чего нужны ленивые ByteString.

0 голосов
/ 10 октября 2017

Data.ByteString.Lazy.Char8 теперь имеет функции toStrict и fromStrict.

0 голосов
/ 06 апреля 2013

Вы также можете использовать blaze-builder для создания строгой ByteString из ленивых

toStrict :: BL.ByteString -> BS.ByteString
toStrict = toByteString . fromLazyByteString

Это должно быть эффективно.

...