@@ -26,7 +26,8 @@ module Streamly.Mem.Array.Types
2626 , unsafeInlineIO
2727 , withNewArray
2828 , newArray
29− , unsafeAppend
29+ , unsafeSnoc
30+ , snoc
3031 , shrinkToFit
3132 , memcpy
3233 , memcmp
@@ -215,15 +216,39 @@ withNewArray count f = do
215216-- Internal routine for when the array is being created. Appends one item at
216217-- the end of the array. Useful when sequentially writing a stream to the
217218-- array. DOES NOT CHECK THE ARRAY BOUNDS.
218−{-# INLINE unsafeAppend #-}
219−unsafeAppend :: forall a. Storable a => Array a -> a -> IO (Array a)
220−unsafeAppend arr@Array{..} x = do
219+{-# INLINE unsafeSnoc #-}
220+unsafeSnoc :: forall a. Storable a => Array a -> a -> IO (Array a)
221+unsafeSnoc arr@Array{..} x = do
221222 when (aEnd == aBound) $
222223 error "BUG: unsafeAppend: writing beyond array bounds"
223224 poke aEnd x
224225 touchForeignPtr aStart
225226 return $ arr {aEnd = aEnd `plusPtr` (sizeOf (undefined :: a))}
226227
228+{-# INLINE snoc #-}
229+snoc :: forall a. Storable a => Array a -> a -> Array a
230+snoc arr@Array {..} x = unsafePerformIO $
231+ if (aEnd == aBound)
232+ then do
233+ let oldStart = unsafeForeignPtrToPtr aStart
234+ size = aEnd `minusPtr` oldStart
235+ newSize = (size + (sizeOf (undefined :: a)))
236+ newPtr <- mallocPlainForeignPtrAlignedBytes newSize (alignment (undefined :: a))
237+ withForeignPtr newPtr $ \pNew -> do
238+ memcpy (castPtr pNew) (castPtr oldStart) size
239+ poke (pNew `plusPtr` size) x
240+ touchForeignPtr aStart
241+ return $ Array
242+ { aStart = newPtr
243+ , aEnd = pNew `plusPtr` (size + sizeOf (undefined :: a))
244+ , aBound = pNew `plusPtr` newSize
245+ }
246+ else do
247+ poke aEnd x
248+ touchForeignPtr aStart
249+ return $ arr {aEnd = aEnd `plusPtr` (sizeOf (undefined :: a))}
250+
251+
227252-- | Remove the free space from an Array.
228253shrinkToFit :: forall a. Storable a => Array a -> IO (Array a)
229254shrinkToFit arr@Array{..} = do