-- |-- Module: Data.Enumerator.Binary-- Copyright: 2010-2011 John Millikin-- License: MIT---- Maintainer: jmillikin@gmail.com-- Portability: portable---- Byte-oriented alternatives to "Data.Enumerator.List". Note that the-- enumeratees in this module must unpack their inputs to work properly. If-- you do not need to handle leftover input on a byte-by-byte basis, the-- chunk-oriented versions will be much faster.---- This module is intended to be imported qualified:---- @-- import qualified Data.Enumerator.Binary as EB-- @---- Since: 0.4.5moduleData.Enumerator.Binary(-- * IOenumHandle,enumHandleRange,enumFile,enumFileRange,iterHandle-- * List analogues-- ** Folds,fold,foldM-- ** Maps,Data.Enumerator.Binary.map,Data.Enumerator.Binary.mapM,Data.Enumerator.Binary.mapM_,Data.Enumerator.Binary.concatMap,concatMapM-- ** Accumulating maps,mapAccum,mapAccumM,concatMapAccum,concatMapAccumM-- ** Infinite streams,Data.Enumerator.Binary.iterate,iterateM,Data.Enumerator.Binary.repeat,repeatM-- ** Bounded streams,Data.Enumerator.Binary.replicate,replicateM,generateM,unfold,unfoldM-- ** Dropping input,Data.Enumerator.Binary.drop,Data.Enumerator.Binary.dropWhile,Data.Enumerator.Binary.filter,filterM-- ** Consumers,Data.Enumerator.Binary.head,head_,Data.Enumerator.Binary.take,takeWhile,consume-- ** Zipping,zip,zip3,zip4,zip5,zip6,zip7,zipWith,zipWith3,zipWith4,zipWith5,zipWith6,zipWith7-- ** Unsorted,require,isolate,isolateWhile,splitWhen)whereimportPreludehiding(head,drop,takeWhile,mapM_,zip,zip3,zipWith,zipWith3)importqualifiedControl.ExceptionasExcimportqualifiedControl.MonadasCMimportControl.Monad(liftM)importControl.Monad.IO.Class(MonadIO)importControl.Monad.Trans.Class(lift)importqualifiedData.ByteStringasBimportqualifiedData.ByteString.LazyasBLimportData.Monoid(mappend)importData.Word(Word8)importqualifiedSystem.IOasIOimportSystem.IO.Error(isEOFError)importData.Enumerator.InternalimportData.Enumerator(isEOF,throwError,tryIO)importqualifiedData.Enumerator.ListasEL-- | Consume the entire input stream with a strict left fold, one byte-- at a time.---- Since: 0.4.8fold::Monadm=>(b->Word8->b)->b->IterateeB.ByteStringmbfoldstep=EL.fold(B.foldl'step)-- | Consume the entire input stream with a strict monadic left fold, one-- byte at a time.---- Since: 0.4.8foldM::Monadm=>(b->Word8->mb)->b->IterateeB.ByteStringmbfoldMstep=EL.foldM(\bbytes->CM.foldMstepb(B.unpackbytes))-- | Enumerates a stream of bytes by repeatedly applying a function to-- some state.---- Similar to 'Data.Enumerator.Binary.iterate'.---- Since: 0.4.8unfold::Monadm=>(s->Maybe(Word8,s))->s->EnumeratorB.ByteStringmbunfoldf=checkContinue1$\loopsk->casefsofNothing->continuekJust(b,s')->k(Chunks[B.singletonb])>>==loops'-- | Enumerates a stream of bytes by repeatedly applying a computation to-- some state.---- Similar to 'iterateM'.---- Since: 0.4.8unfoldM::Monadm=>(s->m(Maybe(Word8,s)))->s->EnumeratorB.ByteStringmbunfoldMf=checkContinue1$\loopsk->dofs<-lift(fs)casefsofNothing->continuekJust(b,s')->k(Chunks[B.singletonb])>>==loops'-- | @'Data.Enumerator.Binary.map' f@ applies /f/ to each input byte and-- feeds the resulting outputs to the inner iteratee.---- Since: 0.4.8map::Monadm=>(Word8->Word8)->EnumerateeB.ByteStringB.ByteStringmbmapf=Data.Enumerator.Binary.concatMap(\x->B.singleton(fx))-- | @'Data.Enumerator.Binary.mapM' f@ applies /f/ to each input byte and-- feeds the resulting outputs to the inner iteratee.---- Since: 0.4.8mapM::Monadm=>(Word8->mWord8)->EnumerateeB.ByteStringB.ByteStringmbmapMf=Data.Enumerator.Binary.concatMapM(\x->liftMB.singleton(fx))-- | @'Data.Enumerator.Binary.mapM_' f@ applies /f/ to each input byte, and-- discards the results.---- Since: 0.4.11mapM_::Monadm=>(Word8->m())->IterateeB.ByteStringm()mapM_f=foldM(\_x->fx>>return())()-- | @'Data.Enumerator.Binary.concatMap' f@ applies /f/ to each input byte-- and feeds the resulting outputs to the inner iteratee.---- Since: 0.4.8concatMap::Monadm=>(Word8->B.ByteString)->EnumerateeB.ByteStringB.ByteStringmbconcatMapf=Data.Enumerator.Binary.concatMapM(return.f)-- | @'concatMapM' f@ applies /f/ to each input byte and feeds the-- resulting outputs to the inner iteratee.---- Since: 0.4.8concatMapM::Monadm=>(Word8->mB.ByteString)->EnumerateeB.ByteStringB.ByteStringmbconcatMapMf=checkDone(continue.step)wherestepkEOF=yield(Continuek)EOFstepk(Chunksxs)=loopk(BL.unpack(BL.fromChunksxs))loopk[]=continue(stepk)loopk(x:xs)=dofx<-lift(fx)k(Chunks[fx])>>==checkDoneEx(Chunks[B.packxs])(`loop`xs)-- | Similar to 'Data.Enumerator.Binary.concatMap', but with a stateful step-- function.---- Since: 0.4.11concatMapAccum::Monadm=>(s->Word8->(s,B.ByteString))->s->EnumerateeB.ByteStringB.ByteStringmbconcatMapAccumfs0=checkDone(continue.steps0)wherestep_kEOF=yield(Continuek)EOFstepsk(Chunksxs)=loopskxsloopsk[]=continue(stepsk)loopsk(x:xs)=caseB.unconsxofNothing->loopskxsJust(b,x')->casefsbof(s',ai)->k(Chunks[ai])>>==checkDoneEx(Chunks(x':xs))(\k'->loops'k'(x':xs))-- | Similar to 'concatMapM', but with a stateful step function.---- Since: 0.4.11concatMapAccumM::Monadm=>(s->Word8->m(s,B.ByteString))->s->EnumerateeB.ByteStringB.ByteStringmbconcatMapAccumMfs0=checkDone(continue.steps0)wherestep_kEOF=yield(Continuek)EOFstepsk(Chunksxs)=loopskxsloopsk[]=continue(stepsk)loopsk(x:xs)=caseB.unconsxofNothing->loopskxsJust(b,x')->do(s',ai)<-lift(fsb)k(Chunks[ai])>>==checkDoneEx(Chunks(x':xs))(\k'->loops'k'(x':xs))-- | Similar to 'Data.Enumerator.Binary.map', but with a stateful step-- function.---- Since: 0.4.9mapAccum::Monadm=>(s->Word8->(s,Word8))->s->EnumerateeB.ByteStringB.ByteStringmbmapAccumf=concatMapAccum(\sw->casefswof(s',w')->(s',B.singletonw'))-- | Similar to 'Data.Enumerator.Binary.mapM', but with a stateful step-- function.---- Since: 0.4.9mapAccumM::Monadm=>(s->Word8->m(s,Word8))->s->EnumerateeB.ByteStringB.ByteStringmbmapAccumMf=concatMapAccumM(\sw->do(s',w')<-fswreturn(s',B.singletonw'))-- | @'Data.Enumerator.Binary.iterate' f x@ enumerates an infinite stream of-- repeated applications of /f/ to /x/.---- Analogous to 'Prelude.iterate'.---- Since: 0.4.8iterate::Monadm=>(Word8->Word8)->Word8->EnumeratorB.ByteStringmbiteratef=checkContinue1$\loopsk->k(Chunks[B.singletons])>>==loop(fs)-- | Similar to 'Data.Enumerator.Binary.iterate', except the iteration-- function is monadic.---- Since: 0.4.8iterateM::Monadm=>(Word8->mWord8)->Word8->EnumeratorB.ByteStringmbiterateMfbase=worker(returnbase)whereworker=checkContinue1$\loopm_bytek->dobyte<-liftm_bytek(Chunks[B.singletonbyte])>>==loop(fbyte)-- | Enumerates an infinite stream of a single byte.---- Analogous to 'Prelude.repeat'.---- Since: 0.4.8repeat::Monadm=>Word8->EnumeratorB.ByteStringmbrepeatbyte=EL.repeat(B.singletonbyte)-- | Enumerates an infinite stream of byte. Each byte is computed by the-- underlying monad.---- Since: 0.4.8repeatM::Monadm=>mWord8->EnumeratorB.ByteStringmbrepeatMnext=EL.repeatM(liftMB.singletonnext)-- | @'Data.Enumerator.Binary.replicate' n x@ enumerates a stream containing-- /n/ copies of /x/.---- Since: 0.4.8replicate::Monadm=>Integer->Word8->EnumeratorB.ByteStringmbreplicatenbyte=EL.replicaten(B.singletonbyte)-- | @'replicateM' n m_x@ enumerates a stream of /n/ bytes, with each byte-- computed by /m_x/.---- Since: 0.4.8replicateM::Monadm=>Integer->mWord8->EnumeratorB.ByteStringmbreplicateMnnext=EL.replicateMn(liftMB.singletonnext)-- | Like 'repeatM', except the computation may terminate the stream by-- returning 'Nothing'.---- Since: 0.4.8generateM::Monadm=>m(MaybeWord8)->EnumeratorB.ByteStringmbgenerateMnext=EL.generateM(liftM(liftMB.singleton)next)-- | Applies a predicate to the stream. The inner iteratee only receives-- characters for which the predicate is @True@.---- Since: 0.4.8filter::Monadm=>(Word8->Bool)->EnumerateeB.ByteStringB.ByteStringmbfilterp=Data.Enumerator.Binary.concatMap(\x->B.pack[x|px])-- | Applies a monadic predicate to the stream. The inner iteratee only-- receives bytes for which the predicate returns @True@.---- Since: 0.4.8filterM::Monadm=>(Word8->mBool)->EnumerateeB.ByteStringB.ByteStringmbfilterMp=Data.Enumerator.Binary.concatMapM(\x->liftMB.pack(CM.filterMp[x]))-- | @'Data.Enumerator.Binary.take' n@ extracts the next /n/ bytes from the-- stream, as a lazy-- ByteString.---- Since: 0.4.5take::Monadm=>Integer->IterateeB.ByteStringmBL.ByteStringtaken|n<=0=returnBL.emptytaken=continue(loopidn)whereloopaccn'(Chunksxs)=iterwherelazy=BL.fromChunksxslen=toInteger(BL.lengthlazy)iter=iflen<n'thencontinue(loop(acc.BL.appendlazy)(n'-len))elselet(xs',extra)=BL.splitAt(fromIntegern')lazyinyield(accxs')(toChunksextra)loopacc_EOF=yield(accBL.empty)EOF-- | @'takeWhile' p@ extracts input from the stream until the first byte which-- does not match the predicate.---- Since: 0.4.5takeWhile::Monadm=>(Word8->Bool)->IterateeB.ByteStringmBL.ByteStringtakeWhilep=continue(loopid)whereloopacc(Chunks[])=continue(loopacc)loopacc(Chunksxs)=iterwherelazy=BL.fromChunksxs(xs',extra)=BL.spanplazyiter=ifBL.nullextrathencontinue(loop(acc.BL.appendlazy))elseyield(accxs')(toChunksextra)loopaccEOF=yield(accBL.empty)EOF-- | @'consume' = 'takeWhile' (const True)@---- Since: 0.4.5consume::Monadm=>IterateeB.ByteStringmBL.ByteStringconsume=continue(loopid)whereloopacc(Chunks[])=continue(loopacc)loopacc(Chunksxs)=iterwherelazy=BL.fromChunksxsiter=continue(loop(acc.BL.appendlazy))loopaccEOF=yield(accBL.empty)EOF-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee.---- Analogous to 'Data.List.zip'.---- Since: 0.4.14zip::Monadm=>IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringm(b1,b2)zipi1i2=continuestepwherestep(Chunks[])=continuestepstepstream@(Chunks_)=doletenumStreams=casesofContinuek->kstreamYieldbextra->yieldb(mappendextrastream)Errorerr->throwErrorerrs1<-lift(runIteratee(enumStream==<<i1))s2<-lift(runIteratee(enumStream==<<i2))case(s1,s2)of(Continuek1,Continuek2)->zip(continuek1)(continuek2)(Yieldb1_,Continuek2)->zip(yieldb1(Chunks[]))(continuek2)(Continuek1,Yieldb2_)->zip(continuek1)(yieldb2(Chunks[]))(Yieldb1ex1,Yieldb2ex2)->yield(b1,b2)(shorterex1ex2)(Errorerr,_)->throwErrorerr(_,Errorerr)->throwErrorerrstepEOF=dob1<-enumEOF=<<lift(runIterateei1)b2<-enumEOF=<<lift(runIterateei2)return(b1,b2)shorterc1@(Chunksxs)c2@(Chunksys)=letxs'=B.concatxsys'=B.concatysinifB.lengthxs'<B.lengthys'thenc1elsec2shorter__=EOF-- | Pass input from a stream through three iteratees at once. Excess input is-- yielded if it was not consumed by any iteratee.---- Analogous to 'Data.List.zip3'.---- Since: 0.4.14zip3::Monadm=>IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringm(b1,b2,b3)zip3i1i2i3=do(b1,(b2,b3))<-zipi1(zipi2i3)return(b1,b2,b3){-# INLINE zip3 #-}-- | Pass input from a stream through four iteratees at once. Excess input is-- yielded if it was not consumed by any iteratee.---- Analogous to 'Data.List.zip4'.---- Since: 0.4.14zip4::Monadm=>IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringm(b1,b2,b3,b4)zip4i1i2i3i4=do(b1,(b2,b3,b4))<-zipi1(zip3i2i3i4)return(b1,b2,b3,b4){-# INLINE zip4 #-}-- | Pass input from a stream through five iteratees at once. Excess input is-- yielded if it was not consumed by any iteratee.---- Analogous to 'Data.List.zip5'.---- Since: 0.4.14zip5::Monadm=>IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmb5->IterateeB.ByteStringm(b1,b2,b3,b4,b5)zip5i1i2i3i4i5=do(b1,(b2,b3,b4,b5))<-zipi1(zip4i2i3i4i5)return(b1,b2,b3,b4,b5){-# INLINE zip5 #-}-- | Pass input from a stream through six iteratees at once. Excess input is-- yielded if it was not consumed by any iteratee.---- Analogous to 'Data.List.zip6'.---- Since: 0.4.14zip6::Monadm=>IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmb5->IterateeB.ByteStringmb6->IterateeB.ByteStringm(b1,b2,b3,b4,b5,b6)zip6i1i2i3i4i5i6=do(b1,(b2,b3,b4,b5,b6))<-zipi1(zip5i2i3i4i5i6)return(b1,b2,b3,b4,b5,b6){-# INLINE zip6 #-}-- | Pass input from a stream through seven iteratees at once. Excess input is-- yielded if it was not consumed by any iteratee.---- Analogous to 'Data.List.zip7'.---- Since: 0.4.14zip7::Monadm=>IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmb5->IterateeB.ByteStringmb6->IterateeB.ByteStringmb7->IterateeB.ByteStringm(b1,b2,b3,b4,b5,b6,b7)zip7i1i2i3i4i5i6i7=do(b1,(b2,b3,b4,b5,b6,b7))<-zipi1(zip6i2i3i4i5i6i7)return(b1,b2,b3,b4,b5,b6,b7){-# INLINE zip7 #-}-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee. Output from the-- iteratees is combined with a user-provided function.---- Analogous to 'Data.List.zipWith'.---- Since: 0.4.14zipWith::Monadm=>(b1->b2->c)->IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmczipWithfi1i2=do(b1,b2)<-zipi1i2return(fb1b2){-# INLINE zipWith #-}-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee. Output from the-- iteratees is combined with a user-provided function.---- Analogous to 'Data.List.zipWith3'.---- Since: 0.4.14zipWith3::Monadm=>(b1->b2->b3->c)->IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmczipWith3fi1i2i3=do(b1,b2,b3)<-zip3i1i2i3return(fb1b2b3){-# INLINE zipWith3 #-}-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee. Output from the-- iteratees is combined with a user-provided function.---- Analogous to 'Data.List.zipWith4'.---- Since: 0.4.14zipWith4::Monadm=>(b1->b2->b3->b4->c)->IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmczipWith4fi1i2i3i4=do(b1,b2,b3,b4)<-zip4i1i2i3i4return(fb1b2b3b4){-# INLINE zipWith4 #-}-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee. Output from the-- iteratees is combined with a user-provided function.---- Analogous to 'Data.List.zipWith5'.---- Since: 0.4.14zipWith5::Monadm=>(b1->b2->b3->b4->b5->c)->IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmb5->IterateeB.ByteStringmczipWith5fi1i2i3i4i5=do(b1,b2,b3,b4,b5)<-zip5i1i2i3i4i5return(fb1b2b3b4b5){-# INLINE zipWith5 #-}-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee. Output from the-- iteratees is combined with a user-provided function.---- Analogous to 'Data.List.zipWith6'.---- Since: 0.4.14zipWith6::Monadm=>(b1->b2->b3->b4->b5->b6->c)->IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmb5->IterateeB.ByteStringmb6->IterateeB.ByteStringmczipWith6fi1i2i3i4i5i6=do(b1,b2,b3,b4,b5,b6)<-zip6i1i2i3i4i5i6return(fb1b2b3b4b5b6){-# INLINE zipWith6 #-}-- | Pass input from a stream through two iteratees at once. Excess input is-- yielded if it was not consumed by either iteratee. Output from the-- iteratees is combined with a user-provided function.---- Analogous to 'Data.List.zipWith7'.---- Since: 0.4.14zipWith7::Monadm=>(b1->b2->b3->b4->b5->b6->b7->c)->IterateeB.ByteStringmb1->IterateeB.ByteStringmb2->IterateeB.ByteStringmb3->IterateeB.ByteStringmb4->IterateeB.ByteStringmb5->IterateeB.ByteStringmb6->IterateeB.ByteStringmb7->IterateeB.ByteStringmczipWith7fi1i2i3i4i5i6i7=do(b1,b2,b3,b4,b5,b6,b7)<-zip7i1i2i3i4i5i6i7return(fb1b2b3b4b5b6b7){-# INLINE zipWith7 #-}-- | Get the next byte from the stream, or 'Nothing' if the stream has-- ended.---- Since: 0.4.5head::Monadm=>IterateeB.ByteStringm(MaybeWord8)head=continueloopwhereloop(Chunksxs)=caseBL.uncons(BL.fromChunksxs)ofJust(char,extra)->yield(Justchar)(toChunksextra)Nothing->headloopEOF=yieldNothingEOF-- | Get the next element from the stream, or raise an error if the stream-- has ended.---- Since: 0.4.14head_::Monadm=>IterateeB.ByteStringmWord8head_=head>>=\x->casexofJustx'->returnx'Nothing->throwError(Exc.ErrorCall"head_: stream has ended")-- | @'drop' n@ ignores /n/ bytes of input from the stream.---- Since: 0.4.5drop::Monadm=>Integer->IterateeB.ByteStringm()dropn|n<=0=return()dropn=continue(loopn)whereloopn'(Chunksxs)=iterwherelazy=BL.fromChunksxslen=toInteger(BL.lengthlazy)iter=iflen<n'thendrop(n'-len)elseyield()(toChunks(BL.drop(fromIntegern')lazy))loop_EOF=yield()EOF-- | @'Data.Enumerator.Binary.dropWhile' p@ ignores input from the stream-- until the first byte which does not match the predicate.---- Since: 0.4.5dropWhile::Monadm=>(Word8->Bool)->IterateeB.ByteStringm()dropWhilep=continueloopwhereloop(Chunksxs)=iterwherelazy=BL.dropWhilep(BL.fromChunksxs)iter=ifBL.nulllazythencontinueloopelseyield()(toChunkslazy)loopEOF=yield()EOF-- | @'require' n@ buffers input until at least /n/ bytes are available, or-- throws an error if the stream ends early.---- Since: 0.4.5require::Monadm=>Integer->IterateeB.ByteStringm()requiren|n<=0=return()requiren=continue(loopidn)whereloopaccn'(Chunksxs)=iterwherelazy=BL.fromChunksxslen=toInteger(BL.lengthlazy)iter=iflen<n'thencontinue(loop(acc.BL.appendlazy)(n'-len))elseyield()(toChunks(acclazy))loop__EOF=throwError(Exc.ErrorCall"require: Unexpected EOF")-- | @'isolate' n@ reads at most /n/ bytes from the stream, and passes them-- to its iteratee. If the iteratee finishes early, bytes continue to be-- consumed from the outer stream until /n/ have been consumed.---- Since: 0.4.5isolate::Monadm=>Integer->EnumerateeB.ByteStringB.ByteStringmbisolatenstep|n<=0=returnstepisolaten(Continuek)=continueloopwhereloop(Chunks[])=continuelooploop(Chunksxs)=iterwherelazy=BL.fromChunksxslen=toInteger(BL.lengthlazy)iter=iflen<=nthenk(Chunksxs)>>==isolate(n-len)elselet(s1,s2)=BL.splitAt(fromIntegern)lazyink(toChunkss1)>>==(`yield`toChunkss2)loopEOF=kEOF>>==(`yield`EOF)isolatenstep=dropn>>returnstep-- | @'isolateWhile' p@ reads bytes from the stream until /p/ is false, and-- passes them to its iteratee. If the iteratee finishes early, bytes-- continue to be consumed from the outer stream until /p/ is false.---- Since: 0.4.16isolateWhile::Monadm=>(Word8->Bool)->EnumerateeB.ByteStringB.ByteStringmbisolateWhilep(Continuek)=continueloopwhereloop(Chunks[])=continuelooploop(Chunksxs)=iterwherelazy=BL.fromChunksxs(s1,s2)=BL.spanplazyiter=ifBL.nulls2thenk(Chunksxs)>>==isolateWhilepelsek(toChunkss1)>>==(`yield`toChunkss2)loopEOF=kEOF>>==(`yield`EOF)isolateWhilepstep=Data.Enumerator.Binary.dropWhilep>>returnstep-- | Split on bytes satisfying a given predicate.---- Since: 0.4.8splitWhen::Monadm=>(Word8->Bool)->EnumerateeB.ByteStringB.ByteStringmbsplitWhenp=loopwhereloop=checkDonestepstepk=isEOF>>=\eof->ifeofthenyield(Continuek)EOFelsedolazy<-takeWhile(not.p)letbytes=B.concat(BL.toChunkslazy)eof<-isEOFdrop1ifBL.nulllazy&&eofthenyield(Continuek)EOFelsek(Chunks[bytes])>>==loop-- | Read bytes (in chunks of the given buffer size) from the handle, and-- stream them to an 'Iteratee'. If an exception occurs during file IO,-- enumeration will stop and 'Error' will be returned. Exceptions from the-- iteratee are not caught.---- This enumerator blocks until at least one byte is available from the-- handle, and might read less than the maximum buffer size in some-- cases.---- The handle should be opened with no encoding, and in 'IO.ReadMode' or-- 'IO.ReadWriteMode'.---- Since: 0.4.5enumHandle::MonadIOm=>Integer-- ^ Buffer size->IO.Handle->EnumeratorB.ByteStringmbenumHandlebufferSizeh=checkContinue0$\loopk->doletintSize=fromIntegerbufferSizebytes<-tryIO(getByteshintSize)ifB.nullbytesthencontinuekelsek(Chunks[bytes])>>==loop-- | Read bytes (in chunks of the given buffer size) from the handle, and-- stream them to an 'Iteratee'. If an exception occurs during file IO,-- enumeration will stop and 'Error' will be returned. Exceptions from the-- iteratee are not caught.---- This enumerator blocks until at least one byte is available from the-- handle, and might read less than the maximum buffer size in some-- cases.---- The handle should be opened with no encoding, and in 'IO.ReadMode' or-- 'IO.ReadWriteMode'.---- If an offset is specified, the handle will be seeked to that offset-- before reading. If the handle cannot be seeked, an error will be-- thrown.---- If a maximum count is specified, the number of bytes read will not-- exceed that count.---- Since: 0.4.8enumHandleRange::MonadIOm=>Integer-- ^ Buffer size->MaybeInteger-- ^ Offset->MaybeInteger-- ^ Maximum count->IO.Handle->EnumeratorB.ByteStringmbenumHandleRangebufferSizeoffsetcounths=seek>>enumwhereseek=caseoffsetofNothing->return()Justoff->tryIO(IO.hSeekhIO.AbsoluteSeekoff)enum=casecountofJustn->enumRangensNothing->enumHandlebufferSizehsenumRange=checkContinue1$\loopnk->letrem=fromInteger(minbufferSizen)keepGoing=dobytes<-tryIO(getByteshrem)ifB.nullbytesthencontinuekelsefeedbytesfeedbs=k(Chunks[bs])>>==loop(n-toInteger(B.lengthbs))inifrem<=0thencontinuekelsekeepGoinggetBytes::IO.Handle->Int->IOB.ByteStringgetByteshn=dohasInput<-Exc.catch(IO.hWaitForInputh(-1))(\err->ifisEOFErrorerrthenreturnFalseelseExc.throwIOerr)ifhasInputthenB.hGetNonBlockinghnelsereturnB.empty-- | Opens a file path in binary mode, and passes the handle to-- 'enumHandle'. The file will be closed when enumeration finishes.---- Since: 0.4.5enumFile::FilePath->EnumeratorB.ByteStringIObenumFilepath=enumFileRangepathNothingNothing-- | Opens a file path in binary mode, and passes the handle to-- 'enumHandleRange'. The file will be closed when enumeration finishes.---- Since: 0.4.8enumFileRange::FilePath->MaybeInteger-- ^ Offset->MaybeInteger-- ^ Maximum count->EnumeratorB.ByteStringIObenumFileRangepathoffsetcountstep=doh<-tryIO(IO.openBinaryFilepathIO.ReadMode)letiter=enumHandleRange4096offsetcounthstepIteratee(Exc.finally(runIterateeiter)(IO.hCloseh))-- | Read bytes from a stream and write them to a handle. If an exception-- occurs during file IO, enumeration will stop and 'Error' will be-- returned.---- The handle should be opened with no encoding, and in 'IO.WriteMode' or-- 'IO.ReadWriteMode'.---- Since: 0.4.5iterHandle::MonadIOm=>IO.Handle->IterateeB.ByteStringm()iterHandleh=continuestepwherestepEOF=yield()EOFstep(Chunks[])=continuestepstep(Chunksbytes)=dotryIO(CM.mapM_(B.hPuth)bytes)continuesteptoChunks::BL.ByteString->StreamB.ByteStringtoChunks=Chunks.BL.toChunks