packages feed

iteratee 0.2.4 → 0.3.1

raw patch · 24 files changed

+791/−499 lines, 24 filesdep ~basedep ~containersdep ~haskell98setup-changedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, containers, haskell98, unix

API changes (from Hackage documentation)

- Data.Iteratee.Base.StreamChunk: instance (Storable el) => ReadableChunk [] el
- Data.Iteratee.IO.Base: Errno :: CInt -> Errno
- Data.Iteratee.IO.Base: myfdRead :: Fd -> Ptr CChar -> ByteCount -> IO (Either Errno ByteCount)
- Data.Iteratee.IO.Base: myfdSeek :: Fd -> SeekMode -> FileOffset -> IO (Either Errno FileOffset)
- Data.Iteratee.IO.Base: newtype Errno :: *
- Data.Iteratee.IO.Base: select'read'pending :: [Fd] -> IO (Either Errno [Fd])
- Data.Iteratee.IO.Base: type FileOffset = COff
+ Data.Iteratee.Base: dropWhile :: (StreamChunk s el, Monad m) => (el -> Bool) -> IterateeG s el m ()
+ Data.Iteratee.Base: enumPair :: (ListLike (s el) el, Monad m) => IterateeG s el m a -> IterateeG s el m b -> IterateeG s el m (a, b)
+ Data.Iteratee.Base: instance Monoid ErrMsg
+ Data.Iteratee.Base: liftInner :: (Monad m, MonadTrans t, Monad (t m)) => IterateeG s el m a -> IterateeG s el (t m) a
+ Data.Iteratee.Base: looseMapStream :: (StreamChunk s el, StreamChunk s el', LooseMap s el el', Monad m) => (el -> el') -> EnumeratorN s el s el' m a
+ Data.Iteratee.Base: product :: (ListLike (s el) el, Num el, Monad m) => IterateeG s el m el
+ Data.Iteratee.Base: rigidMapStream :: (StreamChunk s el, Monad m) => (el -> el) -> EnumeratorN s el s el m a
+ Data.Iteratee.Base: stream2stream :: (StreamChunk s el, Monad m) => IterateeG s el m (s el)
+ Data.Iteratee.Base: sum :: (ListLike (s el) el, Num el, Monad m) => IterateeG s el m el
+ Data.Iteratee.Base.LooseMap: class LooseMap c el el'
+ Data.Iteratee.Base.LooseMap: looseMap :: (LooseMap c el el') => (el -> el') -> c el -> c el'
+ Data.Iteratee.Base.StreamChunk: instance ReadableChunk [] Char
+ Data.Iteratee.Base.StreamChunk: instance ReadableChunk [] Word
+ Data.Iteratee.Base.StreamChunk: instance ReadableChunk [] Word16
+ Data.Iteratee.Base.StreamChunk: instance ReadableChunk [] Word32
+ Data.Iteratee.Base.StreamChunk: instance ReadableChunk [] Word8
+ Data.Iteratee.IO.Fd: enumFd :: (ReadableChunk s el, MonadIO m) => Fd -> EnumeratorGM s el m a
+ Data.Iteratee.IO.Fd: enumFdRandom :: (ReadableChunk s el, MonadIO m) => Fd -> EnumeratorGM s el m a
+ Data.Iteratee.IO.Fd: fileDriverFd :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
+ Data.Iteratee.IO.Fd: fileDriverRandomFd :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
+ Data.Iteratee.IO.Handle: enumHandle :: (ReadableChunk s el, MonadIO m) => Handle -> EnumeratorGM s el m a
+ Data.Iteratee.IO.Handle: enumHandleRandom :: (ReadableChunk s el, MonadIO m) => Handle -> EnumeratorGM s el m a
+ Data.Iteratee.IO.Handle: fileDriverHandle :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
+ Data.Iteratee.IO.Handle: fileDriverRandomHandle :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
+ Data.Iteratee.IO.Posix: Errno :: CInt -> Errno
+ Data.Iteratee.IO.Posix: myfdRead :: Fd -> Ptr CChar -> ByteCount -> IO (Either Errno ByteCount)
+ Data.Iteratee.IO.Posix: myfdSeek :: Fd -> SeekMode -> FileOffset -> IO (Either Errno FileOffset)
+ Data.Iteratee.IO.Posix: newtype Errno :: *
+ Data.Iteratee.IO.Posix: select'read'pending :: [Fd] -> IO (Either Errno [Fd])
+ Data.Iteratee.IO.Posix: type FileOffset = COff
- Data.Iteratee: fileDriver :: (ReadableChunk s el) => IterateeG s el IO a -> FilePath -> IO a
+ Data.Iteratee: fileDriver :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
- Data.Iteratee: fileDriverRandom :: (ReadableChunk s el) => IterateeG s el IO a -> FilePath -> IO a
+ Data.Iteratee: fileDriverRandom :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
- Data.Iteratee.Base.StreamChunk: cMap :: (StreamChunk c el, StreamChunk c' el') => (el -> el') -> c el -> c' el'
+ Data.Iteratee.Base.StreamChunk: cMap :: (StreamChunk c el, StreamChunk c el') => (el -> el') -> c el -> c el'
- Data.Iteratee.Char: enumLines :: (Functor m, Monad m) => IterateeG [] Line m a -> IterateeG [] Char m (IterateeG [] Line m a)
+ Data.Iteratee.Char: enumLines :: (ListLike (s el) el, StringLike (s el), Functor m, Monad m) => IterateeG [] (s el) m a -> IterateeG s el m (IterateeG [] (s el) m a)
- Data.Iteratee.Char: enumWords :: (Functor m, Monad m) => IterateeG [] String m a -> IterateeG [] Char m (IterateeG [] String m a)
+ Data.Iteratee.Char: enumWords :: (ListLike (s el) el, StringLike (s el), Functor m, Monad m) => IterateeG [] (s el) m a -> IterateeG s el m (IterateeG [] (s el) m a)
- Data.Iteratee.IO: enumFd :: (ReadableChunk s el) => Fd -> EnumeratorGM s el IO a
+ Data.Iteratee.IO: enumFd :: (ReadableChunk s el, MonadIO m) => Fd -> EnumeratorGM s el m a
- Data.Iteratee.IO: enumFdRandom :: (ReadableChunk s el) => Fd -> EnumeratorGM s el IO a
+ Data.Iteratee.IO: enumFdRandom :: (ReadableChunk s el, MonadIO m) => Fd -> EnumeratorGM s el m a
- Data.Iteratee.IO: enumHandle :: (ReadableChunk s el) => Handle -> EnumeratorGM s el IO a
+ Data.Iteratee.IO: enumHandle :: (ReadableChunk s el, MonadIO m) => Handle -> EnumeratorGM s el m a
- Data.Iteratee.IO: enumHandleRandom :: (ReadableChunk s el) => Handle -> EnumeratorGM s el IO a
+ Data.Iteratee.IO: enumHandleRandom :: (ReadableChunk s el, MonadIO m) => Handle -> EnumeratorGM s el m a
- Data.Iteratee.IO: fileDriver :: (ReadableChunk s el) => IterateeG s el IO a -> FilePath -> IO a
+ Data.Iteratee.IO: fileDriver :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a
- Data.Iteratee.IO: fileDriverRandom :: (ReadableChunk s el) => IterateeG s el IO a -> FilePath -> IO a
+ Data.Iteratee.IO: fileDriverRandom :: (MonadIO m, ReadableChunk s el) => IterateeG s el m a -> FilePath -> m a

Files

CONTRIBUTORS view
@@ -1,10 +1,9 @@-Thanks to the following individuals for contributing code to this project.+Thanks to the following individuals for contributing to this project.  Oleg Kiselyov+Brian Lewis John Lato+Echo Nolan Paulo Tanimoto-Bas van Dijk--In addition to the above, many thanks for comments and advice provided by: Johan Tibell-Echo Nolan+Bas van Dijk
Examples/headers.hs view
@@ -11,7 +11,7 @@ -- HTTP chunk decoding -- Each chunk has the following format: ----- 	  <chunk-size> CRLF <chunk-data> CRLF+--        <chunk-size> CRLF <chunk-data> CRLF -- -- where <chunk-size> is the hexadecimal number; <chunk-data> is a -- sequence of <chunk-size> bytes.@@ -64,7 +64,7 @@   read_hex acc _ = Nothing    frame_err e iter = IterateeG (\_ ->-                     return $ Cont (joinIM $ enumErr e $ iter)+                     return $ Cont (joinIM $ enumErr e iter)                      (Just $ Err "Frame error"))  -- ------------------------------------------------------------------------@@ -89,7 +89,7 @@          enumPure1Chunk test_str1 read_lines_rest     in     lines == ["header1: v1","header2: v2","header3: v3","header4: v4",-	     "header5: v5","header6: v6","header7: v7"]+             "header5: v5","header6: v6","header7: v7"]     && rest == "rest\n"  testp2 :: Bool@@ -98,7 +98,7 @@                               enumPureNChunk test_str1 5 read_lines_rest     in     lines == ["header1: v1","header2: v2","header3: v3","header4: v4",-	     "header5: v5","header6: v6","header7: v7"]+             "header5: v5","header6: v6","header7: v7"]     && rest == "rest\n"  @@ -136,9 +136,39 @@     status <- isFinished     return (headers, body, status) -test31 = test_driver_full "test_full1.txt"-test32 = test_driver_full "test_full2.txt"-test33 = test_driver_full "test_full3.txt"+test31 = do+  putStrLn "Expected result is:"+  putStrLn "About to read headers"+  putStrLn "Finished reading"+  putStrLn "Complete headers"+  putStrLn "[\"header1: v1\",\"header2: v2\",\"header3: v3\",\"header4: v4\"]"+  putStrLn "Problem Just (Err \"EOF\")"+  putStrLn "Incomplete body"+  putStrLn "[\"body line 1\",\"body line    2\",\"body line       3\",\"body line          4\"]"+  putStrLn ""+  putStrLn "Actual result is:"+  test_driver_full "test_full1.txt" -test34 = test_driver_full "test_full3.txt"+test32 = do+  putStrLn "Expected result is:"+  putStrLn "About to read headers"+  putStrLn "*** Exception: control message: Just (Err \"Frame error\")"++  putStrLn ""+  putStrLn "Actual result is:"+  test_driver_full "test_full2.txt"++test33 = do+  putStrLn "Expected result is:"+  putStrLn "About to read headers"+  putStrLn "Finished reading"+  putStrLn "Complete headers"+  putStrLn "[\"header1: v1\",\"header2: v2\",\"header3: v3\",\"header4: v4\"]"+  putStrLn "Problem Just (Err \"EOF\")"+  putStrLn "Incomplete body"+  putStrLn "[\"body line 1\",\"body line    2\",\"body line       3\",\"body line          4\",\"body line             5\"]"++  putStrLn ""+  putStrLn "Actual result is:"+  test_driver_full "test_full3.txt" 
Examples/wave_reader.hs view
@@ -23,7 +23,7 @@  -- Use the collection of [WAVEDE] returned from wave_reader to -- do further processing.  The IntMap has an entry for each type of chunk--- in the wave file.  Read the first format chunk and disply the +-- in the wave file.  Read the first format chunk and disply the -- format information, then use the dict_process_data function -- to enumerate over the maxIter iteratee to find the maximum value -- (peak amplitude) in the file.@@ -41,4 +41,3 @@ -- efficient to use foldl' maxIter :: IterateeG [] Double IO Double maxIter = Iter.foldl' (flip (max . abs)) 0-
+ Examples/word.hs view
@@ -0,0 +1,25 @@+-- A simple wc-like program using Data.Iteratee+module Main where++import Prelude as P+import Data.Iteratee+import Data.Iteratee.Char as C+import System+++-- An iteratee to calculate the number of characters in a stream.  Very basic.+numChars :: Monad m => IterateeG [] el m Int+numChars = C.length++-- An iteratee to calculate the number of words in a stream.+numWords :: (Monad m, Functor m) => IterateeG [] Char m Int+numWords = joinI $ enumWords C.length++-- Count the number of lines, similar to numWords+numLines :: (Monad m, Functor m) => IterateeG [] Char m Int+numLines = joinI $ enumLines C.length++main = do+  f:_ <- getArgs+  words <- fileDriver (numLines `enumPair` numWords `enumPair` numChars) f+  print words
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple (defaultMain)++main :: IO ()+main = defaultMain
− Setup.lhs
@@ -1,4 +0,0 @@-#! /usr/bin/env runhaskell--> import Distribution.Simple-> main = defaultMain
iteratee.cabal view
@@ -1,68 +1,112 @@-Name:		iteratee-Version:        0.2.4-Cabal-Version:  >= 1.2-Description:	The IterateeGM monad provides strict, safe, and functional-                I/O.  In addition to pure Iteratee processors, file IO and -                combinator functions are provided.-License:	BSD3-License-file:	LICENSE-Author:		Oleg Kiselyov-Maintainer:	John W. Lato, jwlato@gmail.com-homepage:       http://inmachina.net/~jwlato/haskell/iteratee-Stability:	experimental-synopsis:       Iteratee-based I/O-category:       System, Data-build-type:     Simple-cabal-version:  >= 1.2-tested-with:    GHC == 6.10.3-extra-source-files: README LICENSE CONTRIBUTORS Examples/headers.hs Examples/test_full1.txt Examples/test_full2.txt Examples/test_full3.txt Examples/wave_reader.hs Examples/short.wav+name:          iteratee+version:       0.3.1+synopsis:      Iteratee-based I/O+description:+  The IterateeGM monad provides strict, safe, and functional I/O. In addition+  to pure Iteratee processors, file IO and combinator functions are provided.+category:      System, Data+author:        Oleg Kiselyov+maintainer:    John W. Lato <jwlato@gmail.com>+license:       BSD3+license-file:  LICENSE+homepage:      http://inmachina.net/~jwlato/haskell/iteratee+tested-with:   GHC == 6.10.4+stability:     experimental +cabal-version: >= 1.6+build-type:    Simple++extra-source-files:+  CONTRIBUTORS+  README+  Examples/*.hs+  Examples/*.txt+  Examples/*.wav+ flag splitBase-  description: Choose the new split-up base package.+  description: Use the new split-up base package.  flag buildTests-  description: build test executables+  description: Build test executables.   default:     False -Library- Hs-Source-Dirs:        src- ghc-options:           -Wall- if flag(splitBase)-   build-depends:       base >= 3, base < 5- else-   build-depends:       base < 3- if os(windows)-   cpp-options:         -DUSE_WINDOWS-   other-modules:       Data.Iteratee.IO.Windows- else-   cpp-options:         -DUSE_POSIX-   other-modules:       Data.Iteratee.IO.Posix-   build-depends:       unix- build-depends:         haskell98, containers >= 0.2 && < 0.3, bytestring >= 0.9 && < 0.10, extensible-exceptions >= 0.1 && < 0.2, transformers >= 0.1.4 && < 0.2, ListLike >= 1.0 && < 2- exposed-modules:       Data.Iteratee-                        Data.Iteratee.Base-                        Data.Iteratee.Base.StreamChunk-                        Data.Iteratee.Binary-                        Data.Iteratee.Char-                        Data.Iteratee.Codecs.Wave-                        Data.Iteratee.Codecs.Tiff-                        Data.Iteratee.IO-                        Data.Iteratee.IO.Base-                        Data.Iteratee.WrappedByteString- other-modules:         Data.Iteratee.IO.Fd-                        Data.Iteratee.IO.Handle+library+  hs-source-dirs:+    src -Executable testIteratee-  Hs-Source-Dirs:  src, tests-  Main-Is:         testIteratee.hs-  Other-Modules:   QCUtils+  if flag(splitBase)+    build-depends:+      base >= 3 && < 5+  else+    build-depends:+      base < 3++  if os(windows)+    cpp-options: -DUSE_WINDOWS+    exposed-modules:+      Data.Iteratee.IO.Windows+  else+    cpp-options: -DUSE_POSIX+    exposed-modules:+      Data.Iteratee.IO.Posix+      Data.Iteratee.IO.Fd+    build-depends:+      unix >= 2 && < 3++  build-depends:+    ListLike              >= 1.0   && < 2,+    bytestring            >= 0.9   && < 0.10,+    containers            >= 0.2   && < 0.4,+    extensible-exceptions >= 0.1   && < 0.2,+    haskell98             >= 1     && < 2,+    transformers          >= 0.1.4 && < 0.2++  exposed-modules:+    Data.Iteratee+    Data.Iteratee.Base+    Data.Iteratee.Base.StreamChunk+    Data.Iteratee.Base.LooseMap+    Data.Iteratee.Binary+    Data.Iteratee.Char+    Data.Iteratee.Codecs.Tiff+    Data.Iteratee.Codecs.Wave+    Data.Iteratee.IO+    Data.Iteratee.IO.Handle+    Data.Iteratee.WrappedByteString++  other-modules:+    Data.Iteratee.IO.Base++  ghc-options:   -Wall+  if impl(ghc >= 6.8)+    ghc-options: -fwarn-tabs++executable testIteratee+  hs-source-dirs:+    src+    tests++  main-is: testIteratee.hs++  other-modules:+    QCUtils+   if flag(buildTests)-    Build-Depends: QuickCheck >= 2 && < 3, test-framework >= 0.2 && < 0.3, test-framework-quickcheck2 >= 0.2 && < 0.3-  Else-    Executable:    False-    Buildable:     False-  If flag(splitBase)-    Build-Depends: base >= 3 && < 5-  Else-    Build-Depends: base >= 1 && < 2+    build-depends:+      QuickCheck                 >= 2   && < 3,+      test-framework             >= 0.2 && < 0.3,+      test-framework-quickcheck2 >= 0.2 && < 0.3+  else+    executable: False+    buildable:  False +  if flag(splitBase)+    build-depends:+      base >= 3 && < 5+  else+    build-depends:+      base < 3++source-repository head+  type:     darcs+  location: http://inmachina.net/~jwlato/haskell/iteratee
src/Data/Iteratee.hs view
@@ -16,4 +16,3 @@ import Data.Iteratee.Base import Data.Iteratee.Binary import Data.Iteratee.IO-
src/Data/Iteratee/Base.hs view
@@ -13,21 +13,23 @@   EnumeratorGM,   EnumeratorGMM,   -- * Iteratees-  -- ** Iteratee Combinators+  -- ** Iteratee Utilities   joinI,   liftI,   isFinished,   run,   joinIM,   stream2list,+  stream2stream,   checkIfDone,+  liftInner,   -- ** Error handling   setEOF,   throwErr,   checkErr,   -- ** Basic Iteratees   break,-  --dropWhile,+  dropWhile,   drop,   identity,   head,@@ -39,30 +41,41 @@   take,   takeR,   mapStream,+  rigidMapStream,+  looseMapStream,   convStream,   filter,   -- ** Folds   foldl,   foldl',   foldl1,+  -- ** Special Folds+  sum,+  product,   -- * Enumerators+  -- ** Basic enumerators   enumEof,   enumErr,-  (>.),   enumPure1Chunk,   enumPureNChunk,+  -- ** Enumerator Combinators+  (>.),+  enumPair,   -- * Misc.   seek,-  FileOffset+  FileOffset,+  -- * Classes+  module Data.Iteratee.Base.LooseMap ) where -import Prelude hiding (head, drop, dropWhile, take, break, foldl, foldl1, length, filter)+import Prelude hiding (head, drop, dropWhile, take, break, foldl, foldl1, length, filter, sum, product) import qualified Prelude as P  import qualified Data.Iteratee.Base.StreamChunk as SC import qualified Data.ListLike as LL import qualified Data.ListLike.FoldableLL as FLL+import Data.Iteratee.Base.LooseMap import Data.Iteratee.IO.Base import Control.Monad import Control.Applicative@@ -112,6 +125,13 @@               | Seek FileOffset               deriving (Show, Eq) +instance Monoid ErrMsg where+  mempty = Err ""+  mappend (Err s1) (Err s2)  = Err (s1 ++ s2)+  mappend e@(Err _) _        = e+  mappend _        e@(Err _) = e+  mappend (Seek _) (Seek b)  = Seek b+ -- |Iteratee -- a generic stream processor, what is being folded over -- a stream -- When Iteratee is in the 'done' state, it contains the computed@@ -144,8 +164,7 @@ -- Useful combinators for implementing iteratees and enumerators  -- | Lift an IterGV result into an 'IterateeG'-liftI :: (Monad m, SC.StreamChunk s el) =>-         IterGV s el m a -> IterateeG s el m a+liftI :: (Monad m, SC.StreamChunk s el) => IterGV s el m a -> IterateeG s el m a liftI (Cont k Nothing)     = k liftI (Cont _k (Just err)) = throwErr err liftI i@(Done _ (EOF _  )) = IterateeG (const (return i))@@ -164,7 +183,7 @@  -- | Check if a stream has finished ('EOF'). isFinished :: (SC.StreamChunk s el, Monad m) =>-              IterateeG s el m (Maybe ErrMsg)+  IterateeG s el m (Maybe ErrMsg) isFinished = IterateeG check   where   check s@(EOF e) = return $ Done (Just $ fromMaybe (Err "EOF") e) s@@ -174,9 +193,9 @@ -- finished then apply it to the given 'EnumeratorGM'. -- If in error, throw the error. checkIfDone :: (SC.StreamChunk s el, Monad m) =>-               (IterateeG s el m a -> m (IterateeG s el m a)) ->-               IterGV s el m a ->-               m (IterateeG s el m a)+  (IterateeG s el m a -> m (IterateeG s el m a)) ->+  IterGV s el m a ->+  m (IterateeG s el m a) checkIfDone _ (Done x _)        = return . return $ x checkIfDone k (Cont x Nothing)  = k x checkIfDone _ (Cont _ (Just e)) = return . throwErr $ e@@ -192,13 +211,25 @@ -- for embedded/nested streams.  In particular, joinI is useful to -- process the result of take, mapStream, or convStream below. joinI :: (SC.StreamChunk s el, SC.StreamChunk s' el', Monad m) =>-         IterateeG s el m (IterateeG s' el' m a) ->-         IterateeG s el m a+  IterateeG s el m (IterateeG s' el' m a) ->+  IterateeG s el m a joinI m = IterateeG (docase <=< runIter m)   where   docase (Done ma str) = liftM (flip Done str) (run ma)   docase (Cont k mErr) = return $ Cont (joinI k) mErr +-- |Layer a monad transformer over the inner monad.+liftInner :: (Monad m, MonadTrans t, Monad (t m)) =>+  IterateeG s el m a ->+  IterateeG s el (t m) a+liftInner iter = IterateeG step+  where+  step str = do+    igv <- lift $ runIter iter str+    case igv of+      Done a res  -> return $ Done a res+      Cont k mErr -> return $ Cont (liftInner k) mErr+ -- It turns out, IterateeG form a monad. We can use the familiar do -- notation for composing Iteratees @@ -207,9 +238,9 @@   (>>=)    = iterBind  iterBind :: (Monad m ) =>-             IterateeG s el m a ->-             (a -> IterateeG s el m b) ->-             IterateeG s el m b+  IterateeG s el m a ->+  (a -> IterateeG s el m b) ->+  IterateeG s el m b iterBind m f = IterateeG (docase <=< runIter m)   where   docase (Done a str)  = runIter (f a) str@@ -250,6 +281,18 @@                                  Nothing   step acc str        = return $ Done (SC.toList acc) str +-- |Read a stream to the end and return all of its elements as a stream+stream2stream :: (SC.StreamChunk s el, Monad m) => IterateeG s el m (s el)+stream2stream = IterateeG (step mempty)+  where+  step acc (Chunk ls)+    | SC.null ls      = return $ Cont (IterateeG (step acc)) Nothing+  step acc (Chunk ls) = return $ Cont+                                 (IterateeG (step (acc `mappend` ls)))+                                 Nothing+  step acc str        = return $ Done acc str++ -- |Report and propagate an error.  Disregard the input first and then -- propagate the error. throwErr :: (Monad m) => ErrMsg -> IterateeG s el m a@@ -267,8 +310,8 @@ -- with an empty stream.  In particular, it enables them to be used with -- 'convStream'. checkErr :: (Monad m, SC.StreamChunk s el) =>-              IterateeG s el m a ->-              IterateeG s el m (Either ErrMsg a)+  IterateeG s el m a ->+  IterateeG s el m (Either ErrMsg a) checkErr iter = IterateeG (check <=< runIter iter)   where   check (Done a str) = return $ Done (Right a) str@@ -288,8 +331,8 @@ -- satisfies the predicate.  break :: (SC.StreamChunk s el, Monad m) =>-          (el -> Bool) ->-          IterateeG s el m (s el)+  (el -> Bool) ->+  IterateeG s el m (s el) break cpred = IterateeG (step mempty)   where   step before (Chunk str) | SC.null str = return $@@ -325,8 +368,8 @@ -- For example, if the stream contains "abd", then (heads "abc") -- will remove the characters "ab" and return 2. heads :: (SC.StreamChunk s el, Monad m, Eq el) =>-         s el ->-         IterateeG s el m Int+  s el ->+  IterateeG s el m Int heads st | SC.null st = return 0 heads st = loop 0 st   where@@ -382,7 +425,20 @@   step (Chunk str)       = return $ Done () (Chunk (LL.drop n str))   step stream            = return $ Done () stream +-- |Skip all elements while the predicate is true.+-- This is the analogue of List.dropWhile+dropWhile :: (SC.StreamChunk s el, Monad m) =>+  (el -> Bool) ->+  IterateeG s el m ()+dropWhile p = IterateeG step+  where+  step (Chunk str) = let dropped = LL.dropWhile p str+                     in if LL.null dropped+                       then return $ Cont (dropWhile p) Nothing+                       else return $ Done () (Chunk dropped)+  step stream      = return $ Done () stream + -- |Return the total length of the stream length :: (Num a, LL.ListLike (s el) el, Monad m) => IterateeG s el m a length = length' 0@@ -410,19 +466,19 @@ -- stream of the read elements. Unless the stream is terminated early, we -- read exactly n elements (even if the iteratee has accepted fewer). take :: (SC.StreamChunk s el, Monad m) =>-        Int ->-        EnumeratorN s el s el m a+  Int ->+  EnumeratorN s el s el m a take 0 iter = return iter take n' iter = IterateeG (step n')   where   step n chk@(Chunk str)     | SC.null str = return $ Cont (take n iter) Nothing-    | SC.length str <= n = return $ Cont (joinIM inner) Nothing+    | SC.length str < n = liftM (flip Cont Nothing) inner       where inner = liftM (check (n - SC.length str)) (runIter iter chk)   step n (Chunk str) = done (Chunk s1) (Chunk s2)     where (s1, s2) = SC.splitAt n str   step _n stream            = done stream stream-  check n (Done x _)        = drop n >> (return $ return x)+  check n (Done x _)        = drop n >> return (return x)   check n (Cont x Nothing)  = take n x   check n (Cont _ (Just e)) = drop n >> throwErr e   done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return)@@ -435,9 +491,9 @@ -- of processing of the outer stream once the processing of the inner stream -- finished early. takeR :: (SC.StreamChunk s el, Monad m) =>-         Int ->-         IterateeG s el m a ->-         IterateeG s el m (IterateeG s el m a)+  Int ->+  IterateeG s el m a ->+  IterateeG s el m (IterateeG s el m a) takeR 0 iter = return iter takeR n iter = IterateeG (step n)   where@@ -459,14 +515,43 @@ -- Note the contravariance  mapStream :: (SC.StreamChunk s el, SC.StreamChunk s el', Monad m) =>-              (el -> el') ->-              EnumeratorN s el s el' m a-mapStream f iter = IterateeG ((check <=< runIter iter) . strMap (SC.cMap f))+ (el -> el')+  -> EnumeratorN s el s el' m a+mapStream f i = IterateeG ((check <=< runIter i) . strMap (SC.cMap f))   where-  check (Done a _) = return $ Done (return a) (Chunk LL.empty)-  check (Cont k mErr) = return $ Cont (mapStream f k) mErr+    go iter = IterateeG ((check <=< runIter iter) . strMap (SC.cMap f))+    check (Done a _)    = return $ Done (return a) (Chunk LL.empty)+    check (Cont k mErr) = return $ Cont (go k) mErr +-- |Map a stream without changing the element type.  For StreamChunks+-- with limited element types (e.g. bytestrings)+-- this can be much more efficient than regular mapStream+rigidMapStream :: (SC.StreamChunk s el, Monad m) =>+  (el -> el)+  -> EnumeratorN s el s el m a+rigidMapStream f i =  go i+  where+    go iter = IterateeG ((check <=< runIter iter) . strMap (LL.rigidMap f))+    check (Done a _)    = return $ Done (return a) (Chunk LL.empty)+    check (Cont k mErr) = return $ Cont (go k) mErr +-- |Yet another stream mapping function.  For container instances with+-- class contexts, such as uvector or storablevector, this allows+-- the native map function to be used  and is likely to be much+-- more efficient than the standard mapStream.+looseMapStream :: (SC.StreamChunk s el,+    SC.StreamChunk s el',+    LooseMap s el el',+    Monad m) =>+  (el -> el')+  -> EnumeratorN s el s el' m a+looseMapStream f i =  go i+  where+    go iter = IterateeG ((check <=< runIter iter) . strMap (looseMap f))+    check (Done a _)    = return $ Done (return a) (Chunk LL.empty)+    check (Cont k mErr) = return $ Cont (go k) mErr++ -- |Convert one stream into another, not necessarily in `lockstep' -- The transformer mapStream maps one element of the outer stream -- to one element of the nested stream.  The transformer below is more@@ -491,8 +576,8 @@ -- |Creates an enumerator with only elements from the stream that -- satisfy the predicate function. filter :: (LL.ListLike (s el) el, Monad m) =>-          (el -> Bool) ->-          EnumeratorN s el s el m a+  (el -> Bool) ->+  EnumeratorN s el s el m a filter p = convStream f'   where   f' = IterateeG step@@ -505,33 +590,37 @@  -- | Left-associative fold. foldl :: (LL.ListLike (s el) el, FLL.FoldableLL (s el) el, Monad m) =>-         (a -> el -> a) ->-         a ->-         IterateeG s el m a-foldl f i = iter+  (a -> el -> a) ->+  a ->+  IterateeG s el m a+foldl f i = iter i   where-  iter = IterateeG step-  step (Chunk xs) | LL.null xs = return $ Cont (iter) Nothing-  step (Chunk xs) = return $ Cont (foldl f (FLL.foldl f i xs)) Nothing-  step stream     = return $ Done i stream+  iter ac = IterateeG step+    where+      step (Chunk xs) | LL.null xs = return $ Cont (iter ac) Nothing+      step (Chunk xs) = return $ Cont (iter (FLL.foldl f ac xs)) Nothing+      step stream     = return $ Done ac stream  -- | Left-associative fold that is strict in the accumulator. foldl' :: (LL.ListLike (s el) el, FLL.FoldableLL (s el) el, Monad m) =>-          (a -> el -> a) ->-          a ->-          IterateeG s el m a-foldl' f i = iter+  (a -> el -> a) ->+  a ->+  IterateeG s el m a+foldl' f i = IterateeG (step i)   where-  iter = IterateeG step-  step (Chunk xs) | LL.null xs = return $ Cont (iter) Nothing-  step (Chunk xs) = return $ Cont (foldl' f $! FLL.foldl' f i xs) Nothing-  step stream     = return $ Done i stream+    step ac (Chunk xs) | LL.null xs = return $ Cont (IterateeG (step ac))+                                               Nothing+    step ac (Chunk xs) = return $ Cont (IterateeG (step $! FLL.foldl' f ac xs))+                                       Nothing+    step ac stream     = return $ Done ac stream +{-# INLINE foldl' #-}+ -- | Variant of foldl with no base case.  Requires at least one element --   in the stream. foldl1 :: (LL.ListLike (s el) el, FLL.FoldableLL (s el) el, Monad m) =>-          (el -> el -> el) ->-          IterateeG s el m el+  (el -> el -> el) ->+  IterateeG s el m el foldl1 f = IterateeG step   where   step (Chunk xs) | LL.null xs = return $ Cont (foldl1 f) Nothing@@ -540,7 +629,55 @@   step (Chunk xs) = return $ Cont (foldl f (FLL.foldl1 f xs)) Nothing   step stream     = return $ Cont (foldl1 f) (Just (setEOF stream)) +-- | Sum of a stream.+sum :: (LL.ListLike (s el) el, Num el, Monad m) =>+  IterateeG s el m el+sum = IterateeG (step 0)+  where+    step acc (Chunk xs)+      | LL.null xs = return $ Cont (IterateeG (step acc)) Nothing+    step acc (Chunk xs) = return $ Cont (IterateeG . step $! acc + (LL.sum xs))+                                        Nothing+    step acc str = return $ Done acc str++-- | Product of a stream+product :: (LL.ListLike (s el) el, Num el, Monad m) =>+  IterateeG s el m el+product = IterateeG (step 1)+  where+    step acc (Chunk xs)+      | LL.null xs = return $ Cont (IterateeG (step acc)) Nothing+    step acc (Chunk xs) = return $ Cont (IterateeG . step $! acc *+                                          (LL.product xs))+                                        Nothing+    step acc str = return $ Done acc str+ -- ------------------------------------------------------------------------+-- Zips++-- |Enumerate two iteratees over a single stream simultaneously.+enumPair :: (LL.ListLike (s el) el, Monad m) =>+  IterateeG s el m a ->+  IterateeG s el m b ->+  IterateeG s el m (a,b)+enumPair i1 i2 = IterateeG step+  where+  longest c1@(Chunk xs) c2@(Chunk ys) = if LL.length xs > LL.length ys+                                        then c1 else c2+  longest e@(EOF _)  _          = e+  longest _          e@(EOF _)  = e+  step (Chunk xs) | LL.null xs = return $ Cont (IterateeG step) Nothing+  step str = do+    ia <- runIter i1 str+    ib <- runIter i2 str+    case (ia, ib) of+      (Done a astr, Done b bstr)  -> return $ Done (a,b) $ longest astr bstr+      (Done a _astr, Cont k mErr) -> return $ Cont (enumPair (return a) k) mErr+      (Cont k mErr, Done b _bstr) -> return $ Cont (enumPair k (return b)) mErr+      (Cont a aEr,  Cont b bEr)   -> return $ Cont (enumPair a b)+                                                   (aEr `mappend` bEr)++-- ------------------------------------------------------------------------ -- Enumerators -- |Each enumerator takes an iteratee and returns an iteratee -- an Enumerator is an iteratee transformer.@@ -563,7 +700,7 @@ -- |The most primitive enumerator: applies the iteratee to the terminated -- stream. The result is the iteratee usually in the done state. enumEof :: Monad m =>-           EnumeratorGM s el m a+  EnumeratorGM s el m a enumEof iter = runIter iter (EOF Nothing) >>= check   where   check (Done x _) = return $ IterateeG $ return . Done x@@ -571,8 +708,8 @@  -- |Another primitive enumerator: report an error enumErr :: (SC.StreamChunk s el, Monad m) =>-           String ->-           EnumeratorGM s el m a+  String ->+  EnumeratorGM s el m a enumErr e iter = runIter iter (EOF (Just (Err e))) >>= check   where   check (Done x _)  = return $ IterateeG (return . Done x)@@ -584,15 +721,15 @@ -- though: in e1 >. e2, e1 is executed first  (>.):: (SC.StreamChunk s el, Monad m) =>-       EnumeratorGM s el m a -> EnumeratorGM s el m a -> EnumeratorGM s el m a+  EnumeratorGM s el m a -> EnumeratorGM s el m a -> EnumeratorGM s el m a (>.) e1 e2 = e2 <=< e1  -- |The pure 1-chunk enumerator -- It passes a given list of elements to the iteratee in one chunk -- This enumerator does no IO and is useful for testing of base parsing enumPure1Chunk :: (SC.StreamChunk s el, Monad m) =>-                    s el ->-                    EnumeratorGM s el m a+  s el ->+  EnumeratorGM s el m a enumPure1Chunk str iter = runIter iter (Chunk str) >>= checkIfDone return  @@ -601,9 +738,9 @@ -- This enumerator does no IO and is useful for testing of base parsing -- and handling of chunk boundaries enumPureNChunk :: (SC.StreamChunk s el, Monad m) =>-                    s el ->-                    Int ->-                    EnumeratorGM s el m a+  s el ->+  Int ->+  EnumeratorGM s el m a enumPureNChunk str _ iter | SC.null str = return iter enumPureNChunk str n iter | n > 0 = runIter iter (Chunk s1) >>=                                     checkIfDone (enumPureNChunk s2 n)@@ -612,7 +749,5 @@ enumPureNChunk _ n _ = error $ "enumPureNChunk called with n==" ++ show n  -- |A variant of join for Iteratees in a monad.-joinIM :: (Monad m) =>-          m (IterateeG s el m a) -> IterateeG s el m a+joinIM :: (Monad m) => m (IterateeG s el m a) -> IterateeG s el m a joinIM m = IterateeG (\str -> m >>= flip runIter str)-
+ src/Data/Iteratee/Base/LooseMap.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE MultiParamTypeClasses #-}+module Data.Iteratee.Base.LooseMap (+  LooseMap (..)+)++where++-- |Enable map functions for containers that require class contexts on the+-- element types.  There's really no reason to ever use this with+-- types that are fully polymorphic, such as Lists.+class LooseMap c el el' where+  looseMap :: (el -> el') -> c el -> c el'
src/Data/Iteratee/Base/StreamChunk.hs view
@@ -15,6 +15,8 @@  import qualified Data.List as L import qualified Data.ListLike as LL+import Data.Word+import Foreign.C import Foreign.Ptr import Foreign.Storable import Foreign.Marshal.Array@@ -64,16 +66,11 @@   toList = LL.toList    -- |Map a computation over the stream.-  cMap :: (StreamChunk c' el') => (el -> el') -> c el -> c' el'+  cMap :: (StreamChunk c el') => (el -> el') -> c el -> c el'   cMap f = LL.foldr (LL.cons . f) LL.empty  instance StreamChunk [] el where-  cMap       = listmap--listmap :: (StreamChunk s' el') => (el -> el') -> [el] -> s' el'-listmap f = foldr (LL.cons . f) LL.empty--{-# RULES "listmap/map" listmap = map #-}+  cMap       = map  -- |Class of streams which can be filled from a 'Ptr'.  Typically these -- are streams which can be read from a file.@@ -82,6 +79,17 @@ class (StreamChunk s el, Storable el) => ReadableChunk s el where   readFromPtr :: Ptr (el) -> Int -> IO (s el) -instance (Storable el) => ReadableChunk [] el where+instance ReadableChunk [] Char where+  readFromPtr buf l = peekCAStringLen (castPtr buf, l)++instance ReadableChunk [] Word8 where   readFromPtr = flip peekArray +instance ReadableChunk [] Word16 where+  readFromPtr = flip peekArray++instance ReadableChunk [] Word32 where+  readFromPtr = flip peekArray++instance ReadableChunk [] Word where+  readFromPtr = flip peekArray
src/Data/Iteratee/Binary.hs view
@@ -29,7 +29,7 @@   deriving (Eq, Ord, Show, Enum)  endianRead2 :: (StreamChunk s Word8, Monad m) => Endian ->-                It.IterateeG s Word8 m Word16+  It.IterateeG s Word8 m Word16 endianRead2 e = do   c1 <- It.head   c2 <- It.head@@ -41,7 +41,7 @@ -- set the entire first byte so the Word32 can be properly set negative as -- well. endianRead3 :: (StreamChunk s Word8, Monad m) => Endian ->-                It.IterateeG s Word8 m Word32+  It.IterateeG s Word8 m Word32 endianRead3 e = do   c1 <- It.head   c2 <- It.head@@ -58,22 +58,20 @@                         `shiftL` 8) .|. fromIntegral m  endianRead4 :: (StreamChunk s Word8, Monad m) => Endian ->-                It.IterateeG s Word8 m Word32+  It.IterateeG s Word8 m Word32 endianRead4 e = do   c1 <- It.head   c2 <- It.head   c3 <- It.head   c4 <- It.head   case e of-    MSB -> return $ -	       (((((fromIntegral c1-		`shiftL` 8) .|. fromIntegral c2)-	        `shiftL` 8) .|. fromIntegral c3)-	        `shiftL` 8) .|. fromIntegral c4-    LSB -> return $ -	       (((((fromIntegral c4-		`shiftL` 8) .|. fromIntegral c3)-	        `shiftL` 8) .|. fromIntegral c2)-	        `shiftL` 8) .|. fromIntegral c1--+    MSB -> return $+               (((((fromIntegral c1+                `shiftL` 8) .|. fromIntegral c2)+                `shiftL` 8) .|. fromIntegral c3)+                `shiftL` 8) .|. fromIntegral c4+    LSB -> return $+               (((((fromIntegral c4+                `shiftL` 8) .|. fromIntegral c3)+                `shiftL` 8) .|. fromIntegral c2)+                `shiftL` 8) .|. fromIntegral c1
src/Data/Iteratee/Char.hs view
@@ -34,6 +34,8 @@ import Data.Iteratee.Base hiding (break) import Data.Char import Control.Monad.Trans+import qualified Data.ListLike as LL+import Data.Monoid  -- |A particular instance of StreamG: the stream of characters. -- This stream is used by many input parsers.@@ -43,7 +45,7 @@  -- Useful combinators for implementing iteratees and enumerators -type Line = String	-- The line of text, terminators are not included+type Line = String      -- The line of text, terminators are not included  -- |Read the line of text from the stream -- The line can be terminated by CR, LF or CRLF.@@ -105,15 +107,27 @@ -- This is the first proper iteratee-enumerator: it is the iteratee of the -- character stream and the enumerator of the line stream. -enumLines :: (Functor m, Monad m) =>-             IterateeG [] Line m a ->-             IterateeG [] Char m (IterateeG [] Line m a)-enumLines iter = line >>= check iter+enumLines :: (LL.ListLike (s el) el, LL.StringLike (s el), Functor m, Monad m) =>+  IterateeG [] (s el) m a ->+  IterateeG s el m (IterateeG [] (s el) m a)+enumLines = convStream getter   where-  --check :: Either Line Line -> IterateeG [] Char m (IterateeG [] Line m a)-  check iter' (Left l)  = runLine iter' l-  check iter' (Right l) = runLine iter' l-  runLine i' l = return . joinIM . fmap Iter.liftI $ (runIter i' $ Chunk [l])+    getter = IterateeG step+    lChar = (== '\n') . last . LL.toString+    step (Chunk xs)+      | LL.null xs = return $ Cont getter Nothing+      | lChar xs   = return $ Done (Just $ LL.lines xs) (Chunk mempty)+      | True       = return $ Cont (IterateeG (step' xs)) Nothing+    step str       = return $ Done Nothing str+    step' xs (Chunk ys)+      | LL.null ys = return $ Cont (IterateeG (step' xs)) Nothing+      | lChar ys   = return $ Done (Just . LL.lines . mappend xs $ ys)+                                   (Chunk mempty)+      | True       = let w' = LL.lines $ mappend xs ys+                         ws = init w'+                         ck = last w'+                     in return $ Done (Just ws) (Chunk ck)+    step' xs str   = return $ Done (Just $ LL.lines xs) str   -- |Convert the stream of characters to the stream of words, and@@ -123,19 +137,34 @@ -- One should keep in mind that enumWords is a more general, monadic -- function. -enumWords :: (Functor m, Monad m) =>-	     IterateeG [] String m a ->-             IterateeG [] Char m (IterateeG [] String m a)-enumWords iter = Iter.break isSpace >>= check iter+enumWords :: (LL.ListLike (s el) el+    , LL.StringLike (s el)+    , Functor m, Monad m)+  => IterateeG [] (s el) m a+  -> IterateeG s el m (IterateeG [] (s el) m a)+enumWords = convStream getter   where-  --check :: String -> IterateeG [] Char m (IterateeG [] String m a)-  check iter' "" = return iter'-  check iter' w  = return . joinIM . fmap Iter.liftI $-                   (runIter iter' $ Chunk [w])+    getter = IterateeG step+    lChar = isSpace . last . LL.toString+    step (Chunk xs) | LL.null xs = return $ Cont getter Nothing+    step (Chunk xs)+      | LL.null xs = return $ Cont getter Nothing+      | lChar xs   = return $ Done (Just $ LL.words xs) (Chunk mempty)+      | True       = return $ Cont (IterateeG (step' xs)) Nothing+    step str       = return $ Done Nothing str+    step' xs (Chunk ys)+      | LL.null ys = return $ Cont (IterateeG (step' xs)) Nothing+      | lChar ys   = return $ Done (Just . LL.words . mappend xs $ ys)+                                   (Chunk mempty)+      | True       = let w' = LL.words $ mappend xs ys+                         ws = init w'+                         ck = last w'+                     in return $ Done (Just ws) (Chunk ck)+    step' xs str   = return $ Done (Just $ LL.words xs) str +{-# INLINE enumWords #-}  -- ------------------------------------------------------------------------ -- Enumerators  type EnumeratorM m a = EnumeratorGM [] Char m a-
src/Data/Iteratee/Codecs/Tiff.hs view
@@ -5,16 +5,16 @@ -- A general-purpose TIFF library  -- The library gives the user the TIFF dictionary, which the user--- can search for specific tags and obtain the values associated with +-- can search for specific tags and obtain the values associated with -- the tags, including the pixel matrix. -- -- The overarching theme is incremental processing: initially, -- only the TIFF dictionary is read. The value associated with a tag -- is read only when that tag is looked up (unless the value was short -- and was packed in the TIFF dictionary entry). The pixel matrix--- (let alone the whole TIFF file) is not loaded in memory -- +-- (let alone the whole TIFF file) is not loaded in memory -- -- the pixel matrix is not even located before it is needed.--- The matrix is processed incrementally, by a user-supplied +-- The matrix is processed incrementally, by a user-supplied -- iteratee. -- -- The incremental processing is accomplished by iteratees and enumerators.@@ -23,8 +23,8 @@ -- represent the values associated with tags; the values will be read -- on demand, when the enumerator is applied to a user-given iteratee. ----- The library extensively uses nested streams, tacitly converting the --- stream of raw bytes from the file into streams of integers, +-- The library extensively uses nested streams, tacitly converting the+-- stream of raw bytes from the file into streams of integers, -- rationals and other user-friendly items. The pixel matrix is -- presented as a contiguous stream, regardless of its segmentation -- into strips and physical arrangement.@@ -48,7 +48,7 @@ --     http://okmij.org/ftp/Scheme/binary-io.html#tiff -- The main distinction is using iteratees for on-demand processing. -module Data.Iteratee.Codecs.Tiff where+module Data.Iteratee.Codecs.Tiff {-# DEPRECATED "This will be moved to a separate package in the future" #-} where  import Data.Iteratee import qualified Data.Iteratee as Iter@@ -90,7 +90,7 @@   check_tag TG_IMAGELENGTH (flip dict_read_int dict) 122   check_tag TG_BITSPERSAMPLE (flip dict_read_int dict) 8   check_tag TG_IMAGEDESCRIPTION (flip dict_read_string dict)-		"JPEG:gnu-head-sm.jpg 129x122"+                "JPEG:gnu-head-sm.jpg 129x122"   check_tag TG_COMPRESSION (flip dict_read_int dict) 1   check_tag TG_SAMPLESPERPIXEL (flip dict_read_int dict) 1   check_tag TG_STRIPBYTECOUNTS (flip dict_read_int dict) 15738 -- nrows*ncols@@ -106,10 +106,10 @@   --maybe (return ()) error err   --return err  where check_tag tag action v = do-	   vc <- action tag-	   case vc of-	     Just v' | v' == v -> note ["Tag ",show tag, " value ", show v]-	     _ -> error $ unwords ["Tag", show tag, "unexpected:", show vc]+           vc <- action tag+           case vc of+             Just v' | v' == v -> note ["Tag ",show tag, " value ", show v]+             _ -> error $ unwords ["Tag", show tag, "unexpected:", show vc]  -- process_tiff Nothing = return Nothing @@ -135,8 +135,8 @@ -- as everything is verified or the error is detected verify_pixel_vals :: MonadIO m =>                      TIFFDict -> [(IM.Key, Word8)] -> IterateeG [] Word8 m ()-verify_pixel_vals dict pixels = Iter.joinI $ pixel_matrix_enum dict $ -				verify 0 (IM.fromList pixels)+verify_pixel_vals dict pixels = Iter.joinI $ pixel_matrix_enum dict $+                                verify 0 (IM.fromList pixels)  where  verify _ m | IM.null m = return ()  verify n m = IterateeG (step n m)@@ -144,10 +144,11 @@    | SC.null xs = return $ Cont (verify n m) Nothing    | otherwise = let (h, t) = (SC.head xs, SC.tail xs) in    case IM.updateLookupWithKey (\_k _e -> Nothing) n m of-    (Just v,m') -> if v == h then step (succ n) m' (Chunk t)-		     else let er = (unwords ["Pixel #",show n,-					      "expected:",show v,-					      "found", show h])+    (Just v,m') -> if v == h+                     then step (succ n) m' (Chunk t)+                     else let er = (unwords ["Pixel #",show n,+                                             "expected:",show v,+                                             "found", show h])                           in return $ Cont (throwErr . Err $ er) (Just $ Err er)     (Nothing,m')->    step (succ n) m' (Chunk t)  step _n _m s = return $ Done () s@@ -161,8 +162,8 @@ type TIFFDict = IM.IntMap TIFFDE  data TIFFDE = TIFFDE{tiffde_count :: Int,        -- number of items-		     tiffde_enum  :: TIFFDE_ENUM -- enumerator to get values-		    }+                     tiffde_enum  :: TIFFDE_ENUM -- enumerator to get values+                    }  data TIFFDE_ENUM =   TEN_CHAR (forall a m. Monad m => EnumeratorGMM [] Word8 [] Char m a)@@ -177,7 +178,7 @@   | TT_short     -- 3   16-bit unsigned integer   | TT_long      -- 4   32-bit unsigned integer   | TT_rational  -- 5   64-bit fractional (numer+denominator)-    				-- The following was added in TIFF 6.0+                                -- The following was added in TIFF 6.0   | TT_sbyte     -- 6   8-bit signed (2s-complement) integer   | TT_undefined -- 7   An 8-bit byte, "8-bit chunk"   | TT_sshort    -- 8   16-bit signed (2s-complement) integer@@ -189,55 +190,55 @@   -- Standard TIFF tags-data TIFF_TAG = TG_other Int		-- other than below-  | TG_SUBFILETYPE 	        -- subfile data descriptor+data TIFF_TAG = TG_other Int            -- other than below+  | TG_SUBFILETYPE              -- subfile data descriptor   | TG_OSUBFILETYPE             -- +kind of data in subfile-  | TG_IMAGEWIDTH	        -- image width in pixels-  | TG_IMAGELENGTH	        -- image height in pixels-  | TG_BITSPERSAMPLE	        -- bits per channel (sample)-  | TG_COMPRESSION	        -- data compression technique-  | TG_PHOTOMETRIC	        -- photometric interpretation-  | TG_THRESHOLDING		-- +thresholding used on data-  | TG_CELLWIDTH		-- +dithering matrix width-  | TG_CELLLENGTH	        -- +dithering matrix height-  | TG_FILLORDER		-- +data order within a byte-  | TG_DOCUMENTNAME	        -- name of doc. image is from-  | TG_IMAGEDESCRIPTION	        -- info about image-  | TG_MAKE			-- scanner manufacturer name-  | TG_MODEL			-- scanner model name/number-  | TG_STRIPOFFSETS		-- offsets to data strips-  | TG_ORIENTATION	        -- +image orientation+  | TG_IMAGEWIDTH               -- image width in pixels+  | TG_IMAGELENGTH              -- image height in pixels+  | TG_BITSPERSAMPLE            -- bits per channel (sample)+  | TG_COMPRESSION              -- data compression technique+  | TG_PHOTOMETRIC              -- photometric interpretation+  | TG_THRESHOLDING             -- +thresholding used on data+  | TG_CELLWIDTH                -- +dithering matrix width+  | TG_CELLLENGTH               -- +dithering matrix height+  | TG_FILLORDER                -- +data order within a byte+  | TG_DOCUMENTNAME             -- name of doc. image is from+  | TG_IMAGEDESCRIPTION         -- info about image+  | TG_MAKE                     -- scanner manufacturer name+  | TG_MODEL                    -- scanner model name/number+  | TG_STRIPOFFSETS             -- offsets to data strips+  | TG_ORIENTATION              -- +image orientation   | TG_SAMPLESPERPIXEL          -- samples per pixel-  | TG_ROWSPERSTRIP	        -- rows per strip of data+  | TG_ROWSPERSTRIP             -- rows per strip of data   | TG_STRIPBYTECOUNTS          -- bytes counts for strips-  | TG_MINSAMPLEVALUE	        -- +minimum sample value+  | TG_MINSAMPLEVALUE           -- +minimum sample value   | TG_MAXSAMPLEVALUE           -- maximum sample value   | TG_XRESOLUTION              -- pixels/resolution in x   | TG_YRESOLUTION              -- pixels/resolution in y   | TG_PLANARCONFIG             -- storage organization-  | TG_PAGENAME		        -- page name image is from-  | TG_XPOSITION		-- x page offset of image lhs-  | TG_YPOSITION		-- y page offset of image lhs-  | TG_FREEOFFSETS	        -- +byte offset to free block-  | TG_FREEBYTECOUNTS	        -- +sizes of free blocks+  | TG_PAGENAME                 -- page name image is from+  | TG_XPOSITION                -- x page offset of image lhs+  | TG_YPOSITION                -- y page offset of image lhs+  | TG_FREEOFFSETS              -- +byte offset to free block+  | TG_FREEBYTECOUNTS           -- +sizes of free blocks   | TG_GRAYRESPONSEUNIT         -- gray scale curve accuracy-  | TG_GRAYRESPONSECURVE	-- gray scale response curve+  | TG_GRAYRESPONSECURVE        -- gray scale response curve   | TG_GROUP3OPTIONS            -- 32 flag bits-  | TG_GROUP4OPTIONS 	        -- 32 flag bits+  | TG_GROUP4OPTIONS            -- 32 flag bits   | TG_RESOLUTIONUNIT           -- units of resolutions-  | TG_PAGENUMBER	        -- page numbers of multi-page-  | TG_COLORRESPONSEUNIT 	-- color scale curve accuracy+  | TG_PAGENUMBER               -- page numbers of multi-page+  | TG_COLORRESPONSEUNIT        -- color scale curve accuracy   | TG_COLORRESPONSECURVE       -- RGB response curve-  | TG_SOFTWARE			-- name & release-  | TG_DATETIME 		-- creation date and time-  | TG_ARTIST			-- creator of image-  | TG_HOSTCOMPUTER		-- machine where created-  | TG_PREDICTOR 		-- prediction scheme w/ LZW-  | TG_WHITEPOINT		-- image white point+  | TG_SOFTWARE                 -- name & release+  | TG_DATETIME                 -- creation date and time+  | TG_ARTIST                   -- creator of image+  | TG_HOSTCOMPUTER             -- machine where created+  | TG_PREDICTOR                -- prediction scheme w/ LZW+  | TG_WHITEPOINT               -- image white point   | TG_PRIMARYCHROMATICITIES    -- primary chromaticities-  | TG_COLORMAP 		-- RGB map for pallette image-  | TG_BADFAXLINES		-- lines w/ wrong pixel count-  | TG_CLEANFAXDATA		-- regenerated line info+  | TG_COLORMAP                 -- RGB map for pallette image+  | TG_BADFAXLINES              -- lines w/ wrong pixel count+  | TG_CLEANFAXDATA             -- regenerated line info   | TG_CONSECUTIVEBADFAXLINES   -- max consecutive bad lines   | TG_MATTEING                 -- alpha channel is present  deriving (Eq, Show)@@ -338,7 +339,7 @@  -- A few conversion procedures u32_to_float :: Word32 -> Double-u32_to_float _x = 		-- unsigned 32-bit int -> IEEE float+u32_to_float _x =               -- unsigned 32-bit int -> IEEE float   error "u32->float is not yet implemented"  u32_to_s32 :: Word32 -> Int32   -- unsigned 32-bit int -> signed 32 bit@@ -370,7 +371,7 @@   next_dict <- endianRead4 e   when (next_dict > 0) $       note ["The TIFF file contains several images, ",-	         "only the first one will be considered"]+            "only the first one will be considered"]   return dict  where   read_entry dictM = dictM >>=@@ -384,14 +385,14 @@       -- in its lower-numbered bytes, regardless of the big/little endian       -- order! -     note ["TIFFEntry: tag ",show . int_to_tag . fromIntegral $ tag, -	   " type ", show typ, " count ", show count]+     note ["TIFFEntry: tag ",show . int_to_tag . fromIntegral $ tag,+           " type ", show typ, " count ", show count]      enum_m <- maybe (return Nothing)                      (\t -> read_value t e (fromIntegral count)) typ      case enum_m of       Just enum ->-       return . Just $ IM.insert (fromIntegral tag) -		                 (TIFFDE (fromIntegral count) enum) dict+       return . Just $ IM.insert (fromIntegral tag)+                                 (TIFFDE (fromIntegral count) enum) dict       _ -> return (Just dict)      ) @@ -402,7 +403,7 @@       throwErr . Err $ "Bad type of entry: " ++ show typ       return Nothing -  read_value :: MonadIO m => TIFF_TYPE -> Endian -> Int -> +  read_value :: MonadIO m => TIFF_TYPE -> Endian -> Int ->                 IterateeG [] Word8 m (Maybe TIFFDE_ENUM)    read_value typ e' 0 = do@@ -410,24 +411,24 @@     throwErr . Err $ "Zero count in the entry of type: " ++ show typ     return Nothing -            		-- Read an ascii string from the offset in the-			-- dictionary. The last byte of-            		-- an ascii string is always zero, which is-            		-- included in 'count' but we don't need to read it+  -- Read an ascii string from the offset in the+  -- dictionary. The last byte of+  -- an ascii string is always zero, which is+  -- included in 'count' but we don't need to read it   read_value TT_ascii e' count | count > 4 = do -- val-offset is offset       offset <- endianRead4 e'       return . Just . TEN_CHAR $ \iter_char -> return $ do             Iter.seek (fromIntegral offset)-            let iter = convStream -                         (checkErr Iter.head >>= return . either (const Nothing) (Just . (:[]) . chr . fromIntegral))+            let iter = convStream+                         (liftM (either (const Nothing) (Just . (:[]) . chr . fromIntegral)) (checkErr Iter.head))                          iter_char             Iter.joinI $ Iter.joinI $ Iter.takeR (pred count) iter -			-- Read the string of 0 to 3 characters long-                        -- The zero terminator is included in count, but-			-- we don't need to read it-  read_value TT_ascii _e count = do	-- count is within 1..4-    let len = pred count		-- string length+  -- Read the string of 0 to 3 characters long+  -- The zero terminator is included in count, but+  -- we don't need to read it+  read_value TT_ascii _e count = do     -- count is within 1..4+    let len = pred count                -- string length     let loop acc 0 = return . Just . reverse $ acc         loop acc n = Iter.head >>= (\v -> loop ((chr . fromIntegral $ v):acc)                                              (pred n))@@ -437,17 +438,17 @@       Just str' -> return . Just . TEN_CHAR $ immed_value str'       Nothing   -> return Nothing -			-- Read the array of signed or unsigned bytes+  -- Read the array of signed or unsigned bytes   read_value typ e' count | count > 4 && typ == TT_byte || typ == TT_sbyte = do       offset <- endianRead4 e'       return . Just . TEN_INT $ \iter_int -> return $ do             Iter.seek (fromIntegral offset)-            let iter = convStream -                         (checkErr Iter.head >>= return . either (const Nothing) (Just . (:[]) . conv_byte typ))+            let iter = convStream+                         (liftM (either (const Nothing) (Just . (:[]) . conv_byte typ)) (checkErr Iter.head))                          iter_int             Iter.joinI $ Iter.joinI $ Iter.takeR count iter -			-- Read the array of 1 to 4 bytes+  -- Read the array of 1 to 4 bytes   read_value typ _e count | typ == TT_byte || typ == TT_sbyte = do     let loop acc 0 = return . Just . reverse $ acc         loop acc n = Iter.head >>= (\v -> loop (conv_byte typ v:acc)@@ -458,16 +459,16 @@       Just str' -> return . Just . TEN_INT $ immed_value str'       Nothing   -> return Nothing -			-- Read the array of Word8+  -- Read the array of Word8   read_value TT_undefined e' count | count > 4 = do     offset <- endianRead4 e'     return . Just . TEN_BYTE $ \iter -> return $ do           Iter.seek (fromIntegral offset)           Iter.joinI $ Iter.takeR count iter -			-- Read the array of Word8 of 1..4 elements,-			-- packed in the offset field-  read_value TT_undefined _e count = do +  -- Read the array of Word8 of 1..4 elements,+  -- packed in the offset field+  read_value TT_undefined _e count = do     let loop acc 0 = return . Just . reverse $ acc         loop acc n = Iter.head >>= (\v -> loop (v:acc) (pred n))     str <- loop [] count@@ -477,47 +478,45 @@       Nothing   -> return Nothing     --return . Just . TEN_BYTE $ immed_value str -			-- Read the array of short integers+  -- Read the array of short integers -			-- of 1 element: the offset field contains the value+  -- of 1 element: the offset field contains the value   read_value typ e' 1 | typ == TT_short || typ == TT_sshort = do     item <- endianRead2 e'-    Iter.drop 2				-- skip the padding+    Iter.drop 2                         -- skip the padding     return . Just . TEN_INT $ immed_value [conv_short typ item] -			-- of 2 elements: the offset field contains the value+  -- of 2 elements: the offset field contains the value   read_value typ e' 2 | typ == TT_short || typ == TT_sshort = do     i1 <- endianRead2 e'     i2 <- endianRead2 e'-    return . Just . TEN_INT $ -	     immed_value [conv_short typ i1, conv_short typ i2]+    return . Just . TEN_INT $+             immed_value [conv_short typ i1, conv_short typ i2] -			-- of n elements+  -- of n elements   read_value typ e' count | typ == TT_short || typ == TT_sshort = do     offset <- endianRead4 e'     return . Just . TEN_INT $ \iter_int -> return $ do           Iter.seek (fromIntegral offset)-          let iter = convStream -                         (checkErr (endianRead2 e') >>=-                           return . either (const Nothing) (Just . (:[]) . conv_short typ))+          let iter = convStream+                         (liftM (either (const Nothing) (Just . (:[]) . conv_short typ)) (checkErr (endianRead2 e')))                          iter_int           Iter.joinI $ Iter.joinI $ Iter.takeR (2*count) iter  -			-- Read the array of long integers-			-- of 1 element: the offset field contains the value+  -- Read the array of long integers+  -- of 1 element: the offset field contains the value   read_value typ e' 1 | typ == TT_long || typ == TT_slong = do     item <-  endianRead4 e'     return . Just . TEN_INT $ immed_value [conv_long typ item] -			-- of n elements+  -- of n elements   read_value typ e' count | typ == TT_long || typ == TT_slong = do       offset <- endianRead4 e'       return . Just . TEN_INT $ \iter_int -> return $ do             Iter.seek (fromIntegral offset)-            let iter = convStream -                         (checkErr (endianRead4 e') >>=-                           return . either (const Nothing) (Just . (:[]) . conv_long typ))+            let iter = convStream+                         (liftM (either (const Nothing) (Just . (:[]) . conv_long typ)) (checkErr (endianRead4 e')))                          iter_int             Iter.joinI $ Iter.joinI $ Iter.takeR (4*count) iter @@ -562,30 +561,30 @@       strip_offsets <- liftM (fromMaybe [0]) $                        dict_read_ints TG_STRIPOFFSETS dict       rps <- liftM (fromMaybe nrows) (dict_read_int TG_ROWSPERSTRIP dict)-      if ncols > 0 && nrows > 0 && rps > 0 +      if ncols > 0 && nrows > 0 && rps > 0         then return $ Just (ncols,nrows,rps,strip_offsets)         else return Nothing-	   +    dict_assert tag v = do       vfound <- dict_read_int tag dict       case vfound of         Just v' | v' == v -> return $ Just ()-	_ -> throwErr (Err (unwords ["dict_assert: tag:", show tag,-				"expected:", show v, "found:", show vfound])) >>+        _ -> throwErr (Err (unwords ["dict_assert: tag:", show tag,+                                     "expected:", show v, "found:", show vfound])) >>              return Nothing     proceed Nothing = throwErr $ Err "Can't handle this TIFF"     proceed (Just (ncols,nrows,rows_per_strip,strip_offsets)) = do      let strip_size = rows_per_strip * ncols-	 image_size = nrows * ncols+         image_size = nrows * ncols      note ["Processing the pixel matrix, ", show image_size, " bytes"]      let loop _pos [] iter'          = return iter'          loop pos (strip:strips) iter' = do-	   Iter.seek (fromIntegral strip)-	   let len = min strip_size (image_size - pos)-	   iter'' <- Iter.takeR (fromIntegral len) iter'-	   loop (pos+len) strips iter''+             Iter.seek (fromIntegral strip)+             let len = min strip_size (image_size - pos)+             iter'' <- Iter.takeR (fromIntegral len) iter'+             loop (pos+len) strips iter''      loop 0 strip_offsets iter  @@ -599,29 +598,29 @@    Just (e:_) -> return $ Just e    _          -> return Nothing -dict_read_ints :: Monad m => TIFF_TAG -> TIFFDict -> -		  IterateeG [] Word8 m (Maybe [Int])-dict_read_ints tag dict = +dict_read_ints :: Monad m => TIFF_TAG -> TIFFDict ->+                  IterateeG [] Word8 m (Maybe [Int])+dict_read_ints tag dict =   case IM.lookup (tag_to_int tag) dict of       Just (TIFFDE _ (TEN_INT enum)) -> do-	     e <- joinIM $ enum stream2list-	     return (Just e)+          e <- joinIM $ enum stream2list+          return (Just e)       _ -> return Nothing  dict_read_rat :: Monad m => TIFF_TAG -> TIFFDict ->                  IterateeG [] Word8 m (Maybe (Ratio Int))-dict_read_rat tag dict = +dict_read_rat tag dict =   case IM.lookup (tag_to_int tag) dict of       Just (TIFFDE 1 (TEN_RAT enum)) -> do-	     [e] <- joinIM $ enum stream2list-	     return (Just e)+          [e] <- joinIM $ enum stream2list+          return (Just e)       _ -> return Nothing  dict_read_string :: Monad m => TIFF_TAG -> TIFFDict ->                     IterateeG [] Word8 m (Maybe String)-dict_read_string tag dict = +dict_read_string tag dict =   case IM.lookup (tag_to_int tag) dict of       Just (TIFFDE _ (TEN_CHAR enum)) -> do-	     e <- joinIM $ enum stream2list-	     return (Just e)+          e <- joinIM $ enum stream2list+          return (Just e)       _ -> return Nothing
src/Data/Iteratee/Codecs/Wave.hs view
@@ -8,7 +8,7 @@  -} -module Data.Iteratee.Codecs.Wave (+module Data.Iteratee.Codecs.Wave {-# DEPRECATED "This will be moved to a separate package in the future" #-} (   WAVEDE (..),   WAVEDE_ENUM (..),   WAVE_CHUNK (..),@@ -323,4 +323,3 @@   where     divPos = fromIntegral (1 `shiftL` fromIntegral (bd - 1) :: Int) - 1     divNeg = fromIntegral (1 `shiftL` fromIntegral (bd - 1) :: Int)-
src/Data/Iteratee/IO.hs view
@@ -13,6 +13,8 @@   enumFdRandom, #endif   -- * Iteratee drivers+  --   These are FileDescriptor-based on POSIX systems, otherwise they are+  --   Handle-based.   fileDriver,   fileDriverRandom, )@@ -28,21 +30,25 @@ import Data.Iteratee.IO.Fd #endif +import Control.Monad.Trans+ -- If Posix is available, use the fileDriverRandomFd as fileDriverRandom.  Otherwise, use a handle-based variant. #if defined(USE_POSIX)  -- |Process a file using the given IterateeG.  This function wraps -- enumFd as a convenience.-fileDriver :: ReadableChunk s el => IterateeG s el IO a ->-              FilePath ->-              IO a+fileDriver :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriver = fileDriverFd  -- |Process a file using the given IterateeG.  This function wraps -- enumFdRandom as a convenience.-fileDriverRandom :: ReadableChunk s el => IterateeG s el IO a ->-                    FilePath ->-                    IO a+fileDriverRandom :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriverRandom = fileDriverRandomFd  #else@@ -52,16 +58,18 @@  -- |Process a file using the given IterateeG.  This function wraps -- enumHandle as a convenience.-fileDriver :: ReadableChunk s el => IterateeG s el IO a ->-              FilePath ->-              IO a+fileDriver :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriver = fileDriverHandle  -- |Process a file using the given IterateeG.  This function wraps -- enumFdHandle as a convenience.-fileDriverRandom :: ReadableChunk s el => IterateeG s el IO a ->-                    FilePath ->-                    IO a+fileDriverRandom :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriverRandom = fileDriverRandomHandle  #endif
src/Data/Iteratee/IO/Base.hs view
@@ -16,9 +16,10 @@ import Data.Iteratee.IO.Windows #endif +-- Provide the FileOffset type, which is available in Posix modules+-- and maybe Windows #if defined(USE_POSIX) import Data.Iteratee.IO.Posix #else type FileOffset = Integer #endif-
src/Data/Iteratee/IO/Fd.hs view
@@ -24,13 +24,17 @@ import Data.Iteratee.Binary() import Data.Iteratee.IO.Base +import Control.Monad+import Control.Monad.Trans+ import Foreign.Ptr-import Foreign.Marshal.Alloc+import Foreign.ForeignPtr import Foreign.Storable  import System.IO (SeekMode(..))  import System.Posix hiding (FileOffset)+import GHC.Conc  -- ------------------------------------------------------------------------ -- Binary Random IO enumerators@@ -38,92 +42,104 @@ -- |The enumerator of a POSIX File Descriptor.  This version enumerates -- over the entire contents of a file, in order, unless stopped by -- the iteratee.  In particular, seeking is not supported.-enumFd :: forall a s el.(ReadableChunk s el) => Fd -> EnumeratorGM s el IO a-enumFd fd iter' = allocaBytes (fromIntegral buffer_size) $ loop iter'+enumFd :: forall s el m a.(ReadableChunk s el, MonadIO m) =>+  Fd ->+  EnumeratorGM s el m a+enumFd fd iter' =+  liftIO (mallocForeignPtrBytes (fromIntegral buffer_size)) >>= loop iter'   where-    buffer_size = fromIntegral $ 2048 - (mod 2048 $ sizeOf (undefined :: el))-    loop iter p = do-      n <- myfdRead fd (castPtr p) buffer_size-      case n of-        Left _errno -> enumErr "IO error" iter-        Right 0 -> return iter-        Right n' -> do-          s <- readFromPtr p (fromIntegral n')-          igv <- runIter iter (Chunk s)-          check p igv+    buffer_size = fromIntegral $ 4096 - mod 4096 (sizeOf (undefined :: el))+    loop iter fp = do+      s <- liftIO . withForeignPtr fp $ \p -> do+        liftIO $ GHC.Conc.threadWaitRead fd+        n <- myfdRead fd (castPtr p) buffer_size+        case n of+          Left _errno -> return $ Left "IO error"+          Right 0 -> return $ Right Nothing+          Right n' -> liftM (Right . Just) $ readFromPtr p (fromIntegral n')+      checkres fp iter s+    checkres fp iter = either (flip enumErr iter)+                              (maybe (return iter)+                                     (check fp <=< runIter iter . Chunk))     check _p (Done x _) = return . return $ x     check p  (Cont i Nothing) = loop i p     check _p (Cont _ (Just e)) = return $ throwErr e  -- |The enumerator of a POSIX File Descriptor: a variation of enumFd that -- supports RandomIO (seek requests)-enumFdRandom :: forall a s el.(ReadableChunk s el) => Fd -> EnumeratorGM s el IO a-enumFdRandom fd iter =- allocaBytes (fromIntegral buffer_size) (loop (0,0) iter)+enumFdRandom :: forall s el m a.(ReadableChunk s el, MonadIO m) =>+  Fd ->+  EnumeratorGM s el m a+enumFdRandom fd iter' =+ liftIO (mallocForeignPtrBytes (fromIntegral buffer_size)) >>= loop (0,0) iter'  where   -- this can be usefully varied.  Values between 512 and 4096 seem   -- to provide the best performance for most cases.-  buffer_size = fromIntegral $ 4096 - (mod 4096 $ sizeOf (undefined :: el))+  buffer_size = fromIntegral $ 4096 - mod 4096 (sizeOf (undefined :: el))   -- the first argument of loop is (off,len), describing which part-  -- of the file is currently in the buffer 'p'-{--  loop :: (ReadableChunk s el) =>-          (FileOffset,Int) ->-          IterateeG s el IO a -> -	  Ptr el ->-          IO (IterateeG s el IO a)--}+  -- of the file is currently in the buffer 'fp'+  loop :: (FileOffset,Int) ->+          IterateeG s el m a ->+          ForeignPtr el ->+          m (IterateeG s el m a)     -- Thanks to John Lato for the strictness annotation     -- Otherwise, the `off + fromIntegral len' below accumulates thunks-  loop (off,len) _iter' _p | off `seq` len `seq` False = undefined-  loop (off,len) iter' p = do-   n <- myfdRead fd (castPtr p) buffer_size-   case n of-    Left _errno -> enumErr "IO error" iter'-    Right 0 -> return iter'-    Right n' -> do-         s <- readFromPtr p (fromIntegral n')-         igv <- runIter iter' (Chunk s)-         check (off + fromIntegral len, fromIntegral n') p igv-  seekTo pos@(off, len) off' iter' p+  loop (off,len) _iter _fp | off `seq` len `seq` False = undefined+  loop (off,len) iter fp = do+    s <- liftIO . withForeignPtr fp $ \p -> do+      liftIO $ GHC.Conc.threadWaitRead fd+      n <- myfdRead fd (castPtr p) buffer_size+      case n of+        Left _errno -> return $ Left "IO error"+        Right 0 -> return $ Right Nothing+        Right n' -> liftM+          (Right . Just . (,) (off + fromIntegral len, fromIntegral n'))+          (readFromPtr p (fromIntegral n'))+    checkres fp iter s+  seekTo pos@(off, len) off' iter fp     | off <= off' && off' < off + fromIntegral len =   -- Seek within buffer     do     let local_off = fromIntegral $ off' - off-    s <- readFromPtr (p `plusPtr` local_off) (len - local_off)-    igv <- runIter iter' (Chunk s)-    check pos p igv-  seekTo _pos off iter' p = do                           -- Seek outside buffer-    off' <- myfdSeek fd AbsoluteSeek (fromIntegral off)+    s <- liftIO $ withForeignPtr fp $ \p ->+                    readFromPtr (p `plusPtr` local_off) (len - local_off)+    igv <- runIter iter (Chunk s)+    check pos fp igv+  seekTo _pos off iter fp = do                         -- Seek outside buffer+    off' <- liftIO $ myfdSeek fd AbsoluteSeek (fromIntegral off)     case off' of-      Left _errno -> enumErr "IO error" iter'-      Right off'' -> loop (off'',0) iter' p-  check _ _p (Done x _)                 = return . return $ x-  check o p  (Cont i Nothing)           = loop o i p-  check o p  (Cont i (Just (Seek off))) = seekTo o off i p-  check _ _p (Cont _ (Just e))          = return $ throwErr e+      Left _errno -> enumErr "IO error" iter+      Right off'' -> loop (off'',0) iter fp+  checkres fp iter = either+                       (flip enumErr iter)+                       (maybe (return iter) (uncurry $ runS fp iter))+  runS fp iter o s = runIter iter (Chunk s) >>= check o fp+  check _ _fp (Done x _)                 = return . return $ x+  check o fp  (Cont i Nothing)           = loop o i fp+  check o fp  (Cont i (Just (Seek off))) = seekTo o off i fp+  check _ _fp (Cont _ (Just e))          = return $ throwErr e  -- |Process a file using the given IterateeGM.  This function wraps -- enumFd as a convenience.-fileDriverFd :: ReadableChunk s el => IterateeG s el IO a ->-                FilePath ->-                IO a+fileDriverFd :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriverFd iter filepath = do-  fd <- openFd filepath ReadOnly Nothing defaultFileFlags+  fd <- liftIO $ openFd filepath ReadOnly Nothing defaultFileFlags   result <- enumFd fd iter >>= run-  closeFd fd+  liftIO $ closeFd fd   return result  -- |Process a file using the given IterateeGM.  This function wraps -- enumFdRandom as a convenience.-fileDriverRandomFd :: ReadableChunk s el =>-                      IterateeG s el IO a ->-                      FilePath ->-                      IO a+fileDriverRandomFd :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriverRandomFd iter filepath = do-  fd <- openFd filepath ReadOnly Nothing defaultFileFlags+  fd <- liftIO $ openFd filepath ReadOnly Nothing defaultFileFlags   result <- enumFdRandom fd iter >>= run-  closeFd fd+  liftIO $ closeFd fd   return result  #endif-
src/Data/Iteratee/IO/Handle.hs view
@@ -22,9 +22,11 @@  import Data.Int import Control.Exception.Extensible+import Control.Monad+import Control.Monad.Trans  import Foreign.Ptr-import Foreign.Marshal.Alloc+import Foreign.ForeignPtr import Foreign.Storable  import System.IO@@ -36,95 +38,101 @@ -- |The enumerator of a file Handle.  This version enumerates -- over the entire contents of a file, in order, unless stopped by -- the iteratee.  In particular, seeking is not supported.-enumHandle :: forall a s el.(ReadableChunk s el) => Handle -> EnumeratorGM s el IO a-enumHandle h i = allocaBytes (fromIntegral buffer_size) $ loop i+enumHandle :: forall s el m a.(ReadableChunk s el, MonadIO m) =>+  Handle ->+  EnumeratorGM s el m a+enumHandle h i =+  liftIO (mallocForeignPtrBytes (fromIntegral buffer_size)) >>= loop i   where-    buffer_size = 4096 - (mod 4096 $ sizeOf (undefined :: el))-    loop iter p = do-      n <- (try $ hGetBuf h p buffer_size) :: IO (Either SomeException Int)-      case n of-        Left _   -> enumErr "IO error" iter-        Right 0  -> return iter-        Right n' -> do-          s <- readFromPtr p (fromIntegral n')-          igv <- runIter iter (Chunk s)-          check p igv+    buffer_size = 4096 - mod 4096 (sizeOf (undefined :: el))+    loop iter fp = do+      s <- liftIO . withForeignPtr fp $ \p -> do+        n <- try $ hGetBuf h p buffer_size :: IO (Either SomeException Int)+        case n of+          Left _  -> return $ Left "IO error"+          Right 0 -> return $ Right Nothing+          Right n' -> liftM (Right . Just) $ readFromPtr p (fromIntegral n')+      checkres fp iter s+    checkres fp iter = either (flip enumErr iter)+                              (maybe (return iter)+                                     (check fp <=< runIter iter . Chunk))     check _p (Done x _) = return . return $ x     check p  (Cont i' Nothing) = loop i' p     check _p (Cont _ (Just e)) = return $ throwErr e - -- |The enumerator of a Handle: a variation of enumHandle that -- supports RandomIO (seek requests)-enumHandleRandom :: forall a s el.(ReadableChunk s el) => Handle -> EnumeratorGM s el IO a-enumHandleRandom h iter =- allocaBytes (fromIntegral buffer_size) (loop (0,0) iter)+enumHandleRandom :: forall s el m a.(ReadableChunk s el, MonadIO m) =>+  Handle ->+  EnumeratorGM s el m a+enumHandleRandom h i =+ liftIO (mallocForeignPtrBytes (fromIntegral buffer_size)) >>= loop (0,0) i  where-  -- this can be usefully varied.  Values between 512 and 4096 seem-  -- to provide the best performance for most cases.-  buffer_size = 4096 - (mod 4096 $ sizeOf (undefined :: el))+  buffer_size = 4096 - mod 4096 (sizeOf (undefined :: el))   -- the first argument of loop is (off,len), describing which part-  -- of the file is currently in the buffer 'p'-{--  loop :: (ReadableChunk s el) =>-          (FileOffset,Int) ->-          IterateeG s el IO a -> -	  Ptr el ->-          IO (IterateeG s el IO a)--}-  -- Otherwise, the `off + fromIntegral len' below accumulates thunks-  loop (off,len) _iter' _p | off `seq` len `seq` False = undefined-  loop (off,len) iter' p = do-   n <- (try $ hGetBuf h p buffer_size) :: IO (Either SomeException Int)-   case n of-    Left _errno -> enumErr "IO error" iter-    Right 0 -> return iter'-    Right n' -> do-         s <- readFromPtr p (fromIntegral n')-         igv <- runIter iter' (Chunk s)-	 check (off + fromIntegral len,fromIntegral n') p igv-  seekTo pos@(off, len) off' iter' p-    | off <= off' && off' < off + fromIntegral len =	-- Seek within buffer+  -- of the file is currently in the buffer 'fp'+  loop :: (FileOffset,Int) ->+          IterateeG s el m a ->+          ForeignPtr el ->+          m (IterateeG s el m a)+  -- strictify `off', else the `off + fromIntegral len' accumulates thunks+  loop (off,len) _iter _p | off `seq` len `seq` False = undefined+  loop (off,len) iter fp = do+    s <- liftIO . withForeignPtr fp $ \p -> do+      n <- try $ hGetBuf h p buffer_size :: IO (Either SomeException Int)+      case n of+        Left _errno -> return $ Left "IO error"+        Right 0 -> return $ Right Nothing+        Right n' -> liftM+          (Right . Just . (,) (off + fromIntegral len, fromIntegral n'))+          (readFromPtr p (fromIntegral n'))+    checkres fp iter s+  seekTo pos@(off, len) off' iter fp+    | off <= off' && off' < off + fromIntegral len =    -- Seek within buffer     do     let local_off = fromIntegral $ off' - off-    s <- readFromPtr (p `plusPtr` local_off) (len - local_off)-    igv <- runIter iter' (Chunk s)-    check pos p igv-  seekTo _pos off iter' p = do                          -- Seek outside buffer-   off' <- (try $ hSeek h AbsoluteSeek-            (fromIntegral off)) :: IO (Either SomeException ())+    s <- liftIO $ withForeignPtr fp $ \p ->+                    readFromPtr (p `plusPtr` local_off) (len - local_off)+    igv <- runIter iter (Chunk s)+    check pos fp igv+  seekTo _pos off iter fp = do                          -- Seek outside buffer+   off' <- liftIO (try $ hSeek h AbsoluteSeek+            (fromIntegral off) :: IO (Either SomeException ()))    case off' of-    Left _errno -> enumErr "IO error" iter'-    Right _     -> loop (off,0) iter' p-  check _ _ (Done x _)                 = return . return $ x-  check o p (Cont i Nothing)           = loop o i p-  check o p (Cont i (Just (Seek off))) = seekTo o off i p-  check _ _ (Cont _ (Just e))          = return $ throwErr e+    Left _errno -> enumErr "IO error" iter+    Right _     -> loop (off,0) iter fp+  checkres fp iter = either+                       (flip enumErr iter)+                       (maybe (return iter) (uncurry $ runS fp iter))+  runS fp iter o s = runIter iter (Chunk s) >>= check o fp+  check _ _ (Done x _)                   = return . return $ x+  check o fp (Cont i' Nothing)           = loop o i' fp+  check o fp (Cont i' (Just (Seek off))) = seekTo o off i' fp+  check _ _ (Cont _ (Just e))            = return $ throwErr e  -- ---------------------------------------------- -- File Driver wrapper functions.  -- |Process a file using the given IterateeGM.  This function wraps -- enumHandle as a convenience.-fileDriverHandle :: ReadableChunk s el =>-                    IterateeG s el IO a ->-                    FilePath ->-                    IO a+fileDriverHandle :: (MonadIO m, ReadableChunk s el) =>+  IterateeG s el m a ->+  FilePath ->+  m a fileDriverHandle iter filepath = do-  h <- openBinaryFile filepath ReadMode+  h <- liftIO $ openBinaryFile filepath ReadMode   result <- enumHandle h iter >>= run-  hClose h+  liftIO $ hClose h   return result  -- |Process a file using the given IterateeGM.  This function wraps -- enumHandleRandom as a convenience.-fileDriverRandomHandle :: ReadableChunk s el =>-                          IterateeG s el IO a ->+fileDriverRandomHandle :: (MonadIO m, ReadableChunk s el) =>+                          IterateeG s el m a ->                           FilePath ->-                          IO a+                          m a fileDriverRandomHandle iter filepath = do-  h <- openBinaryFile filepath ReadMode+  h <- liftIO $ openBinaryFile filepath ReadMode   result <- enumHandleRandom h iter >>= run-  hClose h+  liftIO $ hClose h   return result-
src/Data/Iteratee/IO/Posix.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE CPP, ForeignFunctionInterface #-} --- Low-level IO operations +-- Low-level IO operations -- These operations are either missing from the GHC run-time library, -- or implemented suboptimally or heavy-handedly @@ -23,8 +23,8 @@ import System.Posix import System.IO (SeekMode(..)) import Control.Monad-import Data.Bits			-- for select-import Foreign.Marshal.Array		-- for select+import Data.Bits                        -- for select+import Foreign.Marshal.Array            -- for select  -- |Alas, GHC provides no function to read from Fd to an allocated buffer. -- The library function fdRead is not appropriate as it returns a string@@ -49,7 +49,7 @@   n' <- cLSeek fd off (mode2Int mode)   if n' == -1 then liftM Left getErrno      else return . Right  $ n'- where mode2Int :: SeekMode -> CInt	-- From GHC source+ where mode2Int :: SeekMode -> CInt     -- From GHC source        mode2Int AbsoluteSeek = 0        mode2Int RelativeSeek = 1        mode2Int SeekFromEnd  = 2@@ -58,7 +58,7 @@   :: CInt -> FileOffset -> CInt -> IO FileOffset  --- Darn! GHC doesn't provide the real select over several descriptors! +-- Darn! GHC doesn't provide the real select over several descriptors! -- We have to implement it ourselves  type FDSET = CUInt@@ -74,9 +74,9 @@     (nb,off) = quotRem (fromIntegral fd) (bitSize (undefined::FDSET))  fds2mfd :: [FDSET] -> [CInt]-fds2mfd fds = [fromIntegral (j+i*bitsize) | -	       (afds,i) <- zip fds [0..], j <- [0..bitsize],-	       testBit afds j]+fds2mfd fds = [fromIntegral (j+i*bitsize) |+               (afds,i) <- zip fds [0..], j <- [0..bitsize],+               testBit afds j]   where bitsize = bitSize (undefined::FDSET)  unFd :: Fd -> CInt@@ -86,16 +86,13 @@ -- Return the list of read-pending descriptors select'read'pending :: [Fd] -> IO (Either Errno [Fd]) select'read'pending mfd =-    withArray ([0,1]::[TIMEVAL]) ( -- holdover...-    \_timeout ->-      withArray fds (-       \readfs ->-         do-         rc <- c_select (fdmax+1) readfs nullPtr nullPtr nullPtr-         if rc == -1 then liftM Left getErrno-         -- because the wait was indefinite, rc must be positive!-            else peekArray (length fds) readfs >>=-                 return . Right . map Fd . fds2mfd))+    withArray ([0,1]::[TIMEVAL]) $ \_timeout ->+      withArray fds $ \readfs -> do+          rc <- c_select (fdmax+1) readfs nullPtr nullPtr nullPtr+          if rc == -1+            then liftM Left getErrno+            -- because the wait was indefinite, rc must be positive!+            else liftM (Right . map Fd . fds2mfd) (peekArray (length fds) readfs)   where     fds :: [FDSET]     fds  = foldr ormax [] (map (fd2fds . unFd) mfd)
src/Data/Iteratee/IO/Windows.hs view
@@ -11,4 +11,3 @@   #endif-
src/Data/Iteratee/WrappedByteString.hs view
@@ -14,7 +14,6 @@ import Data.Word import Data.Monoid import Foreign.Ptr-import Foreign.Marshal.Array import Control.Monad  -- |Wrap a Data.ByteString ByteString@@ -31,12 +30,12 @@ -- Thanks to Echo Nolan for indicating that the bytestring must copy -- data to a new ptr to preserve referential transparency. instance SC.ReadableChunk WrappedByteString Word8 where-  readFromPtr buf l = liftM WrapBS $! BBase.create l $ \newp ->-                    copyArray newp buf l -- must copy from the buffer+  readFromPtr buf l = let csl = (castPtr buf, l) in+                      liftM WrapBS $ BW.packCStringLen csl  instance SC.ReadableChunk WrappedByteString Char where-  readFromPtr buf l = liftM WrapBS $! BBase.create l $ \newp ->-                    copyArray newp (castPtr buf) l --must copy data from buffer+  readFromPtr buf l = let csl = (castPtr buf, l) in+                      liftM WrapBS $ BC.packCStringLen csl  instance LL.ListLike (WrappedByteString Word8) Word8 where   length        = BW.length . unWrap@@ -51,27 +50,22 @@   dropWhile p   = WrapBS . BW.dropWhile p . unWrap   fromList      = WrapBS . BW.pack   toList        = BW.unpack . unWrap+  rigidMap f    = WrapBS . BW.map f . unWrap  instance SC.StreamChunk WrappedByteString Word8 where   cMap          = bwmap  bwmap :: (SC.StreamChunk s' el') =>-         (Word8 -> el') ->-         WrappedByteString Word8 ->-         s' el'+  (Word8 -> el')+  -> WrappedByteString Word8+  -> s' el' bwmap f xs = step xs   where   step bs     | LL.null bs = mempty     | True     = f (LL.head bs) `LL.cons` step (LL.tail bs) --- a specialized version to use in the RULE-bwmap' :: (Word8 -> Word8) ->-          WrappedByteString Word8 ->-          WrappedByteString Word8-bwmap' f = WrapBS . BW.map f . unWrap--{-# RULES "bwmap/map" forall s (f :: Word8 -> Word8). bwmap f s = bwmap' f s #-}+-- Now the Char instance  instance Monoid (WrappedByteString Char) where     mempty = WrapBS BW.empty@@ -94,24 +88,17 @@   dropWhile p   = WrapBS . BC.dropWhile p . unWrap   fromList      = WrapBS . BC.pack   toList        = BC.unpack . unWrap+  rigidMap f    = WrapBS . BC.map f . unWrap  instance SC.StreamChunk WrappedByteString Char where   cMap          = bcmap  bcmap :: (SC.StreamChunk s' el') =>-         (Char -> el') ->-         WrappedByteString Char ->-         s' el'+  (Char -> el')+   -> WrappedByteString Char+   -> s' el' bcmap f xs = step xs   where   step bs     | LL.null bs = mempty     | True     = f (LL.head bs) `LL.cons` step (LL.tail bs)---- a specialized version to use in the RULE-bcmap' :: (Char -> Char) ->-          WrappedByteString Char ->-          WrappedByteString Char-bcmap' f = WrapBS . BC.map f . unWrap--{-# RULES "bcmap/map" forall s (f :: Char -> Char). bcmap f s = bcmap' f s #-}
tests/QCUtils.hs view
@@ -39,4 +39,3 @@               ,I.heads ns >> stream2list               ,I.peek >> stream2list               ]-
tests/testIteratee.hs view
@@ -30,7 +30,7 @@ type ST = StreamG [] Int  prop_eq str = str == str-  where types = (str :: ST)+  where types = str :: ST  prop_mempty = mempty == (Chunk [] :: StreamG [] Int) @@ -44,7 +44,7 @@   where types = (str :: ST, f :: Int -> Integer)  prop_mappend2 str = str `mappend` mempty == mempty `mappend` str-  where types = (str :: ST)+  where types = str :: ST   isChunk (Chunk _) = True@@ -159,7 +159,7 @@ prop_nullH xs = P.length xs > 0 ==>                 runner1 (enumPure1Chunk xs =<< enumPure1Chunk [] Iter.head)                 == runner1 (enumPure1Chunk xs Iter.head)-  where types = (xs :: [Int])+  where types = xs :: [Int] -- --------------------------------------------- -- Nested Iteratees @@ -200,27 +200,27 @@ prop_convstream2 xs = P.length xs > 0 ==>                       runner2 (enumPure1Chunk xs $ convStream convId Iter.head)                       == runner1 (enumPure1Chunk xs Iter.head)-  where types = (xs :: [Int])+  where types = xs :: [Int]  prop_convstream3 xs = P.length xs > 0 ==>                       runner2 (enumPure1Chunk xs $ convStream convId stream2list)                       == runner1 (enumPure1Chunk xs stream2list)-  where types = (xs :: [Int])+  where types = xs :: [Int]  prop_take xs n = n >= 0 ==>                  runner2 (enumPure1Chunk xs $ Iter.take n stream2list)                  == runner1 (enumPure1Chunk (P.take n xs) stream2list)-  where types = (xs :: [Int])+  where types = xs :: [Int]  prop_take2 xs n = n > 0 ==>                   runner2 (enumPure1Chunk xs $ Iter.take n peek)                   == runner1 (enumPure1Chunk (P.take n xs) peek)-  where types = (xs :: [Int])+  where types = xs :: [Int]  prop_takeR xs n = n >= 0 ==>                   runner2 (enumPure1Chunk xs $ Iter.take n stream2list)                   == runner2 (enumPure1Chunk xs $ takeR n stream2list)-  where types = (xs :: [Int])+  where types = xs :: [Int]  -- --------------------------------------------- -- Data.Iteratee.Char@@ -296,4 +296,3 @@ -- The entry point  main = defaultMain tests-