on bb59622 help sign in
Data/Aeson/Parser/Internal.hs+16−41
since splitsnapshots
unifiedsplit
@@ -2,12 +2,9 @@
2{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
3{-# LANGUAGE NoImplicitPrelude #-}
3{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
5−#if MIN_VERSION_ghc_prim(0,3,1)
6−{-# LANGUAGE MagicHash #-}
7−#endif
8#if __GLASGOW_HASKELL__ <= 710 && __GLASGOW_HASKELL__ >= 706
5#if __GLASGOW_HASKELL__ <= 710 && __GLASGOW_HASKELL__ >= 706
9-- Work around a compiler bug
6-- Work around a compiler bug
10−{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}
7+{-# OPTIONS_GHC -fsimpl-tick-factor=300 #-}
11#endif
8#endif
12-- |
9-- |
13-- Module: Data.Aeson.Parser.Internal
10-- Module: Data.Aeson.Parser.Internal
@@ -58,8 +55,10 @@ import Data.Aeson.Types.Internal (IResult(..), JSONPath, Object, Result(..), Val
58import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, string)
55import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, string)
59import Data.Function (fix)
56import Data.Function (fix)
60import Data.Functor.Compat (($>))
57import Data.Functor.Compat (($>))
58+import Data.Bits (testBit)
61import Data.Scientific (Scientific)
59import Data.Scientific (Scientific)
62import Data.Text (Text)
60import Data.Text (Text)
61+import qualified Data.Text.Encoding as TE
63import Data.Vector (Vector)
62import Data.Vector (Vector)
64import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
63import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
65import qualified Data.Attoparsec.ByteString as A
64import qualified Data.Attoparsec.ByteString as A
@@ -71,12 +70,6 @@ import qualified Data.HashMap.Strict as H
71import qualified Data.Scientific as Sci
70import qualified Data.Scientific as Sci
72import Data.Aeson.Parser.Unescape (unescapeText)
71import Data.Aeson.Parser.Unescape (unescapeText)
73
72
74−#if MIN_VERSION_ghc_prim(0,3,1)
75−import GHC.Base (Int#, (==#), isTrue#, word2Int#, orI#, andI#)
76−import GHC.Word (Word8(W8#))
77−import qualified Data.Text.Encoding as TE
78−#endif
79−
80#define BACKSLASH 92
73#define BACKSLASH 92
81#define CLOSE_CURLY 125
74#define CLOSE_CURLY 125
82#define CLOSE_SQUARE 93
75#define CLOSE_SQUARE 93
@@ -323,37 +316,20 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
323-- | Parse a string without a leading quote.
316-- | Parse a string without a leading quote.
324jstring_ :: Parser Text
317jstring_ :: Parser Text
325{-# INLINE jstring_ #-}
318{-# INLINE jstring_ #-}
326−jstring_ = {-# SCC "jstring_" #-} do
319+jstring_ = do
327−#if MIN_VERSION_ghc_prim(0,3,1)
320+ s <- A.takeWhile (\w -> w /= DOUBLE_QUOTE && w /= BACKSLASH && not (testBit w 7))
328− (s, S _ escaped) <- A.runScanner startState go <* A.anyWord8
321+ let txt = TE.decodeUtf8 s
329− -- We escape only if there are
322+ w <- A.peekWord8
330− -- non-ascii (over 7bit) characters or backslash present.
331− --
332− -- Note: if/when text will have fast ascii -> text conversion
333− -- (e.g. uses utf8 encoding) we can have further speedup.
334− if isTrue# escaped
335− then case unescapeText s of
323+ case w of
336− Right r -> return r
324+ Nothing -> fail "string without end"
337− Left err -> fail $ show err
325+ Just DOUBLE_QUOTE -> A.anyWord8 $> txt
338− else return (TE.decodeUtf8 s)
326+ _ -> jstringSlow s
339− where
327+
340− startState = S 0# 0#
328+jstringSlow :: B.ByteString -> Parser Text
341− go (S skip escaped) (W8# c)
329+{-# INLINE jstringSlow #-}
342− | isTrue# skip = Just (S 0# escaped')
330+jstringSlow s' = {-# SCC "jstringSlow" #-} do
343− | isTrue# (w ==# 34#) = Nothing -- double quote
344− | otherwise = Just (S skip' escaped')
345− where
346− w = word2Int# c
347− skip' = w ==# 92# -- backslash
348− escaped' = escaped
349− `orI#` (w `andI#` 0x80# ==# 0x80#) -- c >= 0x80
350− `orI#` skip'
351− `orI#` (w `andI#` 0x1f# ==# w) -- c < 0x20
352−
353−data S = S Int# Int#
354−#else
355 s <- A.scan startState go <* A.anyWord8
331 s <- A.scan startState go <* A.anyWord8
356− case unescapeText s of
332+ case unescapeText (B.append s' s) of
357 Right r -> return r
333 Right r -> return r
358 Left err -> fail $ show err
334 Left err -> fail $ show err
359 where
335 where
@@ -364,7 +340,6 @@ data S = S Int# Int#
364 | otherwise = let a' = c == backslash
340 | otherwise = let a' = c == backslash
365 in Just a'
341 in Just a'
366 where backslash = BACKSLASH
342 where backslash = BACKSLASH
367−#endif
368
343
369decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
344decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
370decodeWith p to s =
345decodeWith p to s =