@@ -1,55 +1,80 @@
1−import qualified Streamly.Prelude as S
1+import Data.Char (ord)
2+import System.Environment (getArgs)
3+import System.IO (IOMode(..), hSeek, SeekMode(..))
2import qualified Streamly.Data.Fold as FL
5import qualified Streamly.Data.Fold as FL
3−-- import qualified Streamly.Memory.Array as A
4import qualified Streamly.FileSystem.Handle as FH
6import qualified Streamly.FileSystem.Handle as FH
5import qualified System.IO as FH
7import qualified System.IO as FH
8+import qualified Streamly.Memory.Array as A
9+import qualified Streamly.Prelude as S
6-- import qualified Streamly.FileSystem.FD as FH
10-- import qualified Streamly.FileSystem.FD as FH
7−-- import qualified Streamly.Data.Unicode.Stream as US
9import qualified Streamly.Internal.Data.Fold as FL
12import qualified Streamly.Internal.Data.Fold as FL
13+import qualified Streamly.Internal.Data.Unicode.Stream as US
10import qualified Streamly.Internal.Memory.ArrayStream as AS
14import qualified Streamly.Internal.Memory.ArrayStream as AS
11−import qualified Streamly.Internal.FileSystem.Handle as IFH
15+import qualified Streamly.Internal.Prelude as S
13−import Data.Char (ord)
17+-- Read the contents of a file to stdout.
14−import System.Environment (getArgs)
18+--
15−import System.IO (IOMode(..), hSeek, SeekMode(..))
19+-- FH.read reads the file in 32KB chunks and converts the chunks into a byte
20+-- stream. FH.write takes the byte stream as input, converts it into chunks of
21+-- 32KB and writes those chunks to stdout.
23+_cat :: FH.Handle -> IO ()
24+_cat src = S.fold (FH.write FH.stdout) $ S.unfold FH.read src
26+-- Chunked version, more efficient than the byte stream version above. Reads
27+-- the file in 256KB chunks and writes those chunks to stdout.
17cat :: FH.Handle -> IO ()
28cat :: FH.Handle -> IO ()
19 S.fold (FH.writeChunks FH.stdout)
30 S.fold (FH.writeChunks FH.stdout)
20− $ IFH.toChunksWithBufferOf (256*1024) src
31+ $ S.unfold FH.readChunksWithBufferOf ((256*1024), src)
21−-- byte stream version
32+
33+-- Copy a source file to a destination file.
35+-- FH.read reads the file in 32KB chunks and converts the chunks into a byte
36+-- stream. FH.write takes the byte stream as input, converts it into chunks of
37+-- 32KB and writes those chunks to the destination file.
38+_cp :: FH.Handle -> FH.Handle -> IO ()
22−-- cat src = S.fold (FH.write FH.stdout) $ FH.read src
39+_cp src dst = S.fold (FH.write dst) $ S.unfold FH.read src
41+-- Chunked version, more efficient than the byte stream version above. Reads
42+-- the file in 256KB chunks and writes those chunks to stdout.
24cp :: FH.Handle -> FH.Handle -> IO ()
43cp :: FH.Handle -> FH.Handle -> IO ()
25cp src dst =
44cp src dst =
26 S.fold (FH.writeChunks dst)
45 S.fold (FH.writeChunks dst)
27− $ IFH.toChunksWithBufferOf (256*1024) src
46+ $ S.unfold FH.readChunksWithBufferOf ((256*1024), src)
28−-- byte stream version
29−-- cp src dst = S.fold (FH.write dst) $ FH.read src
31ord' :: Num a => Char -> a
48ord' :: Num a => Char -> a
32ord' = (fromIntegral . ord)
49ord' = (fromIntegral . ord)
51+-- Count lines like wc -l.
53+-- Char stream version. Reads the input as a byte stream, splits it into lines
54+-- and counts the lines..
55+_wcl :: FH.Handle -> IO ()
56+_wcl src = print =<< (S.length
59+ $ S.unfold FH.read src)
61+-- More efficient chunked version. Reads chunks from the input handles and
62+-- splits the chunks directly instead of converting them into byte stream
34wcl :: FH.Handle -> IO ()
64wcl :: FH.Handle -> IO ()
35wcl src = print =<< (S.length
65wcl src = print =<< (S.length
36 $ AS.splitOn 10
66 $ AS.splitOn 10
37− $ IFH.toChunks src)
67+ $ S.unfold FH.readChunks src)
39−-- Char stream version
40−wcl src = print =<< (S.length
41− $ flip US.lines FL.drain
71+-- count the occurrences of a pattern in a file.
47grepc :: String -> FH.Handle -> IO ()
72grepc :: String -> FH.Handle -> IO ()
48grepc pat src = print . (subtract 1) =<< (S.length
73grepc pat src = print . (subtract 1) =<< (S.length
49− $ FL.splitOnSeq (A.fromList (map ord' pat)) FL.drain
74+ $ S.splitOnSeq (A.fromList (map ord' pat)) FL.drain
50− $ FH.read src)
75+ $ S.unfold FH.read src)
77+-- Compute the average line length in a file.
53avgll :: FH.Handle -> IO ()
78avgll :: FH.Handle -> IO ()
54avgll src = print =<< (S.fold avg
79avgll src = print =<< (S.fold avg
55 $ S.splitWithSuffix (== ord' '\n') FL.length
80 $ S.splitWithSuffix (== ord' '\n') FL.length
@@ -57,6 +82,7 @@ avgll src = print =<< (S.fold avg
57 where avg = (/) <$> toDouble FL.sum <*> toDouble FL.length
82 where avg = (/) <$> toDouble FL.sum <*> toDouble FL.length
58 toDouble = fmap (fromIntegral :: Int -> Double)
83 toDouble = fmap (fromIntegral :: Int -> Double)
85+-- histogram of line lengths in a file
60llhisto :: FH.Handle -> IO ()
86llhisto :: FH.Handle -> IO ()
61llhisto src = print =<< (S.fold (FL.classify FL.length)
87llhisto src = print =<< (S.fold (FL.classify FL.length)
62 $ S.map bucket
88 $ S.map bucket
@@ -73,7 +99,7 @@ main = do
74 rewind >> putStrLn "cat" >> cat src -- Unix cat program
100 rewind >> putStrLn "cat" >> cat src -- Unix cat program
75 rewind >> putStr "wcl " >> wcl src -- Unix wc -l program
101 rewind >> putStr "wcl " >> wcl src -- Unix wc -l program
76− -- rewind >> putStr "grepc " >> grepc "aaaa" src -- Unix grep -c program
102+ rewind >> putStr "grepc " >> grepc "aaaa" src -- Unix grep -c program
77 rewind >> putStr "avgll " >> avgll src -- get average line length
103 rewind >> putStr "avgll " >> avgll src -- get average line length
78 rewind >> putStr "llhisto " >> llhisto src -- get line length histogram
104 rewind >> putStr "llhisto " >> llhisto src -- get line length histogram