git.iko.soy/typeable/attoparsec
on master help sign in
Add a fast hex number parser.
commit4c162dd2b179b2991a4a4182f50e24938c809f71 authorBryan O'Sullivan <bos@serpentine.com> dateThu 4 Mar 2010, 22:52 (17 years ago) parent714672c
1 file changed+18−2
Data/Attoparsec/Char8.hs+18−2
Data/Attoparsec/Char8.hs+18−2
@@ -63,6 +63,7 @@ module Data.Attoparsec.Char8
6363 , isHorizontalSpace
6464
6565 -- * Numeric parsers
66+ , hexNumber
6667 --, int
6768 --, integer
6869 --, double
@@ -77,16 +78,20 @@ import Data.Attoparsec.FastSet (charClass, memberChar)
7778import Data.Attoparsec.Internal (Parser, (<?>))
7879import Data.ByteString.Internal (c2w, w2c)
7980-- import Data.ByteString.Lex.Double (readDouble)
80−import Data.Char (toLower)
8181import Data.Word (Word8)
8282import Prelude hiding (takeWhile)
8383import qualified Data.Attoparsec as A
8484import qualified Data.Attoparsec.Internal as I
8585import qualified Data.ByteString.Char8 as B
86+import qualified Data.ByteString as B8
87+
88+toLower :: Word8 -> Word8
89+toLower w | w >= 65 && w <= 90 = w + 32
90+ | otherwise = w
8691
8792-- | Satisfy a literal string, ignoring case.
8893stringCI :: B.ByteString -> Parser B.ByteString
89−stringCI = I.stringTransform (B.map toLower)
94+stringCI = I.stringTransform (B8.map toLower)
9095{-# INLINE stringCI #-}
9196
9297takeWhile1 :: (Char -> Bool) -> Parser B.ByteString
@@ -203,3 +208,14 @@ integer = numeric "Integer" B.readInteger
203208double :: Parser Double
204209double = numeric "Double" readDouble
205210-}
211+
212+hexNumber :: Integral a => Parser a
213+{-# SPECIALISE hexNumber :: Parser Int #-}
214+hexNumber = fromHex `fmap` I.takeWhile1 isHexDigit
215+ where isHexDigit w = (w >= 48 && w <= 57) || (x >= 97 && x <= 102)
216+ where x = toLower w
217+ fromHex = B8.foldl' step 0
218+ step a w | w >= 48 && w <= 57 = a * 16 + fromIntegral (w - 48)
219+ | x >= 97 && x <= 102 = a * 16 + fromIntegral (x - 87)
220+ | otherwise = error "impossible"
221+ where x = toLower w