on master help sign in
Add routines to cast the array into other types
a98d897Harendra Kumar
src/Streamly/Internal/Memory/Array.hs+75−3
@@ -120,6 +120,13 @@ module Streamly.Internal.Memory.Array
120 -- * Immutable Transformations
120 -- * Immutable Transformations
121 , streamTransform
121 , streamTransform
122
122
123+ -- * Casting
124+ , cast
125+ , castWord8
126+ , unsafeCast
127+ , withPtr
128+ , withCString
129+
123 -- * Folding Arrays
130 -- * Folding Arrays
124 , streamFold
131 , streamFold
125 , fold
132 , fold
@@ -129,11 +136,16 @@ module Streamly.Internal.Memory.Array
129 )
136 )
130where
137where
131
138
132−import Control.Monad (when)
139+import Control.Monad (when)
133import Control.Monad.IO.Class (MonadIO(..))
140import Control.Monad.IO.Class (MonadIO(..))
141+#if !(MIN_VERSION_base(4,11,0))
142+import Data.Semigroup ((<>))
143+#endif
144+import Data.Word (Word8)
134-- import Data.Functor.Identity (Identity)
145-- import Data.Functor.Identity (Identity)
146+import Foreign.C.String (CString)
135−import Foreign.ForeignPtr (withForeignPtr, touchForeignPtr)
147+import Foreign.ForeignPtr (withForeignPtr, touchForeignPtr, castForeignPtr)
136−import Foreign.Ptr (plusPtr)
148+import Foreign.Ptr (plusPtr, castPtr)
137import Foreign.Storable (Storable(..))
149import Foreign.Storable (Storable(..))
138import Prelude hiding (length, null, last, map, (!!), read, concat)
150import Prelude hiding (length, null, last, map, (!!), read, concat)
139
151
@@ -488,6 +500,66 @@ streamTransform f arr =
488 P.runFold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
500 P.runFold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
489 $ f (toStream arr)
501 $ f (toStream arr)
490
502
503+-------------------------------------------------------------------------------
504+-- Casts
505+-------------------------------------------------------------------------------
506+
507+-- | Cast an array having elements of type @a@ into an array having elements of
508+-- type @b@. The array size must be a multiple of the size of type @b@
509+-- otherwise accessing the last element of the array may result into a crash or
510+-- a random value.
511+--
512+-- /Internal/
513+--
514+unsafeCast :: Array a -> Array b
515+unsafeCast (Array start end) = Array (castForeignPtr start) (castPtr end)
516+
517+-- | Cast an array into a Word8 array
518+--
519+-- /Internal/
520+--
521+castWord8 :: Array a -> Array Word8
522+castWord8 = unsafeCast
523+
524+-- | Cast an array having elements of type @a@ into an array having elements of
525+-- type @b@. The length of the array should be a multiple of the size of the
526+-- target element otherwise 'Nothing' is returned.
527+--
528+-- /Internal/
529+--
530+cast :: forall a b. (Storable b) => Array a -> Maybe (Array b)
531+cast arr =
532+ let len = A.byteLength arr
533+ r = len `mod` sizeOf (undefined :: b)
534+ in if r /= 0
535+ then Nothing
536+ else Just $ unsafeCast arr
537+
538+-- | Use the array as @Ptr a@.
539+--
540+-- /Unsafe/
541+--
542+-- /Internal/
543+--
544+withPtr :: Array a -> (Ptr b -> IO c) -> IO c
545+withPtr Array{..} act = do
546+ withForeignPtr aStart $ \ptr -> act (castPtr ptr)
547+
548+-- | Convert the array into a null terminated CString Ptr.
549+--
550+-- /Unsafe/
551+--
552+-- /Internal/
553+--
554+withCString :: Array a -> (CString -> IO b) -> IO b
555+withCString arr act = do
556+ let Array{..} = castWord8 arr <> A.fromList [0]
557+ withForeignPtr aStart $ \ptr -> act (castPtr ptr)
558+
559+-------------------------------------------------------------------------------
560+-- Folds
561+-------------------------------------------------------------------------------
562+
491-- | Fold an array using a 'Fold'.
563-- | Fold an array using a 'Fold'.
492--
564--
493-- /Internal/
565-- /Internal/