on cd0c2fd help sign in
228 lines 6.6 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 -- * Streams
13 read
14 , readChars
15 , readChunks
16 -- , getChunksLn
17 -- , getStringsWith -- get strings using the supplied decoding
18 -- , getStrings -- get strings of complete chars,
19 -- leave any partial chars for next string
20 -- , getStringsLn -- get lines decoded as char strings
22 -- * Unfolds
23 , reader
24 , chunkReader
26 -- * Folds
27 , write
28 , writeChunks
29 , writeErr
30 , writeErrChunks
32 -- * Stream writes
33 , putBytes -- Buffered (32K)
34 , putChars
35 , putChunks -- Unbuffered
36 , putStringsWith
37 , putStrings
38 , putStringsLn
39 )
40where
42#include "inline.hs"
44import Control.Monad.IO.Class (MonadIO(..))
45import Data.Word (Word8)
46import System.IO (stdin, stdout, stderr)
47import Prelude hiding (read)
49import Streamly.Internal.Data.Array.Type (Array(..))
50import Streamly.Internal.Data.Stream (Stream)
51import Streamly.Internal.Data.Unfold (Unfold)
52import Streamly.Internal.Data.Fold (Fold)
54import qualified Streamly.Internal.Data.Array as Array
55import qualified Streamly.Internal.Data.Stream as Stream
56 (intersperseMSuffix)
57import qualified Streamly.Internal.Data.Unfold as Unfold
58import qualified Streamly.Internal.FileSystem.Handle as Handle
59import qualified Streamly.Internal.Unicode.Stream as Unicode
61-------------------------------------------------------------------------------
62-- Reads
63-------------------------------------------------------------------------------
65-- | Unfold standard input into a stream of 'Word8'.
66--
67{-# INLINE reader #-}
68reader :: MonadIO m => Unfold m () Word8
69reader = Unfold.lmap (\() -> stdin) Handle.reader
71-- | Read a byte stream from standard input.
72--
73-- > read = Handle.read stdin
74-- > read = Stream.unfold Stdio.reader ()
75--
76-- /Pre-release/
77--
78{-# INLINE read #-}
79read :: MonadIO m => Stream m Word8
80read = Handle.read stdin
82-- | Read a character stream from Utf8 encoded standard input.
83--
84-- > readChars = Unicode.decodeUtf8 Stdio.read
85--
86-- /Pre-release/
87--
88{-# INLINE readChars #-}
89readChars :: MonadIO m => Stream m Char
90readChars = Unicode.decodeUtf8 read
92-- | Unfolds standard input into a stream of 'Word8' arrays.
93--
94{-# INLINE chunkReader #-}
95chunkReader :: MonadIO m => Unfold m () (Array Word8)
96chunkReader = Unfold.lmap (\() -> stdin) Handle.chunkReader
98-- | Read a stream of chunks from standard input. The maximum size of a single
99-- chunk is limited to @defaultChunkSize@. The actual size read may be less
100-- than @defaultChunkSize@.
101--
102-- > readChunks = Handle.readChunks stdin
103-- > readChunks = Stream.unfold Stdio.chunkReader ()
104--
105-- /Pre-release/
106--
107{-# INLINE readChunks #-}
108readChunks :: MonadIO m => Stream m (Array Word8)
109readChunks = Handle.readChunks stdin
111{-
112-- | Read UTF8 encoded lines from standard input.
113--
114-- You may want to process the input byte stream directly using appropriate
115-- folds for more efficient processing.
116--
117-- /Pre-release/
118--
119{-# INLINE getChunksLn #-}
120getChunksLn :: MonadIO m => Stream m (Array Word8)
121getChunksLn = (Stream.splitWithSuffix (== '\n') f) getChars
123 -- XXX Need to implement Fold.unfoldMany, should be easy for
124 -- non-terminating folds, but may be tricky for terminating folds. See
125 -- Array Stream folds.
126 where f = Fold.unfoldMany Unicode.readCharUtf8 Array.write
127-}
129-------------------------------------------------------------------------------
130-- Writes
131-------------------------------------------------------------------------------
133-- | Fold a stream of 'Word8' to standard output.
134--
135{-# INLINE write #-}
136write :: MonadIO m => Fold m Word8 ()
137write = Handle.write stdout
139-- | Fold a stream of 'Word8' to standard error.
140--
141{-# INLINE writeErr #-}
142writeErr :: MonadIO m => Fold m Word8 ()
143writeErr = Handle.write stderr
145-- | Write a stream of bytes to standard output.
146--
147-- > putBytes = Handle.putBytes stdout
148-- > putBytes = Stream.fold Stdio.write
149--
150-- /Pre-release/
151--
152{-# INLINE putBytes #-}
153putBytes :: MonadIO m => Stream m Word8 -> m ()
154putBytes = Handle.putBytes stdout
156-- | Encode a character stream to Utf8 and write it to standard output.
157--
158-- > putChars = Stdio.putBytes . Unicode.encodeUtf8
159--
160-- /Pre-release/
161--
162{-# INLINE putChars #-}
163putChars :: MonadIO m => Stream m Char -> m ()
164putChars = putBytes . Unicode.encodeUtf8
166-- | Fold a stream of @Array Word8@ to standard output.
167--
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{-# INLINE writeErrChunks #-}
175writeErrChunks :: MonadIO m => Fold m (Array Word8) ()
176writeErrChunks = Handle.writeChunks stderr
178-- | Write a stream of chunks to standard output.
179--
180-- > putChunks = Handle.putChunks stdout
181-- > putChunks = Stream.fold Stdio.writeChunks
182--
183-- /Pre-release/
184--
185{-# INLINE putChunks #-}
186putChunks :: MonadIO m => Stream m (Array Word8) -> m ()
187putChunks = Handle.putChunks stdout
189-------------------------------------------------------------------------------
190-- Line buffered
191-------------------------------------------------------------------------------
193-- XXX We need to write transformations as pipes so that they can be applied to
194-- folds as well as unfolds/streams. Non-backtracking (one-to-one, one-to-many,
195-- filters, reducers) transformations may be easy so we can possibly start with
196-- those.
197--
198-- | Write a stream of strings to standard output using the supplied encoding.
199-- Output is flushed to the device for each string.
200--
201-- /Pre-release/
202--
203{-# INLINE putStringsWith #-}
204putStringsWith :: MonadIO m
205 => (Stream m Char -> Stream m Word8) -> Stream m String -> m ()
206putStringsWith encode = putChunks . Unicode.encodeStrings encode
208-- | Write a stream of strings to standard output using UTF8 encoding. Output
209-- is flushed to the device for each string.
210--
211-- /Pre-release/
212--
213{-# INLINE putStrings #-}
214putStrings :: MonadIO m => Stream m String -> m ()
215putStrings = putStringsWith Unicode.encodeUtf8
217-- | Like 'putStrings' but adds a newline at the end of each string.
218--
219-- XXX This is not portable, on Windows we need to use "\r\n" instead.
220--
221-- /Pre-release/
222--
223{-# INLINE putStringsLn #-}
224putStringsLn :: MonadIO m => Stream m String -> m ()
225putStringsLn =
226 putChunks
227 . Stream.intersperseMSuffix (return $ Array.fromList [10])
228 . Unicode.encodeStrings Unicode.encodeUtf8