on master help sign in
Copy-paste and adapt the scientific function from attoparsec
ae70879Bryan O'Sullivan
Data/Aeson/Parser/Internal.hs+41−1
@@ -36,8 +36,11 @@ module Data.Aeson.Parser.Internal
36import Prelude ()
36import Prelude ()
37import Prelude.Compat
37import Prelude.Compat
38
38
39+import Control.Applicative ((<|>))
40+import Control.Monad (void, when)
39import Data.Aeson.Types.Internal (IResult(..), JSONPath, Result(..), Value(..))
41import Data.Aeson.Types.Internal (IResult(..), JSONPath, Result(..), Value(..))
40−import Data.Attoparsec.ByteString.Char8 (Parser, char, endOfInput, scientific, skipSpace, string)
42+import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, skipSpace, string)
43+import Data.Scientific (Scientific)
41import Data.Text (Text)
44import Data.Text (Text)
42import Data.Vector as Vector (Vector, empty, fromListN, reverse)
45import Data.Vector as Vector (Vector, empty, fromListN, reverse)
43import qualified Data.Attoparsec.ByteString as A
46import qualified Data.Attoparsec.ByteString as A
@@ -45,6 +48,7 @@ import qualified Data.Attoparsec.Lazy as L
45import qualified Data.ByteString as B
48import qualified Data.ByteString as B
46import qualified Data.ByteString.Lazy as L
49import qualified Data.ByteString.Lazy as L
47import qualified Data.HashMap.Strict as H
50import qualified Data.HashMap.Strict as H
51+import qualified Data.Scientific as Sci
48import Data.Aeson.Parser.Unescape
52import Data.Aeson.Parser.Unescape
49
53
50#if MIN_VERSION_ghc_prim(0,3,1)
54#if MIN_VERSION_ghc_prim(0,3,1)
@@ -289,3 +293,39 @@ jsonEOF = json <* skipSpace <* endOfInput
289-- end-of-input. See also: 'json''.
293-- end-of-input. See also: 'json''.
290jsonEOF' :: Parser Value
294jsonEOF' :: Parser Value
291jsonEOF' = json' <* skipSpace <* endOfInput
295jsonEOF' = json' <* skipSpace <* endOfInput
296+
297+------------------ Copy-pasted and adapted from attoparsec ------------------
298+
299+-- A strict pair
300+data SP = SP !Integer {-# UNPACK #-}!Int
301+
302+{-# INLINE scientific #-}
303+scientific :: Parser Scientific
304+scientific = do
305+ let minus = 45
306+ plus = 43
307+ sign <- A.peekWord8'
308+ let !positive = sign == plus || sign /= minus
309+ when (sign == plus || sign == minus) $
310+ void A.anyWord8
311+
312+ n <- decimal
313+
314+ let f fracDigits = SP (B.foldl' step n fracDigits)
315+ (negate $ B.length fracDigits)
316+ step a w = a * 10 + fromIntegral (w - 48)
317+
318+ dotty <- A.peekWord8
319+ -- '.' -> ascii 46
320+ SP c e <- case dotty of
321+ Just 46 -> A.anyWord8 *> (f <$> A.takeWhile isDigit_w8)
322+ _ -> pure (SP n 0)
323+
324+ let !signedCoeff | positive = c
325+ | otherwise = -c
326+
327+ let littleE = 101
328+ bigE = 69
329+ (A.satisfy (\ex -> ex == littleE || ex == bigE) *>
330+ fmap (Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
331+ return (Sci.scientific signedCoeff e)