on master help sign in
Add fromByteStr# and fromStr#
4bb8b7cHarendra Kumar
core/src/Streamly/Internal/Data/Stream/Generate.hs+44−4
@@ -30,16 +30,20 @@ module Streamly.Internal.Data.Stream.Generate
30
30
31 -- * From memory
31 -- * From memory
32 , fromPtr
32 , fromPtr
33+ , fromPtrN
34+ , fromByteStr#
35+ -- , fromByteArray#
33 )
36 )
34where
37where
35
38
36import Control.Monad.IO.Class (MonadIO)
39import Control.Monad.IO.Class (MonadIO)
40+import Data.Word (Word8)
37import Foreign.Storable (Storable)
41import Foreign.Storable (Storable)
38−import Foreign.Ptr (Ptr)
42+import GHC.Exts (Addr#, Ptr (Ptr))
39import Streamly.Internal.Data.Stream.Type (Stream, fromStreamK, toStreamK)
43import Streamly.Internal.Data.Stream.Type (Stream, fromStreamK, toStreamK)
40import Streamly.Internal.Data.Unfold.Type (Unfold)
44import Streamly.Internal.Data.Unfold.Type (Unfold)
41
45
42−import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
46+import qualified Streamly.Internal.Data.Stream.StreamD as D
43import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
47import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
44import qualified Streamly.Internal.Data.Stream.Type as Stream
48import qualified Streamly.Internal.Data.Stream.Type as Stream
45
49
@@ -48,6 +52,7 @@ import qualified Streamly.Internal.Data.Stream.Type as Stream
48-- >>> import qualified Streamly.Data.Fold as Fold
52-- >>> import qualified Streamly.Data.Fold as Fold
49-- >>> import qualified Streamly.Data.Unfold as Unfold
53-- >>> import qualified Streamly.Data.Unfold as Unfold
50-- >>> import qualified Streamly.Internal.Data.Stream as Stream
54-- >>> import qualified Streamly.Internal.Data.Stream as Stream
55+-- >>> import GHC.Exts (Ptr (Ptr))
51
56
52
57
53------------------------------------------------------------------------------
58------------------------------------------------------------------------------
@@ -151,6 +156,41 @@ fromFoldableM = Prelude.foldr Stream.consM Stream.nil
151-- From pointers
156-- From pointers
152------------------------------------------------------------------------------
157------------------------------------------------------------------------------
153
158
159+-- | Keep reading 'Storable' elements from 'Ptr' onwards.
160+--
161+-- /Unsafe:/ The caller is responsible for safe addressing.
162+--
163+-- /Pre-release/
154{-# INLINE fromPtr #-}
164{-# INLINE fromPtr #-}
155−fromPtr :: (MonadIO m, Storable a) => Int -> Ptr a -> Stream m a
165+fromPtr :: (MonadIO m, Storable a) => Ptr a -> Stream m a
166+fromPtr = Stream.fromStreamD . D.fromPtr
167+
168+-- | Take @n@ 'Storable' elements starting from 'Ptr' onwards.
169+--
170+-- >>> fromPtrN n = Stream.take n . Stream.fromPtr
171+--
172+-- /Unsafe:/ The caller is responsible for safe addressing.
173+--
174+-- /Pre-release/
175+{-# INLINE fromPtrN #-}
176+fromPtrN :: (MonadIO m, Storable a) => Int -> Ptr a -> Stream m a
177+fromPtrN n = Stream.fromStreamD . D.take n . D.fromPtr
178+
179+-- | Read bytes from an 'Addr#' until a 0 byte is encountered, the 0 byte is
180+-- not included in the stream.
181+--
182+-- >>> fromByteStr# addr = Stream.takeWhile (/= 0) $ Stream.fromPtr $ Ptr addr
183+--
184+-- /Unsafe:/ The caller is responsible for safe addressing.
185+--
186+-- Note that this is completely safe when reading from Haskell string
187+-- literals because they are guaranteed to be NULL terminated:
188+--
189+-- >>> Stream.fold Fold.toList $ Stream.fromByteStr# "\1\2\3\0"#
190+-- [1,2,3]
191+--
192+{-# INLINE fromByteStr# #-}
193+fromByteStr# :: MonadIO m => Addr# -> Stream m Word8
194+fromByteStr# addr =
156−fromPtr n = Stream.fromStreamD . D.fromPtr n
195+ Stream.fromStreamD $ D.takeWhile (/= 0) $ D.fromPtr $ Ptr addr
196+
core/src/Streamly/Internal/Data/Stream/StreamD/Generate.hs+6−5
@@ -470,14 +470,15 @@ fromListM = Stream step
470-- From pointers
470-- From pointers
471-------------------------------------------------------------------------------
471-------------------------------------------------------------------------------
472
472
473+-- | Read an infinite stream from a pointer, advancing the pointer as needed.
474+-- The caller is responsible to end the stream safely.
473{-# INLINE fromPtr #-}
475{-# INLINE fromPtr #-}
474−fromPtr :: forall m a. (MonadIO m, Storable a) => Int -> Ptr a -> Stream m a
476+fromPtr :: forall m a. (MonadIO m, Storable a) => Ptr a -> Stream m a
475−fromPtr count ptr = Stream step (count, ptr)
477+fromPtr = Stream step
476
478
477 where
479 where
478
480
479 {-# INLINE_LATE step #-}
481 {-# INLINE_LATE step #-}
480− step _ (0, _) = return Stop
482+ step _ p = do
481− step _ (n, p) = do
482 x <- liftIO $ peek p
483 x <- liftIO $ peek p
483− return $ Yield x (n - 1, PTR_NEXT(p, a))
484+ return $ Yield x (PTR_NEXT(p, a))
core/src/Streamly/Internal/Data/Unfold.hs+4−5
@@ -177,7 +177,7 @@ module Streamly.Internal.Data.Unfold
177 , fromList
177 , fromList
178 , fromListM
178 , fromListM
179
179
180− -- ** From Pointer
180+ -- ** From Memory
181 , fromPtr
181 , fromPtr
182
182
183 , fromStreamK
183 , fromStreamK
@@ -636,16 +636,15 @@ fromListM = Unfold step pure
636 step [] = pure Stop
636 step [] = pure Stop
637
637
638{-# INLINE fromPtr #-}
638{-# INLINE fromPtr #-}
639−fromPtr :: forall m a. (MonadIO m, Storable a) => Unfold m (Int, Ptr a) a
639+fromPtr :: forall m a. (MonadIO m, Storable a) => Unfold m (Ptr a) a
640fromPtr = Unfold step return
640fromPtr = Unfold step return
641
641
642 where
642 where
643
643
644 {-# INLINE_LATE step #-}
644 {-# INLINE_LATE step #-}
645− step (0, _) = return Stop
646− step (n, p) = do
645+ step p = do
647 x <- liftIO $ peek p
646 x <- liftIO $ peek p
648− return $ Yield x (n - 1, PTR_NEXT(p, a))
647+ return $ Yield x (PTR_NEXT(p, a))
649
648
650------------------------------------------------------------------------------
649------------------------------------------------------------------------------
651-- Specialized Generation
650-- Specialized Generation
src/Streamly/Internal/Unicode/Stream.hs+26
@@ -72,6 +72,9 @@ module Streamly.Internal.Unicode.Stream
72 , decodeUtf8ArraysD'
72 , decodeUtf8ArraysD'
73 , decodeUtf8ArraysD_
73 , decodeUtf8ArraysD_
74
74
75+ -- * Decoding String Literals
76+ , fromStr#
77+
75 -- * Deprecations
78 -- * Deprecations
76 , decodeUtf8Lax
79 , decodeUtf8Lax
77 , encodeLatin1Lax
80 , encodeLatin1Lax
@@ -94,6 +97,7 @@ import Foreign.Marshal.Alloc (mallocBytes)
94import Foreign.Storable (Storable(..))
97import Foreign.Storable (Storable(..))
95import Fusion.Plugin.Types (Fuse(..))
98import Fusion.Plugin.Types (Fuse(..))
96import GHC.Base (assert, unsafeChr)
99import GHC.Base (assert, unsafeChr)
100+import GHC.Exts (Addr#)
97import GHC.IO.Encoding.Failure (isSurrogate)
101import GHC.IO.Encoding.Failure (isSurrogate)
98import GHC.Ptr (Ptr (..), plusPtr)
102import GHC.Ptr (Ptr (..), plusPtr)
99import System.IO.Unsafe (unsafePerformIO)
103import System.IO.Unsafe (unsafePerformIO)
@@ -114,6 +118,7 @@ import qualified Streamly.Internal.Data.Fold as Fold
114import qualified Streamly.Internal.Data.Unfold as Unfold
118import qualified Streamly.Internal.Data.Unfold as Unfold
115import qualified Streamly.Internal.Data.Parser as Parser
119import qualified Streamly.Internal.Data.Parser as Parser
116import qualified Streamly.Internal.Data.Parser.ParserD as ParserD
120import qualified Streamly.Internal.Data.Parser.ParserD as ParserD
121+import qualified Streamly.Internal.Data.Stream as Stream
117import qualified Streamly.Internal.Data.Stream.Serial as Serial
122import qualified Streamly.Internal.Data.Stream.Serial as Serial
118import qualified Streamly.Internal.Data.Array.Unboxed as Array
123import qualified Streamly.Internal.Data.Array.Unboxed as Array
119import qualified Streamly.Internal.Data.Array.Unboxed.Type as A
124import qualified Streamly.Internal.Data.Array.Unboxed.Type as A
@@ -124,9 +129,11 @@ import Prelude hiding (lines, words, unlines, unwords)
124
129
125-- $setup
130-- $setup
126-- >>> :m
131-- >>> :m
132+-- >>> :set -XMagicHash
127-- >>> import Prelude hiding (lines, words, unlines, unwords)
133-- >>> import Prelude hiding (lines, words, unlines, unwords)
128-- >>> import qualified Streamly.Prelude as Stream
134-- >>> import qualified Streamly.Prelude as Stream
129-- >>> import qualified Streamly.Data.Fold as Fold
135-- >>> import qualified Streamly.Data.Fold as Fold
136+-- >>> import qualified Streamly.Internal.Unicode.Stream as Unicode
130-- >>> import Streamly.Internal.Unicode.Stream
137-- >>> import Streamly.Internal.Unicode.Stream
131
138
132-------------------------------------------------------------------------------
139-------------------------------------------------------------------------------
@@ -980,6 +987,25 @@ encodeUtf8_ = fromStreamD . encodeUtf8D_ . toStreamD
980encodeUtf8Lax :: (IsStream t, Monad m) => t m Char -> t m Word8
987encodeUtf8Lax :: (IsStream t, Monad m) => t m Char -> t m Word8
981encodeUtf8Lax = encodeUtf8
988encodeUtf8Lax = encodeUtf8
982
989
990+-------------------------------------------------------------------------------
991+-- Decoding string literals
992+-------------------------------------------------------------------------------
993+
994+-- | Read UTF-8 encoded bytes as chars from an 'Addr#' until a 0 byte is
995+-- encountered, the 0 byte is not included in the stream.
996+--
997+-- /Unsafe:/ The caller is responsible for safe addressing.
998+--
999+-- Note that this is completely safe when reading from Haskell string
1000+-- literals because they are guaranteed to be NULL terminated:
1001+--
1002+-- >>> Stream.fold Fold.toList (Unicode.fromStr# "Haskell"#)
1003+-- "Haskell"
1004+--
1005+{-# INLINE fromStr# #-}
1006+fromStr# :: MonadIO m => Addr# -> SerialT m Char
1007+fromStr# addr = decodeUtf8 $ Stream.fromByteStr# addr
1008+
983-------------------------------------------------------------------------------
1009-------------------------------------------------------------------------------
984-- Encode streams of containers
1010-- Encode streams of containers
985-------------------------------------------------------------------------------
1011-------------------------------------------------------------------------------