Skip to content

Commit 1bca6a1

Browse files
committed
don't unescape text in clear cases
1 parent 6306cec commit 1bca6a1

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

Data/Aeson/Parser/Internal.hs

+32-13
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ import qualified Data.Scientific as Sci
5353
import Data.Aeson.Parser.Unescape (unescapeText)
5454

5555
#if MIN_VERSION_ghc_prim(0,3,1)
56-
import GHC.Base (Int#, (==#), isTrue#, word2Int#)
56+
import GHC.Base (Int#, (==#), isTrue#, word2Int#, orI#, andI#)
5757
import GHC.Word (Word8(W8#))
58+
import qualified Data.Text.Encoding as TE
5859
#endif
5960

6061
#define BACKSLASH 92
@@ -207,23 +208,41 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
207208
jstring_ :: Parser Text
208209
{-# INLINE jstring_ #-}
209210
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
210241
s <- A.scan startState go <* A.anyWord8
211242
case unescapeText s of
212243
Right r -> return r
213244
Left err -> fail $ show err
214245
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
227246
startState = False
228247
go a c
229248
| a = Just False

stack-lts8.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
resolver: lts-8.1
1+
resolver: lts-8.5
22
packages:
33
- '.'
44
- attoparsec-iso8601

0 commit comments

Comments
 (0)