@@ -53,8 +53,9 @@ import qualified Data.Scientific as Sci
53import Data.Aeson.Parser.Unescape (unescapeText)
53import Data.Aeson.Parser.Unescape (unescapeText)
55#if MIN_VERSION_ghc_prim(0,3,1)
55#if MIN_VERSION_ghc_prim(0,3,1)
56−import GHC.Base (Int#, (==#), isTrue#, word2Int#)
56+import GHC.Base (Int#, (==#), isTrue#, word2Int#, orI#, andI#)
57import GHC.Word (Word8(W8#))
57import GHC.Word (Word8(W8#))
58+import qualified Data.Text.Encoding as TE
60#define BACKSLASH 92
61#define BACKSLASH 92
@@ -207,23 +208,39 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
207jstring_ :: Parser Text
208jstring_ :: Parser Text
208{-# INLINE jstring_ #-}
209{-# INLINE jstring_ #-}
209jstring_ = {-# SCC "jstring_" #-} do
210jstring_ = {-# SCC "jstring_" #-} do
211+#if MIN_VERSION_ghc_prim(0,3,1)
212+ (s, S _ escaped) <- A.runScanner startState go <* A.anyWord8
213+ -- We escape only if there are
214+ -- non-ascii (over 7bit) characters or backslash present.
216+ -- Note: if/when text will have fast ascii -> text conversion
217+ -- (e.g. uses utf8 encoding) we can have further speedup.
219+ then case unescapeText s of
221+ Left err -> fail $ show err
222+ else return (TE.decodeUtf8 s)
224+ startState = S 0# 0#
225+ go (S skip escaped) (W8# c)
226+ | isTrue# skip = Just (S 0# escaped')
227+ | isTrue# (w ==# 34#) = Nothing -- double quote
228+ | otherwise = Just (S skip' escaped')
231+ skip' = w ==# 92# -- backslash
233+ `orI#` (w `andI#` 0x80# ==# 0x80#) -- c >= 0x80
235+ `orI#` (w `andI#` 0x1f# ==# w) -- c < 0x20
210 s <- A.scan startState go <* A.anyWord8
239 s <- A.scan startState go <* A.anyWord8
211 case unescapeText s of
240 case unescapeText s of
212 Right r -> return r
241 Right r -> return r
213 Left err -> fail $ show err
242 Left err -> fail $ show err
215−#if MIN_VERSION_ghc_prim(0,3,1)
218− | isTrue# a = Just (S 0#)
219− | isTrue# (word2Int# c ==# 34#) = Nothing -- double quote
220− | otherwise = let a' = word2Int# c ==# 92# -- backslash
224−-- This hint will no longer trigger once hlint > 1.9.41 is released.
225−{-# ANN S ("HLint: ignore Use newtype instead of data" :: String) #-}
227 startState = False
244 startState = False
229 | a = Just False
246 | a = Just False