on 43dda21 help sign in
229 lines 6.7 kB history raw
1-- |
2-- Module : Streamly.Internal.Console.Stdio
3-- Copyright : (c) 2018 Composewell Technologies
4--
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
8-- Portability : GHC
10module Streamly.Internal.Console.Stdio
11 (
12 -- * Read
13 read
14 , getBytes
15 , getChars
16 , readChunks
17 , getChunks
18 -- , getChunksLn
19 -- , getStringsWith -- get strings using the supplied decoding
20 -- , getStrings -- get strings of complete chars,
21 -- leave any partial chars for next string
22 -- , getStringsLn -- get lines decoded as char strings
24 -- * Write
25 , write
26 , writeErr
27 , putBytes -- Buffered (32K)
28 , putChars
29 , writeChunks
30 , writeErrChunks
31 , putChunks -- Unbuffered
32 , putStringsWith
33 , putStrings
34 , putStringsLn
35 )
36where
38#include "inline.hs"
40import Control.Monad.IO.Class (MonadIO(..))
41import Data.Word (Word8)
42import System.IO (stdin, stdout, stderr)
43import Prelude hiding (read)
45import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
46import Streamly.Internal.Data.Stream.Serial (SerialT)
47import Streamly.Internal.Data.Unfold (Unfold)
48import Streamly.Internal.Data.Fold (Fold)
50import qualified Streamly.Internal.Data.Array.Foreign as Array
51import qualified Streamly.Internal.Data.Stream.IsStream as Stream
52import qualified Streamly.Internal.Data.Unfold as Unfold
53import qualified Streamly.Internal.FileSystem.Handle as Handle
54import qualified Streamly.Internal.Unicode.Stream as Unicode
56-------------------------------------------------------------------------------
57-- Reads
58-------------------------------------------------------------------------------
60-- | Unfold standard input into a stream of 'Word8'.
61--
62-- @since 0.8.0
63{-# INLINE read #-}
64read :: MonadIO m => Unfold m () Word8
65read = Unfold.lmap (\() -> stdin) Handle.read
67-- | Read a byte stream from standard input.
68--
69-- > getBytes = Handle.getBytes stdin
70-- > getBytes = Stream.unfold Stdio.read ()
71--
72-- /Pre-release/
73--
74{-# INLINE getBytes #-}
75getBytes :: MonadIO m => SerialT m Word8
76getBytes = Handle.getBytes stdin
78-- | Read a character stream from Utf8 encoded standard input.
79--
80-- > getChars = Unicode.decodeUtf8 Stdio.getBytes
81--
82-- /Pre-release/
83--
84{-# INLINE getChars #-}
85getChars :: MonadIO m => SerialT m Char
86getChars = Unicode.decodeUtf8 getBytes
88-- | Unfolds standard input into a stream of 'Word8' arrays.
89--
90-- @since 0.8.0
91{-# INLINE readChunks #-}
92readChunks :: MonadIO m => Unfold m () (Array Word8)
93readChunks = Unfold.lmap (\() -> stdin) Handle.readChunks
95-- | Read a stream of chunks from standard input. The maximum size of a single
96-- chunk is limited to @defaultChunkSize@. The actual size read may be less
97-- than @defaultChunkSize@.
98--
99-- > getChunks = Handle.getChunks stdin
100-- > getChunks = Stream.unfold Stdio.readChunks ()
101--
102-- /Pre-release/
103--
104{-# INLINE getChunks #-}
105getChunks :: MonadIO m => SerialT m (Array Word8)
106getChunks = Handle.getChunks stdin
108{-
109-- | Read UTF8 encoded lines from standard input.
110--
111-- You may want to process the input byte stream directly using appropriate
112-- folds for more efficient processing.
113--
114-- /Pre-release/
115--
116{-# INLINE getChunksLn #-}
117getChunksLn :: MonadIO m => SerialT m (Array Word8)
118getChunksLn = (Stream.splitWithSuffix (== '\n') f) getChars
120 -- XXX Need to implement Fold.unfoldMany, should be easy for
121 -- non-terminating folds, but may be tricky for terminating folds. See
122 -- Array Stream folds.
123 where f = Fold.unfoldMany Unicode.readCharUtf8 Array.write
124-}
126-------------------------------------------------------------------------------
127-- Writes
128-------------------------------------------------------------------------------
130-- | Fold a stream of 'Word8' to standard output.
131--
132-- @since 0.8.0
133{-# INLINE write #-}
134write :: MonadIO m => Fold m Word8 ()
135write = Handle.write stdout
137-- | Fold a stream of 'Word8' to standard error.
138--
139-- @since 0.8.0
140{-# INLINE writeErr #-}
141writeErr :: MonadIO m => Fold m Word8 ()
142writeErr = Handle.write stderr
144-- | Write a stream of bytes to standard output.
145--
146-- > putBytes = Handle.putBytes stdout
147-- > putBytes = Stream.fold Stdio.write
148--
149-- /Pre-release/
150--
151{-# INLINE putBytes #-}
152putBytes :: MonadIO m => SerialT m Word8 -> m ()
153putBytes = Handle.putBytes stdout
155-- | Encode a character stream to Utf8 and write it to standard output.
156--
157-- > putChars = Stdio.putBytes . Unicode.encodeUtf8
158--
159-- /Pre-release/
160--
161{-# INLINE putChars #-}
162putChars :: MonadIO m => SerialT m Char -> m ()
163putChars = putBytes . Unicode.encodeUtf8
165-- | Fold a stream of @Array Word8@ to standard output.
166--
167-- @since 0.8.0
168{-# INLINE writeChunks #-}
169writeChunks :: MonadIO m => Fold m (Array Word8) ()
170writeChunks = Handle.writeChunks stdout
172-- | Fold a stream of @Array Word8@ to standard error.
173--
174-- @since 0.8.0
175{-# INLINE writeErrChunks #-}
176writeErrChunks :: MonadIO m => Fold m (Array Word8) ()
177writeErrChunks = Handle.writeChunks stderr
179-- | Write a stream of chunks to standard output.
180--
181-- > putChunks = Handle.putChunks stdout
182-- > putChunks = Stream.fold Stdio.writeChunks
183--
184-- /Pre-release/
185--
186{-# INLINE putChunks #-}
187putChunks :: MonadIO m => SerialT m (Array Word8) -> m ()
188putChunks = Handle.putChunks stdout
190-------------------------------------------------------------------------------
191-- Line buffered
192-------------------------------------------------------------------------------
194-- XXX We need to write transformations as pipes so that they can be applied to
195-- folds as well as unfolds/streams. Non-backtracking (one-to-one, one-to-many,
196-- filters, reducers) transformations may be easy so we can possibly start with
197-- those.
198--
199-- | Write a stream of strings to standard output using the supplied encoding.
200-- Output is flushed to the device for each string.
201--
202-- /Pre-release/
203--
204{-# INLINE putStringsWith #-}
205putStringsWith :: MonadIO m
206 => (SerialT m Char -> SerialT m Word8) -> SerialT m String -> m ()
207putStringsWith encode = putChunks . Unicode.encodeStrings encode
209-- | Write a stream of strings to standard output using UTF8 encoding. Output
210-- is flushed to the device for each string.
211--
212-- /Pre-release/
213--
214{-# INLINE putStrings #-}
215putStrings :: MonadIO m => SerialT m String -> m ()
216putStrings = putStringsWith Unicode.encodeUtf8
218-- | Like 'putStrings' but adds a newline at the end of each string.
219--
220-- XXX This is not portable, on Windows we need to use "\r\n" instead.
221--
222-- /Pre-release/
223--
224{-# INLINE putStringsLn #-}
225putStringsLn :: MonadIO m => SerialT m String -> m ()
226putStringsLn =
227 putChunks
228 . Stream.intersperseSuffix (return $ Array.fromList [10])
229 . Unicode.encodeStrings Unicode.encodeUtf8