@@ -1,14 +1,15 @@
1−{-# LANGUAGE BangPatterns, OverloadedStrings, RecordWildCards #-}
1+{-# LANGUAGE BangPatterns, CPP, GADTs, OverloadedStrings, RankNTypes,
3-- Module : Data.Attoparsec.ByteString.Internal
4-- Module : Data.Attoparsec.ByteString.Internal
4−-- Copyright : Bryan O'Sullivan 2007-2014
5+-- Copyright : Bryan O'Sullivan 2007-2015
5-- License : BSD3
6-- License : BSD3
7-- Maintainer : bos@serpentine.com
8-- Maintainer : bos@serpentine.com
8-- Stability : experimental
9-- Stability : experimental
9-- Portability : unknown
10-- Portability : unknown
11−-- Simple, efficient parser combinators for 'B.ByteString' strings,
12+-- Simple, efficient parser combinators for 'ByteString' strings,
12-- loosely based on the Parsec library.
13-- loosely based on the Parsec library.
14module Data.Attoparsec.ByteString.Internal
15module Data.Attoparsec.ByteString.Internal
@@ -46,7 +47,7 @@ module Data.Attoparsec.ByteString.Internal
46 -- * Efficient string handling
47 -- * Efficient string handling
47 , skipWhile
48 , skipWhile
49− , stringTransform
50+ , stringCI
52 , runScanner
53 , runScanner
@@ -65,18 +66,25 @@ module Data.Attoparsec.ByteString.Internal
69+#if !MIN_VERSION_base(4,8,0)
68−import Control.Applicative ((<|>), (<$>))
70+import Control.Applicative ((<$>))
72+import Control.Applicative ((<|>))
69import Control.Monad (when)
73import Control.Monad (when)
74+import Data.Attoparsec.ByteString.Buffer (Buffer, buffer)
70import Data.Attoparsec.ByteString.FastSet (charClass, memberWord8)
75import Data.Attoparsec.ByteString.FastSet (charClass, memberWord8)
71−import Data.Attoparsec.ByteString.Fhthagn (inlinePerformIO)
72import Data.Attoparsec.Combinator ((<?>))
76import Data.Attoparsec.Combinator ((<?>))
77+import Data.Attoparsec.Internal
78+import Data.Attoparsec.Internal.Fhthagn (inlinePerformIO)
73import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
79import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
80+import Data.ByteString (ByteString)
81+import Data.List (intercalate)
74import Data.Word (Word8)
82import Data.Word (Word8)
75import Foreign.ForeignPtr (withForeignPtr)
83import Foreign.ForeignPtr (withForeignPtr)
76import Foreign.Ptr (castPtr, minusPtr, plusPtr)
84import Foreign.Ptr (castPtr, minusPtr, plusPtr)
77import Foreign.Storable (Storable(peek, sizeOf))
85import Foreign.Storable (Storable(peek, sizeOf))
78import Prelude hiding (getChar, succ, take, takeWhile)
86import Prelude hiding (getChar, succ, take, takeWhile)
79−import Data.ByteString (ByteString)
87+import qualified Data.Attoparsec.ByteString.Buffer as Buf
80import qualified Data.Attoparsec.Internal.Types as T
88import qualified Data.Attoparsec.Internal.Types as T
81import qualified Data.ByteString as B8
89import qualified Data.ByteString as B8
82import qualified Data.ByteString.Char8 as B
90import qualified Data.ByteString.Char8 as B
@@ -84,10 +92,10 @@ import qualified Data.ByteString.Internal as B
84import qualified Data.ByteString.Lazy as L
92import qualified Data.ByteString.Lazy as L
85import qualified Data.ByteString.Unsafe as B
93import qualified Data.ByteString.Unsafe as B
87−type Parser = T.Parser B.ByteString B.ByteString
95+type Parser = T.Parser ByteString
88−type Result = IResult B.ByteString B.ByteString
96+type Result = IResult ByteString
89−type Failure r = T.Failure B.ByteString B.ByteString r
97+type Failure r = T.Failure ByteString Buffer r
90−type Success a r = T.Success B.ByteString B.ByteString a r
98+type Success a r = T.Success ByteString Buffer a r
92-- | The parser @satisfy p@ succeeds for any byte for which the
100-- | The parser @satisfy p@ succeeds for any byte for which the
93-- predicate @p@ returns 'True'. Returns the byte that is actually
101-- predicate @p@ returns 'True'. Returns the byte that is actually
@@ -133,22 +141,15 @@ storable = hack undefined
133 hack :: Storable b => b -> Parser b
141 hack :: Storable b => b -> Parser b
134 hack dummy = do
142 hack dummy = do
135 (fp,o,_) <- B.toForeignPtr `fmap` take (sizeOf dummy)
143 (fp,o,_) <- B.toForeignPtr `fmap` take (sizeOf dummy)
136− return . B.inlinePerformIO . withForeignPtr fp $ \p ->
144+ return . inlinePerformIO . withForeignPtr fp $ \p ->
137 peek (castPtr $ p `plusPtr` o)
145 peek (castPtr $ p `plusPtr` o)
139−-- | Consume @n@ bytes of input, but succeed only if the predicate
147+-- | Consume exactly @n@ bytes of input.
141−takeWith :: Int -> (B.ByteString -> Bool) -> Parser B.ByteString
148+take :: Int -> Parser ByteString
142−takeWith n0 p = do
149+take n0 = do
143 let n = max n0 0
150 let n = max n0 0
144 s <- ensure n
151 s <- ensure n
146− then advance n >> return s
152+ advance n >> return s
147− else fail "takeWith"
149−-- | Consume exactly @n@ bytes of input.
150−take :: Int -> Parser B.ByteString
151−take n = takeWith n (const True)
152{-# INLINE take #-}
153{-# INLINE take #-}
154-- | @string s@ parses a sequence of bytes that identically match
155-- | @string s@ parses a sequence of bytes that identically match
@@ -164,16 +165,62 @@ take n = takeWith n (const True)
165-- The reason for its failure is that the first branch is a
166-- The reason for its failure is that the first branch is a
166-- partial match, and will consume the letters @\'f\'@ and @\'o\'@
167-- partial match, and will consume the letters @\'f\'@ and @\'o\'@
167−-- before failing. In Attoparsec, the above parser will /succeed/ on
168+-- before failing. In attoparsec, the above parser will /succeed/ on
168-- that input, because the failed first branch will consume nothing.
169-- that input, because the failed first branch will consume nothing.
169−string :: B.ByteString -> Parser B.ByteString
170+string :: ByteString -> Parser ByteString
170−string s = takeWith (B.length s) (==s)
171+string s = string_ (stringSuspended id) id s
171{-# INLINE string #-}
172{-# INLINE string #-}
173−stringTransform :: (B.ByteString -> B.ByteString) -> B.ByteString
174+-- ASCII-specific but fast, oh yes.
174− -> Parser B.ByteString
175+toLower :: Word8 -> Word8
175−stringTransform f s = takeWith (B.length s) ((==f s) . f)
176+toLower w | w >= 65 && w <= 90 = w + 32
176−{-# INLINE stringTransform #-}
177+ | otherwise = w
179+-- | Satisfy a literal string, ignoring case.
180+stringCI :: ByteString -> Parser ByteString
181+stringCI s = string_ (stringSuspended lower) lower s
182+ where lower = B8.map toLower
183+{-# INLINE stringCI #-}
185+string_ :: (forall r. ByteString -> ByteString -> Buffer -> Pos -> More
186+ -> Failure r -> Success ByteString r -> Result r)
187+ -> (ByteString -> ByteString)
188+ -> ByteString -> Parser ByteString
189+string_ suspended f s0 = T.Parser $ \t pos more lose succ ->
192+ in if lengthAtLeast pos n t
193+ then let t' = substring pos (Pos n) t
195+ then succ t (pos + Pos n) more t'
196+ else lose t pos more [] "string"
197+ else let t' = Buf.unsafeDrop (fromPos pos) t
198+ in if f t' `B.isPrefixOf` s
199+ then suspended s (B.drop (B.length t') s) t pos more lose succ
200+ else lose t pos more [] "string"
201+{-# INLINE string_ #-}
203+stringSuspended :: (ByteString -> ByteString)
204+ -> ByteString -> ByteString -> Buffer -> Pos -> More
206+ -> Success ByteString r
208+stringSuspended f s0 s t pos more lose succ =
209+ runParser (demandInput_ >>= go) t pos more lose succ
210+ where go s'0 = T.Parser $ \t' pos' more' lose' succ' ->
215+ then if B.unsafeTake m s' == s
216+ then let o = Pos (B.length s0)
217+ in succ' t' (pos' + o) more'
218+ (substring pos' o t')
219+ else lose' t' pos' more' [] "string"
220+ else if s' == B.unsafeTake n s
221+ then stringSuspended f s0 (B.unsafeDrop n s)
222+ t' pos' more' lose' succ'
223+ else lose' t' pos' more' [] "string"
178-- | Skip past input for as long as the predicate returns 'True'.
225-- | Skip past input for as long as the predicate returns 'True'.
179skipWhile :: (Word8 -> Bool) -> Parser ()
226skipWhile :: (Word8 -> Bool) -> Parser ()
@@ -181,11 +228,8 @@ skipWhile p = go
183 t <- B8.takeWhile p <$> get
230 t <- B8.takeWhile p <$> get
184− advance (B.length t)
231+ continue <- inputSpansChunks (B.length t)
185− eoc <- endOfChunk
232+ when continue go
189{-# INLINE skipWhile #-}
233{-# INLINE skipWhile #-}
191-- | Consume input as long as the predicate returns 'False'
235-- | Consume input as long as the predicate returns 'False'
@@ -198,7 +242,7 @@ skipWhile p = go
198-- combinators such as 'Control.Applicative.many', because such
242-- combinators such as 'Control.Applicative.many', because such
199-- parsers loop until a failure occurs. Careless use will thus result
243-- parsers loop until a failure occurs. Careless use will thus result
200-- in an infinite loop.
244-- in an infinite loop.
201−takeTill :: (Word8 -> Bool) -> Parser B.ByteString
245+takeTill :: (Word8 -> Bool) -> Parser ByteString
202takeTill p = takeWhile (not . p)
246takeTill p = takeWhile (not . p)
203{-# INLINE takeTill #-}
247{-# INLINE takeTill #-}
@@ -212,23 +256,27 @@ takeTill p = takeWhile (not . p)
212-- combinators such as 'Control.Applicative.many', because such
256-- combinators such as 'Control.Applicative.many', because such
213-- parsers loop until a failure occurs. Careless use will thus result
257-- parsers loop until a failure occurs. Careless use will thus result
214-- in an infinite loop.
258-- in an infinite loop.
215−takeWhile :: (Word8 -> Bool) -> Parser B.ByteString
259+takeWhile :: (Word8 -> Bool) -> Parser ByteString
216−takeWhile p = (B.concat . reverse) `fmap` go []
260+takeWhile p = do
261+ s <- B8.takeWhile p <$> get
262+ continue <- inputSpansChunks (B.length s)
264+ then takeWhileAcc p [s]
266+{-# INLINE takeWhile #-}
268+takeWhileAcc :: (Word8 -> Bool) -> [ByteString] -> Parser ByteString
218 go acc = do
271 go acc = do
219 s <- B8.takeWhile p <$> get
272 s <- B8.takeWhile p <$> get
220− advance (B.length s)
273+ continue <- inputSpansChunks (B.length s)
221− eoc <- endOfChunk
274+ if continue
226− then go (s:acc)
275+ then go (s:acc)
227− else return (s:acc)
276+ else return $ concatReverse (s:acc)
228− else return (s:acc)
277+{-# INLINE takeWhileAcc #-}
229−{-# INLINE takeWhile #-}
231−takeRest :: Parser [B.ByteString]
279+takeRest :: Parser [ByteString]
232takeRest = go []
280takeRest = go []
234 go acc = do
282 go acc = do
@@ -241,7 +289,7 @@ takeRest = go []
241 else return (reverse acc)
289 else return (reverse acc)
243-- | Consume all remaining input and return it as a single string.
291-- | Consume all remaining input and return it as a single string.
244−takeByteString :: Parser B.ByteString
292+takeByteString :: Parser ByteString
245takeByteString = B.concat `fmap` takeRest
293takeByteString = B.concat `fmap` takeRest
247-- | Consume all remaining input and return it as a single string.
295-- | Consume all remaining input and return it as a single string.
@@ -250,7 +298,7 @@ takeLazyByteString = L.fromChunks `fmap` takeRest
251data T s = T {-# UNPACK #-} !Int s
299data T s = T {-# UNPACK #-} !Int s
253−scan_ :: (s -> [B.ByteString] -> Parser r) -> s -> (s -> Word8 -> Maybe s)
301+scan_ :: (s -> [ByteString] -> Parser r) -> s -> (s -> Word8 -> Maybe s)
254 -> Parser r
302 -> Parser r
255scan_ f s0 p = go [] s0
303scan_ f s0 p = go [] s0
@@ -271,14 +319,9 @@ scan_ f s0 p = go [] s0
271 bs <- get
319 bs <- get
272 let T i s' = inlinePerformIO $ scanner bs
320 let T i s' = inlinePerformIO $ scanner bs
273 !h = B.unsafeTake i bs
321 !h = B.unsafeTake i bs
274− advance i
322+ continue <- inputSpansChunks i
275− eoc <- endOfChunk
323+ if continue
280− then go (h:acc) s'
324+ then go (h:acc) s'
282 else f s' (h:acc)
325 else f s' (h:acc)
283{-# INLINE scan_ #-}
326{-# INLINE scan_ #-}
@@ -294,17 +337,14 @@ scan_ f s0 p = go [] s0
294-- combinators such as 'Control.Applicative.many', because such
337-- combinators such as 'Control.Applicative.many', because such
295-- parsers loop until a failure occurs. Careless use will thus result
338-- parsers loop until a failure occurs. Careless use will thus result
296-- in an infinite loop.
339-- in an infinite loop.
297−scan :: s -> (s -> Word8 -> Maybe s) -> Parser B.ByteString
340+scan :: s -> (s -> Word8 -> Maybe s) -> Parser ByteString
298−scan = scan_ $ \_ chunks ->
341+scan = scan_ $ \_ chunks -> return $! concatReverse chunks
301− xs -> return $! B.concat $ reverse xs
302{-# INLINE scan #-}
342{-# INLINE scan #-}
304-- | Like 'scan', but generalized to return the final state of the
344-- | Like 'scan', but generalized to return the final state of the
305-- scanner.
345-- scanner.
306−runScanner :: s -> (s -> Word8 -> Maybe s) -> Parser (B.ByteString, s)
346+runScanner :: s -> (s -> Word8 -> Maybe s) -> Parser (ByteString, s)
307−runScanner = scan_ $ \s xs -> return (B.concat (reverse xs), s)
347+runScanner = scan_ $ \s xs -> let !sx = concatReverse xs in return (sx, s)
308{-# INLINE runScanner #-}
348{-# INLINE runScanner #-}
310-- | Consume input as long as the predicate returns 'True', and return
350-- | Consume input as long as the predicate returns 'True', and return
@@ -313,7 +353,7 @@ runScanner = scan_ $ \s xs -> return (B.concat (reverse xs), s)
313-- This parser requires the predicate to succeed on at least one byte
353-- This parser requires the predicate to succeed on at least one byte
314-- of input: it will fail if the predicate never returns 'True' or if
354-- of input: it will fail if the predicate never returns 'True' or if
315-- there is no input left.
355-- there is no input left.
316−takeWhile1 :: (Word8 -> Bool) -> Parser B.ByteString
356+takeWhile1 :: (Word8 -> Bool) -> Parser ByteString
317takeWhile1 p = do
357takeWhile1 p = do
318 (`when` demandInput) =<< endOfChunk
358 (`when` demandInput) =<< endOfChunk
319 s <- B8.takeWhile p <$> get
359 s <- B8.takeWhile p <$> get
@@ -324,8 +364,9 @@ takeWhile1 p = do
324 advance len
364 advance len
325 eoc <- endOfChunk
365 eoc <- endOfChunk
327− then (s<>) `fmap` takeWhile p
367+ then takeWhileAcc p [s]
328 else return s
368 else return s
369+{-# INLINE takeWhile1 #-}
330-- | Match any byte in a set.
371-- | Match any byte in a set.
@@ -373,13 +414,13 @@ notWord8 c = satisfy (/= c) <?> "not " ++ show c
373peekWord8 :: Parser (Maybe Word8)
414peekWord8 :: Parser (Maybe Word8)
374peekWord8 = T.Parser $ \t pos@(Pos pos_) more _lose succ ->
415peekWord8 = T.Parser $ \t pos@(Pos pos_) more _lose succ ->
375 case () of
416 case () of
376− _| pos_ < B.length t ->
417+ _| pos_ < Buf.length t ->
377− let !w = B.unsafeIndex t pos_
418+ let !w = Buf.unsafeIndex t pos_
378 in succ t pos more (Just w)
419 in succ t pos more (Just w)
379 | more == Complete ->
420 | more == Complete ->
380 succ t pos more Nothing
421 succ t pos more Nothing
381 | otherwise ->
422 | otherwise ->
382− let succ' t' pos' more' = let !w = B.unsafeIndex t pos_
423+ let succ' t' pos' more' = let !w = Buf.unsafeIndex t' pos_
383 in succ t' pos' more' (Just w)
424 in succ t' pos' more' (Just w)
384 lose' t' pos' more' = succ t' pos' more' Nothing
425 lose' t' pos' more' = succ t' pos' more' Nothing
385 in prompt t pos more lose' succ'
426 in prompt t pos more lose' succ'
@@ -390,7 +431,7 @@ peekWord8 = T.Parser $ \t pos@(Pos pos_) more _lose succ ->
390peekWord8' :: Parser Word8
431peekWord8' :: Parser Word8
391peekWord8' = T.Parser $ \t pos more lose succ ->
432peekWord8' = T.Parser $ \t pos more lose succ ->
392 if lengthAtLeast pos 1 t
433 if lengthAtLeast pos 1 t
393− then succ t pos more (B.unsafeIndex t (fromPos pos))
434+ then succ t pos more (Buf.unsafeIndex t (fromPos pos))
394 else let succ' t' pos' more' bs' = succ t' pos' more' $! B.unsafeHead bs'
435 else let succ' t' pos' more' bs' = succ t' pos' more' $! B.unsafeHead bs'
395 in ensureSuspended 1 t pos more lose succ'
436 in ensureSuspended 1 t pos more lose succ'
396{-# INLINE peekWord8' #-}
437{-# INLINE peekWord8' #-}
@@ -402,43 +443,62 @@ endOfLine = (word8 10 >> return ()) <|> (string "\r\n" >> return ())
403-- | Terminal failure continuation.
444-- | Terminal failure continuation.
404failK :: Failure a
445failK :: Failure a
405−failK t (Pos pos) _more stack msg = Fail (B.unsafeDrop pos t) stack msg
446+failK t (Pos pos) _more stack msg = Fail (Buf.unsafeDrop pos t) stack msg
406{-# INLINE failK #-}
447{-# INLINE failK #-}
408-- | Terminal success continuation.
449-- | Terminal success continuation.
409successK :: Success a a
450successK :: Success a a
410−successK t (Pos pos) _more a = Done (B.unsafeDrop pos t) a
451+successK t (Pos pos) _more a = Done (Buf.unsafeDrop pos t) a
411{-# INLINE successK #-}
452{-# INLINE successK #-}
413-- | Run a parser.
454-- | Run a parser.
414−parse :: Parser a -> B.ByteString -> Result a
455+parse :: Parser a -> ByteString -> Result a
415−parse m s = T.runParser m s (Pos 0) Incomplete failK successK
456+parse m s = T.runParser m (buffer s) (Pos 0) Incomplete failK successK
416{-# INLINE parse #-}
457{-# INLINE parse #-}
418-- | Run a parser that cannot be resupplied via a 'Partial' result.
459-- | Run a parser that cannot be resupplied via a 'Partial' result.
461+-- This function does not force a parser to consume all of its input.
462+-- Instead, any residual input will be discarded. To force a parser
463+-- to consume all of its input, use something like this:
466+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')
419−parseOnly :: Parser a -> B.ByteString -> Either String a
468+parseOnly :: Parser a -> ByteString -> Either String a
420−parseOnly m s = case T.runParser m s (Pos 0) Complete failK successK of
469+parseOnly m s = case T.runParser m (buffer s) (Pos 0) Complete failK successK of
470+ Fail _ [] err -> Left err
421− Fail _ _ err -> Left err
471+ Fail _ ctxs err -> Left (intercalate " > " ctxs ++ ": " ++ err)
422− Done _ a -> Right a
472+ Done _ a -> Right a
423− _ -> error "parseOnly: impossible error!"
473+ _ -> error "parseOnly: impossible error!"
424{-# INLINE parseOnly #-}
474{-# INLINE parseOnly #-}
426get :: Parser ByteString
476get :: Parser ByteString
427get = T.Parser $ \t pos more _lose succ ->
477get = T.Parser $ \t pos more _lose succ ->
428− succ t pos more (B.unsafeDrop (fromPos pos) t)
478+ succ t pos more (Buf.unsafeDrop (fromPos pos) t)
429{-# INLINE get #-}
479{-# INLINE get #-}
431endOfChunk :: Parser Bool
481endOfChunk :: Parser Bool
432endOfChunk = T.Parser $ \t pos more _lose succ ->
482endOfChunk = T.Parser $ \t pos more _lose succ ->
433− succ t pos more (fromPos pos == B.length t)
483+ succ t pos more (fromPos pos == Buf.length t)
434{-# INLINE endOfChunk #-}
484{-# INLINE endOfChunk #-}
486+inputSpansChunks :: Int -> Parser Bool
487+inputSpansChunks i = T.Parser $ \t pos_ more _lose succ ->
488+ let pos = pos_ + Pos i
489+ in if fromPos pos < Buf.length t || more == Complete
490+ then succ t pos more False
491+ else let lose' t' pos' more' = succ t' pos' more' False
492+ succ' t' pos' more' = succ t' pos' more' True
493+ in prompt t pos more lose' succ'
494+{-# INLINE inputSpansChunks #-}
436advance :: Int -> Parser ()
496advance :: Int -> Parser ()
437advance n = T.Parser $ \t pos more _lose succ ->
497advance n = T.Parser $ \t pos more _lose succ ->
438 succ t (pos + Pos n) more ()
498 succ t (pos + Pos n) more ()
439{-# INLINE advance #-}
499{-# INLINE advance #-}
441−ensureSuspended :: Int -> ByteString -> Pos -> More
501+ensureSuspended :: Int -> Buffer -> Pos -> More
442 -> Failure r
502 -> Failure r
443 -> Success ByteString r
503 -> Success ByteString r
444 -> Result r
504 -> Result r
@@ -457,54 +517,8 @@ ensure n = T.Parser $ \t pos more lose succ ->
457 then succ t pos more (substring pos (Pos n) t)
517 then succ t pos more (substring pos (Pos n) t)
458 -- The uncommon case is kept out-of-line to reduce code size:
518 -- The uncommon case is kept out-of-line to reduce code size:
459 else ensureSuspended n t pos more lose succ
519 else ensureSuspended n t pos more lose succ
460−-- Non-recursive so the bounds check can be inlined:
461{-# INLINE ensure #-}
520{-# INLINE ensure #-}
463−-- | Ask for input. If we receive any, pass it to a success
464−-- continuation, otherwise to a failure continuation.
465−prompt :: ByteString -> Pos -> More
466− -> (ByteString -> Pos -> More -> IResult ByteString ByteString r)
467− -> (ByteString -> Pos -> More -> IResult ByteString ByteString r)
468− -> IResult ByteString ByteString r
469−prompt t pos _more lose succ = Partial $ \s ->
471− then lose t pos Complete
472− else succ (t <> s) pos Incomplete
474−-- | Immediately demand more input via a 'Partial' continuation
476−demandInput :: Parser ()
477−demandInput = T.Parser $ \t pos more lose succ ->
479− Complete -> lose t pos more [] "not enough input"
480− _ -> let lose' t' pos' more' = lose t' pos' more' [] "not enough input"
481− succ' t' pos' more' = succ t' pos' more' ()
482− in prompt t pos more lose' succ'
484−-- | This parser always succeeds. It returns 'True' if any input is
485−-- available either immediately or on demand, and 'False' if the end
486−-- of all input has been reached.
487−wantInput :: Parser Bool
488−wantInput = T.Parser $ \t pos more _lose succ ->
490− _ | lengthAtLeast pos 1 t -> succ t pos more True
491− | more == Complete -> succ t pos more False
492− | otherwise -> let lose' t' pos' more' = succ t' pos' more' False
493− succ' t' pos' more' = succ t' pos' more' True
494− in prompt t pos more lose' succ'
495−{-# INLINE wantInput #-}
497−-- | Match only if all input has been consumed.
498−endOfInput :: Parser ()
499−endOfInput = T.Parser $ \t pos more lose succ ->
501− _| lengthAtLeast pos 1 t -> lose t pos more [] "endOfInput"
502− | more == Complete -> succ t pos more ()
504− let lose' t' pos' more' _ctx _msg = succ t' pos' more' ()
505− succ' t' pos' more' _a = lose t' pos' more' [] "endOfInput"
506− in runParser demandInput t pos more lose' succ'
508-- | Return both the result of a parse and the portion of the input
522-- | Return both the result of a parse and the portion of the input
509-- that was consumed while it was being parsed.
523-- that was consumed while it was being parsed.
510match :: Parser a -> Parser (ByteString, a)
524match :: Parser a -> Parser (ByteString, a)
@@ -513,16 +527,10 @@ match p = T.Parser $ \t pos more lose succ ->
513 succ t' pos' more' (substring pos (pos'-pos) t', a)
527 succ t' pos' more' (substring pos (pos'-pos) t', a)
514 in runParser p t pos more lose succ'
528 in runParser p t pos more lose succ'
516−-- | Return an indication of whether the end of input has been
519−atEnd = not <$> wantInput
522−lengthAtLeast :: Pos -> Int -> ByteString -> Bool
530+lengthAtLeast :: Pos -> Int -> Buffer -> Bool
523−lengthAtLeast (Pos pos) n bs = B.length bs >= pos + n
531+lengthAtLeast (Pos pos) n bs = Buf.length bs >= pos + n
524{-# INLINE lengthAtLeast #-}
532{-# INLINE lengthAtLeast #-}
526−substring :: Pos -> Pos -> ByteString -> ByteString
534+substring :: Pos -> Pos -> Buffer -> ByteString
527−substring (Pos pos) (Pos n) bs = B.unsafeTake n (B.unsafeDrop pos bs)
535+substring (Pos pos) (Pos n) = Buf.substring pos n
528{-# INLINE substring #-}
536{-# INLINE substring #-}