Gain a bit of speed by using native Attoparsec for number types instead of reimplementing them with ByteString conversion and call to read

This commit is contained in:
Tissevert 2020-02-14 18:02:40 +01:00
parent 1c457d71d8
commit 923d1800b0
3 changed files with 15 additions and 12 deletions

View file

@ -19,7 +19,7 @@ import PDF.Object (
, blank, dictionary, directObject, integer, line , blank, dictionary, directObject, integer, line
) )
import PDF.Output (ObjectId(..), Offset(..)) import PDF.Output (ObjectId(..), Offset(..))
import PDF.Parser (Parser, (<?>), block, char, evalParser, on, takeAll) import PDF.Parser (MonadParser(..), Parser, (<?>), evalParser, on)
data UserState = UserState { data UserState = UserState {
input :: ByteString input :: ByteString

View file

@ -45,6 +45,7 @@ import Data.Map (Map, (!), mapWithKey)
import qualified Data.Map as Map ( import qualified Data.Map as Map (
delete, empty, fromList, lookup, minViewWithKey, toList, union delete, empty, fromList, lookup, minViewWithKey, toList, union
) )
import qualified Data.Set as Set (fromList, member)
import qualified PDF.EOL as EOL (charset, parser) import qualified PDF.EOL as EOL (charset, parser)
import qualified PDF.Output as Output (line, string) import qualified PDF.Output as Output (line, string)
import PDF.Output ( import PDF.Output (
@ -76,8 +77,8 @@ delimiterCharset = "()<>[]{}/%"
regular :: Char -> Bool regular :: Char -> Bool
regular = not . (`elem` (EOL.charset ++ whiteSpaceCharset ++ delimiterCharset)) regular = not . (`elem` (EOL.charset ++ whiteSpaceCharset ++ delimiterCharset))
integer :: (Read a, Num a, MonadParser m) => m a integer :: MonadParser m => m Int
integer = read . Char8.unpack <$> decNumber <* blank <?> "decimal integer" integer = decNumber <* blank <?> "decimal integer"
------------------------------------- -------------------------------------
-- OBJECTS -- OBJECTS
@ -104,13 +105,12 @@ instance Output Number where
_ -> printf "%f" f _ -> printf "%f" f
number :: MonadParser m => m Number number :: MonadParser m => m Number
number = Number . read . Char8.unpack <$> number = Number <$> (sign <*> value) <?> "number"
(mappend <$> sign <*> (integerPart <|> Char8.cons '0' <$> floatPart))
<?> "number"
where where
sign = string "-" <|> option "" (char '+' >> return "") sign = (string "-" *> return negate) <|> option id (char '+' >> return id)
integerPart = mappend <$> decNumber <*> option "" floatPart value = floatNumber <|> (char '.' *> afterPoint)
floatPart = Char8.cons <$> char '.' <*> (option "0" $ decNumber) afterPoint = read . ("0." ++) . Char8.unpack <$> takeAll (`Set.member` digits)
digits = Set.fromList ['0' .. '9']
-- --
-- StringObject -- StringObject

View file

@ -17,7 +17,7 @@ import Control.Monad.Fail (MonadFail(..))
import Control.Monad.State (StateT(..), evalStateT) import Control.Monad.State (StateT(..), evalStateT)
import Control.Monad.Trans (MonadTrans(..)) import Control.Monad.Trans (MonadTrans(..))
import qualified Data.Attoparsec.ByteString.Char8 as Atto ( import qualified Data.Attoparsec.ByteString.Char8 as Atto (
Parser, char, endOfInput, parseOnly, peekChar', satisfy, string, take Parser, char, decimal, double, endOfInput, parseOnly, peekChar', satisfy, string, take
, takeWhile, takeWhile1 , takeWhile, takeWhile1
) )
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
@ -32,7 +32,8 @@ type MonadDeps m = (MonadFail m, MonadPlus m)
class MonadDeps m => MonadParser m where class MonadDeps m => MonadParser m where
block :: Int -> m ByteString block :: Int -> m ByteString
char :: Char -> m Char char :: Char -> m Char
decNumber :: m ByteString decNumber :: m Int
floatNumber :: m Double
endOfInput :: m () endOfInput :: m ()
hexNumber :: m B16Int hexNumber :: m B16Int
oneOf :: String -> m Char oneOf :: String -> m Char
@ -45,7 +46,8 @@ instance MonadParser Atto.Parser where
block = Atto.take block = Atto.take
char = Atto.char char = Atto.char
endOfInput = Atto.endOfInput endOfInput = Atto.endOfInput
decNumber = Atto.takeWhile1 (`Set.member` digits) decNumber = Atto.decimal
floatNumber = Atto.double
hexNumber = B16Int <$> Atto.takeWhile1 (`Set.member` hexDigits) hexNumber = B16Int <$> Atto.takeWhile1 (`Set.member` hexDigits)
oneOf charSet = Atto.satisfy (`elem` charSet) oneOf charSet = Atto.satisfy (`elem` charSet)
peek = Atto.peekChar' peek = Atto.peekChar'
@ -58,6 +60,7 @@ instance (MonadParser m, MonadTrans t, MonadDeps (t m)) => MonadParser (t m) whe
char = lift . char char = lift . char
endOfInput = lift $ endOfInput endOfInput = lift $ endOfInput
decNumber = lift $ decNumber decNumber = lift $ decNumber
floatNumber = lift $ floatNumber
hexNumber = lift $ hexNumber hexNumber = lift $ hexNumber
oneOf = lift . oneOf oneOf = lift . oneOf
peek = lift $ peek peek = lift $ peek