@@ -53,8 +53,9 @@ import qualified Data.Scientific as Sci
53
53
import Data.Aeson.Parser.Unescape (unescapeText )
54
54
55
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 # )
57
57
import GHC.Word (Word8 (W8 #))
58
+ import qualified Data.Text.Encoding as TE
58
59
#endif
59
60
60
61
#define BACKSLASH 92
@@ -207,23 +208,41 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
207
208
jstring_ :: Parser Text
208
209
{-# INLINE jstring_ #-}
209
210
jstring_ = {-# 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
+ -- This hint will no longer trigger once hlint > 1.9.41 is released.
239
+ {-# ANN S ("HLint: ignore Use newtype instead of data" :: String) #-}
240
+ #else
210
241
s <- A. scan startState go <* A. anyWord8
211
242
case unescapeText s of
212
243
Right r -> return r
213
244
Left err -> fail $ show err
214
245
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
246
startState = False
228
247
go a c
229
248
| a = Just False
0 commit comments