on master help sign in
Merge pull request #561 from phadej/text-non-escape
cfb3cb9Adam Bergmark
Data/Aeson/Parser/Internal.hs+30−13
@@ -53,8 +53,9 @@ import qualified Data.Scientific as Sci
53import Data.Aeson.Parser.Unescape (unescapeText)
53import Data.Aeson.Parser.Unescape (unescapeText)
54
54
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
58#endif
59#endif
59
60
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.
215+ --
216+ -- Note: if/when text will have fast ascii -> text conversion
217+ -- (e.g. uses utf8 encoding) we can have further speedup.
218+ if isTrue# escaped
219+ then case unescapeText s of
220+ Right r -> return r
221+ Left err -> fail $ show err
222+ else return (TE.decodeUtf8 s)
223+ where
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')
229+ where
230+ w = word2Int# c
231+ skip' = w ==# 92# -- backslash
232+ escaped' = escaped
233+ `orI#` (w `andI#` 0x80# ==# 0x80#) -- c >= 0x80
234+ `orI#` skip'
235+ `orI#` (w `andI#` 0x1f# ==# w) -- c < 0x20
236+
237+data S = S Int# Int#
238+#else
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
214 where
243 where
215−#if MIN_VERSION_ghc_prim(0,3,1)
216− startState = S 0#
217− go (S a) (W8# c)
218− | isTrue# a = Just (S 0#)
219− | isTrue# (word2Int# c ==# 34#) = Nothing -- double quote
220− | otherwise = let a' = word2Int# c ==# 92# -- backslash
221− in Just (S a')
222−
223−data S = S Int#
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) #-}
226−#else
227 startState = False
244 startState = False
228 go a c
245 go a c
229 | a = Just False
246 | a = Just False
stack-lts8.yaml+1−1
@@ -1,4 +1,4 @@
1−resolver: lts-8.1
1+resolver: lts-8.5
2packages:
2packages:
3- '.'
3- '.'
4- attoparsec-iso8601
4- attoparsec-iso8601