@@ -2,12 +2,9 @@
22{-# LANGUAGE CPP #-}
33{-# LANGUAGE NoImplicitPrelude #-}
44{-# LANGUAGE OverloadedStrings #-}
5−#if MIN_VERSION_ghc_prim(0,3,1)
6−{-# LANGUAGE MagicHash #-}
7−#endif
85#if __GLASGOW_HASKELL__ <= 710 && __GLASGOW_HASKELL__ >= 706
96-- Work around a compiler bug
10−{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}
7+{-# OPTIONS_GHC -fsimpl-tick-factor=300 #-}
118#endif
129-- |
1310-- Module: Data.Aeson.Parser.Internal
@@ -58,8 +55,10 @@ import Data.Aeson.Types.Internal (IResult(..), JSONPath, Object, Result(..), Val
5855import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, string)
5956import Data.Function (fix)
6057import Data.Functor.Compat (($>))
58+import Data.Bits (testBit)
6159import Data.Scientific (Scientific)
6260import Data.Text (Text)
61+import qualified Data.Text.Encoding as TE
6362import Data.Vector (Vector)
6463import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
6564import qualified Data.Attoparsec.ByteString as A
@@ -74,12 +73,6 @@ import qualified Data.HashMap.Strict as H
7473import qualified Data.Scientific as Sci
7574import Data.Aeson.Parser.Unescape (unescapeText)
7675
77−#if MIN_VERSION_ghc_prim(0,3,1)
78−import GHC.Base (Int#, (==#), isTrue#, word2Int#, orI#, andI#)
79−import GHC.Word (Word8(W8#))
80−import qualified Data.Text.Encoding as TE
81−#endif
82−
8376#define BACKSLASH 92
8477#define CLOSE_CURLY 125
8578#define CLOSE_SQUARE 93
@@ -326,37 +319,20 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
326319-- | Parse a string without a leading quote.
327320jstring_ :: Parser Text
328321{-# INLINE jstring_ #-}
329−jstring_ = {-# SCC "jstring_" #-} do
330−#if MIN_VERSION_ghc_prim(0,3,1)
331− (s, S _ escaped) <- A.runScanner startState go <* A.anyWord8
332− -- We escape only if there are
333− -- non-ascii (over 7bit) characters or backslash present.
334− --
335− -- Note: if/when text will have fast ascii -> text conversion
336− -- (e.g. uses utf8 encoding) we can have further speedup.
337− if isTrue# escaped
338− then case unescapeText s of
339− Right r -> return r
340− Left err -> fail $ show err
341− else return (TE.decodeUtf8 s)
342− where
343− startState = S 0# 0#
344− go (S skip escaped) (W8# c)
345− | isTrue# skip = Just (S 0# escaped')
346− | isTrue# (w ==# 34#) = Nothing -- double quote
347− | otherwise = Just (S skip' escaped')
348− where
349− w = word2Int# c
350− skip' = w ==# 92# -- backslash
351− escaped' = escaped
352− `orI#` (w `andI#` 0x80# ==# 0x80#) -- c >= 0x80
353− `orI#` skip'
354− `orI#` (w `andI#` 0x1f# ==# w) -- c < 0x20
355−
356−data S = S Int# Int#
357−#else
322+jstring_ = do
323+ s <- A.takeWhile (\w -> w /= DOUBLE_QUOTE && w /= BACKSLASH && not (testBit w 7))
324+ let txt = TE.decodeUtf8 s
325+ w <- A.peekWord8
326+ case w of
327+ Nothing -> fail "string without end"
328+ Just DOUBLE_QUOTE -> A.anyWord8 $> txt
329+ _ -> jstringSlow s
330+
331+jstringSlow :: B.ByteString -> Parser Text
332+{-# INLINE jstringSlow #-}
333+jstringSlow s' = {-# SCC "jstringSlow" #-} do
358334 s <- A.scan startState go <* A.anyWord8
359− case unescapeText s of
335+ case unescapeText (B.append s' s) of
360336 Right r -> return r
361337 Left err -> fail $ show err
362338 where
@@ -367,7 +343,6 @@ data S = S Int# Int#
367343 | otherwise = let a' = c == backslash
368344 in Just a'
369345 where backslash = BACKSLASH
370−#endif
371346
372347decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
373348decodeWith p to s =