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
)
import PDF.Output (ObjectId(..), Offset(..))
import PDF.Parser (Parser, (<?>), block, char, evalParser, on, takeAll)
import PDF.Parser (MonadParser(..), Parser, (<?>), evalParser, on)
data UserState = UserState {
input :: ByteString

View file

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

View file

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