------------------------------------------------------------------------------- |-- Module : Data.Attoparsec.Split-- Copyright : 2010 Suite Solutions Ltd., Israel---- Maintainer : Yitz Gale <yitzg@suite-sol.com>-- Portability : portable---- Split a lazy bytestring into a lazy list of lazy bytestrings at-- boundaries defined by an attoparsec parser. The result of-- a matching parse is included at the beginning of the-- lazy bytestring which begins at that point.{- Copyright (c) 2010 Suite Solutions Ltd., Israel. All rights reserved.
For licensing information, see the BSD3-style license in the file
LICENSE that was originally distributed by the author together with
this file. -}moduleData.Attoparsec.Split(split)whereimportData.Attoparsec(Parser,Result(..),parse)importData.ByteString.Lazy.Internal(ByteString(..),chunk)importqualifiedData.ByteString.LazyasLazyimportqualifiedData.ByteStringasBimportqualifiedData.ByteStringasStrictimportData.Maybe(fromMaybe,isJust)-- The result of examining the next group of bytes in the input streamdataSplitResult=-- A match of the parser, ending the current lazy bytestringMatch!B.ByteString-- The result of the match, to be used as-- the prefix for the next component!ByteString-- The rest of the input after the match!Bool-- Did the match consume any input?|SplitChunk!B.ByteString-- A chunk of the current lazy bytestringderivingShowisChunk::SplitResult->BoolisChunk(SplitChunk_)=TrueisChunk_=FalseasChunk::SplitResult->B.ByteStringasChunk(SplitChunkc)=casChunk_=B.empty-- | Split a lazy bytestring at boundaries defined by an attoparsec parser.split::ParserStrict.ByteString->Lazy.ByteString->[Lazy.ByteString]splitbdry=firstSplit.splitOneTruebdrywherefirstSplit[]=[]firstSplitresult@(Match___:_)=continueresultfirstSplitresult=nextSplitB.emptyresultnextSplitpfxresult=chunkpfx(foldr(chunk.asChunk)Emptyresult):continue(dropWhileisChunkresult)continue(Matchpfxxsbump:_)=nextSplitpfx(splitOnebumpbdryxs)continue_=[]-- Split off the chunks of the first lazy bytestring from the input.-- If the previous parser match did not consume any input, pass the-- first byte through and only start looking for further parser matches-- at the second byte.-- A Match element will only occur as the last element of the result list.-- If the last element is not a Match, end of input was reached.splitOne::Bool->(ParserB.ByteString)->ByteString->[SplitResult]splitOne__Empty=[]splitOnebumpbdry(Chunkxxs)|bump=go0Nothing.parsebdry$x|otherwise=go1Nothing.parsebdry$B.tailxwheregon_(Fail___)|n<B.lengthx=letn'=n+1ingon'Nothing.parsebdry$B.dropn'x|otherwise=SplitChunkx:splitOneTruebdryxsgonys(Donex'pfx)=[SplitChunk$B.takenx,Matchpfx(chunkx'$fromMaybexsys)$isJustys||B.lengthx'<B.lengthx-n]gonys(Partialk)=goPartialn(fromMaybexsys)kgoPartialn(Chunkyys)k=gon(Justys)$kygoPartialn__=gonNothing$FailB.empty[]""