haskell - Convertir un ByteString perezoso a un ByteString estricto
lazy-evaluation chunking (5)
Como @sclv dijo en los comentarios anteriores, un bytestring perezoso es solo una lista de bytestrings estrictos. Hay dos enfoques para convertir la ByteString perezosa en estricta (fuente: discusión de la lista de correo de haskell sobre cómo agregar a la función de Sttrict ) - código relevante del hilo de correo electrónico a continuación:
Primero, las bibliotecas relevantes:
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
Enfoque 1 (igual que @sclv):
toStrict1 :: BL.ByteString -> B.ByteString
toStrict1 = B.concat . BL.toChunks
Enfoque 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)
Si el rendimiento es una preocupación, recomiendo revisar el hilo de correo electrónico anterior. Tiene criterio de referencia también. toStrict2 es más rápido que toStrict1 en esos puntos de referencia.
Tengo una función que toma un ByteString
lento , que deseo tener listas de retorno de ByteStrings
estrictos (la pereza debe transferirse al tipo de lista de la salida).
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
csVals :: L.ByteString -> [B.ByteString]
Quiero hacer esto por varias razones, varias funciones lexing requieren estrictas ByteString
s, y puedo garantizar que las estrictas ByteString
en la salida de csVal
s anteriores son muy pequeñas.
¿Cómo hago para " ByteString
" las ByteString
s sin chunking ?
Actualización0
Quiero tomar una ByteString
perezosa y hacer una ByteString
estricta que contenga todos sus datos.
Data.ByteString.Lazy.Char8 ahora tiene las funciones ToStrict y fromStrict.
El paquete bytestring
ahora exporta una función toStrict
:
Puede que esto no sea exactamente lo que quieres, pero ciertamente responde la pregunta en el título de esta publicación :)
Si el ByteString perezoso en cuestión es <= el tamaño máximo de un ByteString estricto:
toStrict = fromMaybe SB.empty . listToMaybe . toChunks
toChunks
hace que cada parte sea lo más grande posible (excepto posiblemente la última).
Si el tamaño de su ByteString perezoso es mayor que lo que puede ser un ByteString estricto, entonces esto no es posible: eso es exactamente para lo que son los ByteStrings perezosos.
También puedes usar blaze-builder para construir ByteString estricta desde la perezosa
toStrict :: BL.ByteString -> BS.ByteString
toStrict = toByteString . fromLazyByteString
Debe ser eficaz.