@@ -21,8 +21,9 @@ module Streamly.Internal.Memory.Array.Types
21 -- * Construction
21 -- * Construction
22 , spliceTwo
22 , spliceTwo
24 , fromAddr#
25 , fromAddr#
25− , fromString#
26+ , fromCString#
26 , fromList
27 , fromList
27 , fromListN
28 , fromListN
28 , fromStreamDN
29 , fromStreamDN
@@ -86,7 +87,6 @@ import Control.Monad.IO.Class (MonadIO(..))
86import Data.Word (Word8)
87import Data.Word (Word8)
87import Foreign.C.String (CString)
88import Foreign.C.String (CString)
88import Foreign.C.Types (CSize(..))
89import Foreign.C.Types (CSize(..))
89−import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
90import Foreign.Ptr (plusPtr, castPtr)
90import Foreign.Ptr (plusPtr, castPtr)
91import Foreign.Storable (Storable(..))
91import Foreign.Storable (Storable(..))
92import GHC.Base (Addr#, nullAddr#)
92import GHC.Base (Addr#, nullAddr#)
@@ -217,6 +217,30 @@ spliceTwo :: (MonadIO m, Storable a) => Array a -> Array a -> m (Array a)
217spliceTwo arr1 arr2 =
217spliceTwo arr1 arr2 =
218 unsafeFreeze <$> MA.spliceTwo (unsafeThaw arr1) (unsafeThaw arr2)
218 unsafeFreeze <$> MA.spliceTwo (unsafeThaw arr1) (unsafeThaw arr2)
220+-- | Create an 'Array' of the given number of elements of type @a@ from a read
221+-- only pointer @Ptr a@. The pointer is not freed when the array is garbage
222+-- collected. This API is unsafe for the following reasons:
224+-- 1. The pointer must point to static pinned memory or foreign memory that
225+-- does not require freeing..
226+-- 2. The pointer must be legally accessible upto the given length.
227+-- 3. To guarantee that the array is immutable, the contents of the address
228+-- must be guaranteed to not change.
234+{-# INLINE fromPtr #-}
235+fromPtr :: Int -> Ptr a -> Array a
236+fromPtr n ptr = MA.unsafeInlineIO $ do
237+ fptr <- newForeignPtr_ ptr
238+ let end = ptr `plusPtr` n
220-- XXX when converting an array of Word8 from a literal string we can simply
244-- XXX when converting an array of Word8 from a literal string we can simply
221-- refer to the literal string. Is it possible to write rules such that
245-- refer to the literal string. Is it possible to write rules such that
222-- fromList Word8 can be rewritten so that GHC does not first convert the
246-- fromList Word8 can be rewritten so that GHC does not first convert the
@@ -227,13 +251,8 @@ spliceTwo arr1 arr2 =
227-- an array of the required type. With template Haskell we can provide a safe
251-- an array of the required type. With template Haskell we can provide a safe
228-- version of fromString#.
252-- version of fromString#.
230−-- | Create an @Array Word8@ of the given length from a machine address
254+-- | Create an @Array Word8@ of the given length from a static, read only
231−-- 'Addr#'. This API is unsafe for the following reasons:
255+-- machine address 'Addr#'. See 'fromPtr' for safety caveats.
233−-- 1. The address must point to pinned memory or foreign memory.
234−-- 2. The address must be legally accessible upto the given length.
235−-- 3. To guarantee that the array is immutable, the contents of the address
236−-- must be guaranteed to not change.
238-- A common use case for this API is to create an array from a static unboxed
257-- A common use case for this API is to create an array from a static unboxed
239-- string literal. GHC string literals are of type 'Addr#', and must contain
258-- string literal. GHC string literals are of type 'Addr#', and must contain
@@ -252,52 +271,42 @@ spliceTwo arr1 arr2 =
253-- /Time complexity: O(1)/
272-- /Time complexity: O(1)/
255{-# INLINE fromAddr# #-}
276{-# INLINE fromAddr# #-}
256−fromAddr# :: Int -> Addr# -> IO (Array Word8)
277+fromAddr# :: Int -> Addr# -> Array a
257−fromAddr# n addr# = do
278+fromAddr# n addr# = fromPtr n (castPtr $ Ptr addr#)
258− ptr <- newForeignPtr_ (castPtr $ Ptr addr#)
259− let p = unsafeForeignPtrToPtr ptr
260− let end = p `plusPtr` n
266−-- | Like 'fromAddr#' but determines the length of the array upto and excluding
280+-- | Generate a byte array from an 'Addr#' that contains a sequence of NUL
281+-- (@0@) terminated bytes. The array would not include the NUL byte. The
267−-- the first @0@ byte. The address must be legally accessible up to the first
282+-- address must be in static read-only memory and must be legally accessible up
268−-- NUL byte.
283+-- to and including the first NUL byte.
270−-- A common use case for this API is to create an array from an unboxed string
285+-- An unboxed string literal (e.g. @"hello"#@) is a common example of an
271−-- literal. Unboxed string literals are guaranteed to be terminated by a NUL
286+-- 'Addr#' in static read only memory. It represents the UTF8 encoded sequence
272−-- byte.
287+-- of bytes terminated by a NUL byte (a 'CString') corresponding to the
288+-- given unicode string.
274−-- >>> fromString# "hello world!"#
290+-- >>> fromCString# "hello world!"#
275-- > [104,101,108,108,111,32,119,111,114,108,100,33]
291-- > [104,101,108,108,111,32,119,111,114,108,100,33]
277−-- >>> fromString# "\255\NUL\255"#
293+-- >>> fromCString# "\255\NUL\255"#
278-- > [255]
294-- > [255]
280−-- /See also: 'fromAddr#', 'fromString'/
296+-- /See also: 'fromAddr#'/
282-- /Unsafe/
298-- /Unsafe/
284-- /Time complexity: O(n) (computes the length of the string)/
300-- /Time complexity: O(n) (computes the length of the string)/
286−{-# INLINE fromString# #-}
302+-- /Internal/
304+{-# INLINE fromCString# #-}
287−fromString# :: Addr# -> IO (Array Word8)
305+fromCString# :: Addr# -> Array Word8
288−fromString# addr# = do
306+fromCString# addr# = do
289− ptr <- newForeignPtr_ (castPtr cstr)
307+ let cstr = Ptr addr#
290− len <- c_strlen cstr
308+ len = MA.unsafeInlineIO $ c_strlen cstr
291− let n = fromIntegral len
309+ fromPtr (fromIntegral len) (castPtr cstr)
292− let p = unsafeForeignPtrToPtr ptr
293− let end = p `plusPtr` n
302-- | Create an 'Array' from the first N elements of a list. The array is
311-- | Create an 'Array' from the first N elements of a list. The array is
303-- allocated to size N, if the list terminates before N elements then the
312-- allocated to size N, if the list terminates before N elements then the