@@ -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(..))
4+
25import qualified Streamly.Data.Fold as FL
3−-- import qualified Streamly.Memory.Array as A
46import qualified Streamly.FileSystem.Handle as FH
57import qualified System.IO as FH
8+import qualified Streamly.Memory.Array as A
9+import qualified Streamly.Prelude as S
610-- import qualified Streamly.FileSystem.FD as FH
7−-- import qualified Streamly.Data.Unicode.Stream as US
811
912import qualified Streamly.Internal.Data.Fold as FL
13+import qualified Streamly.Internal.Data.Unicode.Stream as US
1014import qualified Streamly.Internal.Memory.ArrayStream as AS
11−import qualified Streamly.Internal.FileSystem.Handle as IFH
15+import qualified Streamly.Internal.Prelude as S
1216
13−import Data.Char (ord)
14−import System.Environment (getArgs)
15−import System.IO (IOMode(..), hSeek, SeekMode(..))
17+-- Read the contents of a file to stdout.
18+--
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.
22+--
23+_cat :: FH.Handle -> IO ()
24+_cat src = S.fold (FH.write FH.stdout) $ S.unfold FH.read src
1625
26+-- Chunked version, more efficient than the byte stream version above. Reads
27+-- the file in 256KB chunks and writes those chunks to stdout.
1728cat :: FH.Handle -> IO ()
1829cat src =
1930 S.fold (FH.writeChunks FH.stdout)
20− $ IFH.toChunksWithBufferOf (256*1024) src
21−-- byte stream version
22−-- cat src = S.fold (FH.write FH.stdout) $ FH.read src
31+ $ S.unfold FH.readChunksWithBufferOf ((256*1024), src)
32+
33+-- Copy a source file to a destination file.
34+--
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 ()
39+_cp src dst = S.fold (FH.write dst) $ S.unfold FH.read src
2340
41+-- Chunked version, more efficient than the byte stream version above. Reads
42+-- the file in 256KB chunks and writes those chunks to stdout.
2443cp :: FH.Handle -> FH.Handle -> IO ()
2544cp src dst =
2645 S.fold (FH.writeChunks dst)
27− $ IFH.toChunksWithBufferOf (256*1024) src
28−-- byte stream version
29−-- cp src dst = S.fold (FH.write dst) $ FH.read src
46+ $ S.unfold FH.readChunksWithBufferOf ((256*1024), src)
3047
3148ord' :: Num a => Char -> a
3249ord' = (fromIntegral . ord)
3350
51+-- Count lines like wc -l.
52+--
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
57+ $ US.lines FL.drain
58+ $ US.decodeLatin1
59+ $ S.unfold FH.read src)
60+
61+-- More efficient chunked version. Reads chunks from the input handles and
62+-- splits the chunks directly instead of converting them into byte stream
63+-- first.
3464wcl :: FH.Handle -> IO ()
3565wcl src = print =<< (S.length
3666 $ AS.splitOn 10
37− $ IFH.toChunks src)
38−{-
39−-- Char stream version
40−wcl src = print =<< (S.length
41− $ flip US.lines FL.drain
42− $ US.decodeLatin1
43− $ FH.read src)
44−-}
67+ $ S.unfold FH.readChunks src)
4568
46−{-
69+-- grep -c
70+--
71+-- count the occurrences of a pattern in a file.
4772grepc :: String -> FH.Handle -> IO ()
4873grepc pat src = print . (subtract 1) =<< (S.length
49− $ FL.splitOnSeq (A.fromList (map ord' pat)) FL.drain
50− $ FH.read src)
51−-}
74+ $ S.splitOnSeq (A.fromList (map ord' pat)) FL.drain
75+ $ S.unfold FH.read src)
5276
77+-- Compute the average line length in a file.
5378avgll :: FH.Handle -> IO ()
5479avgll src = print =<< (S.fold avg
5580 $ S.splitWithSuffix (== ord' '\n') FL.length
@@ -57,6 +82,7 @@ avgll src = print =<< (S.fold avg
5782 where avg = (/) <$> toDouble FL.sum <*> toDouble FL.length
5883 toDouble = fmap (fromIntegral :: Int -> Double)
5984
85+-- histogram of line lengths in a file
6086llhisto :: FH.Handle -> IO ()
6187llhisto src = print =<< (S.fold (FL.classify FL.length)
6288 $ S.map bucket
@@ -73,7 +99,7 @@ main = do
7399
74100 rewind >> putStrLn "cat" >> cat src -- Unix cat program
75101 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
77103 rewind >> putStr "avgll " >> avgll src -- get average line length
78104 rewind >> putStr "llhisto " >> llhisto src -- get line length histogram
79105