git.iko.soy/typeable/attoparsec
on master help sign in
Speed up scan by a few percent more.
commit9957c03eabec07c3eaf9f21a6d207d3c667d5687 authorBryan O'Sullivan <bos@serpentine.com> dateSat 19 Mar 2011, 16:13 (16 years ago) parent7ac06df
1 file changed+20−12
Data/Attoparsec/Internal.hs+20−12
Data/Attoparsec/Internal.hs+20−12
@@ -71,8 +71,8 @@ import Data.Attoparsec.FastSet (charClass, memberWord8)
7171import Data.Monoid (Monoid(..))
7272import Data.Word (Word8)
7373import Foreign.ForeignPtr (withForeignPtr)
74−import Foreign.Ptr (castPtr, plusPtr)
75−import Foreign.Storable (Storable(peek, sizeOf), peekByteOff)
74+import Foreign.Ptr (castPtr, minusPtr, plusPtr)
75+import Foreign.Storable (Storable(peek, sizeOf))
7676import Prelude hiding (getChar, take, takeWhile)
7777import System.IO.Unsafe (unsafePerformIO)
7878import qualified Data.ByteString as B8
@@ -432,6 +432,8 @@ takeByteString = B.concat `fmap` takeRest
432432takeLazyByteString :: Parser L.ByteString
433433takeLazyByteString = L.fromChunks `fmap` takeRest
434434
435+data T s = T {-# UNPACK #-} !Int s
436+
435437-- | A stateful scanner. The predicate consumes and transforms a
436438-- state argument, and each transformed state is passed to successive
437439-- invocations of the predicate on each byte of the input until one
@@ -452,16 +454,22 @@ scan s0 p = do
452454 where
453455 go acc s1 = do
454456 let scanner (B.PS fp off len) =
455− withForeignPtr fp $ \ptr -> do
456− let inner !i !s | i == off+len = done (i-off) s
457− | otherwise = do
458− w <- peekByteOff ptr i
459− case p s w of
460− Just s' -> inner (i+1) s'
461− Nothing -> done (i-off) s
462− done !i !s = return (B.PS fp off i, B.PS fp (off+i) (len-i),s)
463− inner off s1
464− (h,t,s') <- (unsafePerformIO . scanner) <$> get
457+ withForeignPtr fp $ \ptr0 -> do
458+ let start = ptr0 `plusPtr` off
459+ end = start `plusPtr` len
460+ inner ptr !s
461+ | ptr < end = do
462+ w <- peek ptr
463+ case p s w of
464+ Just s' -> inner (ptr `plusPtr` 1) s'
465+ _ -> done (ptr `minusPtr` start) s
466+ | otherwise = done (ptr `minusPtr` start) s
467+ done !i !s = return (T i s)
468+ inner start s1
469+ bs <- get
470+ let T i s' = unsafePerformIO $ scanner bs
471+ h = B.unsafeTake i bs
472+ t = B.unsafeDrop i bs
465473 put t
466474 if B.null t
467475 then do