on master help sign in
Data/Aeson/Parser/Internal.hs+40−15
since splitsnapshots
unifiedsplit
@@ -2,6 +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
5#if __GLASGOW_HASKELL__ <= 710 && __GLASGOW_HASKELL__ >= 706
8#if __GLASGOW_HASKELL__ <= 710 && __GLASGOW_HASKELL__ >= 706
6-- Work around a compiler bug
9-- Work around a compiler bug
7{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}
10{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}
@@ -55,10 +58,8 @@ import Data.Aeson.Types.Internal (IResult(..), JSONPath, Object, Result(..), Val
55import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, string)
58import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, string)
56import Data.Function (fix)
59import Data.Function (fix)
57import Data.Functor.Compat (($>))
60import Data.Functor.Compat (($>))
58−import Data.Bits (testBit)
59import Data.Scientific (Scientific)
61import Data.Scientific (Scientific)
60import Data.Text (Text)
62import Data.Text (Text)
61−import qualified Data.Text.Encoding as TE
62import Data.Vector (Vector)
63import Data.Vector (Vector)
63import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
64import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
64import qualified Data.Attoparsec.ByteString as A
65import qualified Data.Attoparsec.ByteString as A
@@ -70,6 +71,12 @@ import qualified Data.HashMap.Strict as H
70import qualified Data.Scientific as Sci
71import qualified Data.Scientific as Sci
71import Data.Aeson.Parser.Unescape (unescapeText)
72import Data.Aeson.Parser.Unescape (unescapeText)
72
73
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+
73#define BACKSLASH 92
80#define BACKSLASH 92
74#define CLOSE_CURLY 125
81#define CLOSE_CURLY 125
75#define CLOSE_SQUARE 93
82#define CLOSE_SQUARE 93
@@ -316,20 +323,37 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
316-- | Parse a string without a leading quote.
323-- | Parse a string without a leading quote.
317jstring_ :: Parser Text
324jstring_ :: Parser Text
318{-# INLINE jstring_ #-}
325{-# INLINE jstring_ #-}
319−jstring_ = do
326+jstring_ = {-# SCC "jstring_" #-} do
320− s <- A.takeWhile (\w -> w /= DOUBLE_QUOTE && w /= BACKSLASH && not (testBit w 7))
327+#if MIN_VERSION_ghc_prim(0,3,1)
321− let txt = TE.decodeUtf8 s
328+ (s, S _ escaped) <- A.runScanner startState go <* A.anyWord8
322− w <- A.peekWord8
329+ -- We escape only if there are
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
323− case w of
335+ then case unescapeText s of
324− Nothing -> fail "string without end"
336+ Right r -> return r
325− Just DOUBLE_QUOTE -> A.anyWord8 $> txt
337+ Left err -> fail $ show err
326− _ -> jstringSlow s
338+ else return (TE.decodeUtf8 s)
327−
339+ where
328−jstringSlow :: B.ByteString -> Parser Text
340+ startState = S 0# 0#
329−{-# INLINE jstringSlow #-}
341+ go (S skip escaped) (W8# c)
330−jstringSlow s' = {-# SCC "jstringSlow" #-} do
342+ | isTrue# skip = Just (S 0# escaped')
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
331 s <- A.scan startState go <* A.anyWord8
355 s <- A.scan startState go <* A.anyWord8
332− case unescapeText (B.append s' s) of
356+ case unescapeText s of
333 Right r -> return r
357 Right r -> return r
334 Left err -> fail $ show err
358 Left err -> fail $ show err
335 where
359 where
@@ -340,6 +364,7 @@ jstringSlow s' = {-# SCC "jstringSlow" #-} do
340 | otherwise = let a' = c == backslash
364 | otherwise = let a' = c == backslash
341 in Just a'
365 in Just a'
342 where backslash = BACKSLASH
366 where backslash = BACKSLASH
367+#endif
343
368
344decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
369decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
345decodeWith p to s =
370decodeWith p to s =