Add reversedOnto and commitsOntoChunks

This commit is contained in:
Andrew Martin 2020-02-23 14:10:26 -05:00
parent f5799e7270
commit 1f2aa9b110
3 changed files with 43 additions and 1 deletions

View file

@ -3,6 +3,7 @@
## 0.3.4.0 -- 2020-??-?? ## 0.3.4.0 -- 2020-??-??
* Add `wordPaddedDec4`. * Add `wordPaddedDec4`.
* Add `reversedOnto` and `commitsOntoChunks`.
## 0.3.3.0 -- 2020-02-10 ## 0.3.3.0 -- 2020-02-10

View file

@ -14,6 +14,7 @@ module Data.ByteArray.Builder
-- * Evaluation -- * Evaluation
, run , run
, runOnto , runOnto
, reversedOnto
, putMany , putMany
, putManyConsLength , putManyConsLength
-- * Materialized Byte Sequences -- * Materialized Byte Sequences
@ -113,6 +114,7 @@ import Data.ByteArray.Builder.Unsafe (Builder(Builder))
import Data.ByteArray.Builder.Unsafe (BuilderState(BuilderState),pasteIO) import Data.ByteArray.Builder.Unsafe (BuilderState(BuilderState),pasteIO)
import Data.ByteArray.Builder.Unsafe (Commits(Initial,Mutable,Immutable)) import Data.ByteArray.Builder.Unsafe (Commits(Initial,Mutable,Immutable))
import Data.ByteArray.Builder.Unsafe (reverseCommitsOntoChunks) import Data.ByteArray.Builder.Unsafe (reverseCommitsOntoChunks)
import Data.ByteArray.Builder.Unsafe (commitsOntoChunks)
import Data.ByteArray.Builder.Unsafe (stringUtf8,cstring) import Data.ByteArray.Builder.Unsafe (stringUtf8,cstring)
import Data.ByteArray.Builder.Unsafe (addCommitsLength,copyReverseCommits) import Data.ByteArray.Builder.Unsafe (addCommitsLength,copyReverseCommits)
import Data.ByteString.Short.Internal (ShortByteString(SBS)) import Data.ByteString.Short.Internal (ShortByteString(SBS))
@ -160,6 +162,20 @@ runOnto hint@(I# hint# ) (Builder f) cs0 = runST $ do
(# s1, Mutable bufX offX csX #) (# s1, Mutable bufX offX csX #)
reverseCommitsOntoChunks cs0 cs reverseCommitsOntoChunks cs0 cs
-- | Variant of 'runOnto' that conses the additional chunks
-- in reverse order.
reversedOnto ::
Int -- ^ Size of initial chunk (use 4080 if uncertain)
-> Builder -- ^ Builder
-> Chunks
-> Chunks
reversedOnto hint@(I# hint# ) (Builder f) cs0 = runST $ do
MutableByteArray buf0 <- PM.newByteArray hint
cs <- ST $ \s0 -> case f buf0 0# hint# Initial s0 of
(# s1, bufX, offX, _, csX #) ->
(# s1, Mutable bufX offX csX #)
commitsOntoChunks cs0 cs
-- | Run a builder against lots of elements. This fills the same -- | Run a builder against lots of elements. This fills the same
-- underlying buffer over and over again. Do not let the argument to -- underlying buffer over and over again. Do not let the argument to
-- the callback escape from the callback (i.e. do not write it to an -- the callback escape from the callback (i.e. do not write it to an

View file

@ -18,6 +18,7 @@ module Data.ByteArray.Builder.Unsafe
, fromEffect , fromEffect
-- * Finalization -- * Finalization
, reverseCommitsOntoChunks , reverseCommitsOntoChunks
, commitsOntoChunks
, copyReverseCommits , copyReverseCommits
, addCommitsLength , addCommitsLength
-- * Safe Functions -- * Safe Functions
@ -115,7 +116,7 @@ addCommitsLength !acc (Mutable _ x cs) = addCommitsLength (acc + I# x) cs
-- @Chunks@ list (this argument is often @ChunksNil@). This reverses -- @Chunks@ list (this argument is often @ChunksNil@). This reverses
-- the order of the chunks, which is desirable since builders assemble -- the order of the chunks, which is desirable since builders assemble
-- @Commits@ with the chunks backwards. This performs an in-place shrink -- @Commits@ with the chunks backwards. This performs an in-place shrink
-- and freezes on any mutable byte arrays it encounters. Consequently, -- and freezes any mutable byte arrays it encounters. Consequently,
-- these must not be reused. -- these must not be reused.
reverseCommitsOntoChunks :: Chunks -> Commits s -> ST s Chunks reverseCommitsOntoChunks :: Chunks -> Commits s -> ST s Chunks
reverseCommitsOntoChunks !xs Initial = pure xs reverseCommitsOntoChunks !xs Initial = pure xs
@ -129,6 +130,30 @@ reverseCommitsOntoChunks !xs (Mutable buf len cs) = case len of
arr <- PM.unsafeFreezeByteArray (MutableByteArray buf) arr <- PM.unsafeFreezeByteArray (MutableByteArray buf)
reverseCommitsOntoChunks (ChunksCons (Bytes arr 0 (I# len)) xs) cs reverseCommitsOntoChunks (ChunksCons (Bytes arr 0 (I# len)) xs) cs
-- | Variant of 'reverseCommitsOntoChunks' that does not reverse
-- the order of the commits. Since commits are built backwards by
-- consing, this means that the chunks appended to the front will
-- be backwards. Within each chunk, however, the bytes will be in
-- the correct order.
--
-- Unlike 'reverseCommitsOntoChunks', this function is not tail
-- recursive.
commitsOntoChunks :: Chunks -> Commits s -> ST s Chunks
commitsOntoChunks !xs0 cs0 = go cs0
where
go Initial = pure xs0
go (Immutable arr off len cs) = do
xs <- go cs
pure $! ChunksCons (Bytes (ByteArray arr) (I# off) (I# len)) xs
go (Mutable buf len cs) = case len of
-- Skip over empty byte arrays.
0# -> go cs
_ -> do
shrinkMutableByteArray (MutableByteArray buf) (I# len)
arr <- PM.unsafeFreezeByteArray (MutableByteArray buf)
xs <- go cs
pure $! ChunksCons (Bytes arr 0 (I# len)) xs
-- | Copy the contents of the chunks into a mutable array, reversing -- | Copy the contents of the chunks into a mutable array, reversing
-- the order of the chunks. -- the order of the chunks.
-- Precondition: The destination must have enough space to house the -- Precondition: The destination must have enough space to house the