on master help sign in
Fix up string unescaping, which was both slow and broken (!).
commitc9b1306768a634431cc58ba34b8cd3a4476fbec6 authorBryan O'Sullivan <bos@mailrank.com> dateFri 21 Jan 2011, 19:06 (16 years ago) parent7689c0e
1 file changed+20−22
Data/Aeson/Parser.hs+20−22
Data/Aeson/Parser.hs+20−22
@@ -79,25 +79,23 @@ reparse p s = case (case parse p s of {Partial k -> k ""; r -> r}) of
7979 _ -> fail "unexpected failure"
8080
8181unescape :: Parser [ByteString]
82−unescape = do
83− let backslash = 92
84− h <- A.takeWhile (/=backslash)
85− let rest = do
86− w <- A.word8 backslash *> A.satisfy (`B.elem` "\"\\/ntbrfu")
87− case B.findIndex (==w) "\"\\/ntbrf" of
88− Just i ->
89− ([h,B.singleton $ B.index "\"\\/\n\t\b\r\f" i]++) <$> unescape
90− Nothing -> do
91− a <- reparse hexadecimal =<< A.take 4
92− if a < 0xd800 || a > 0xdfff
93− then ([h,encodeUtf8 . T.singleton . chr $ a]++) <$> unescape
94− else do
95− _ <- string "\\u"
96− b <- reparse hexadecimal =<< A.take 4
97− if a <= 0xdbff && b >= 0xdc00 && b <= 0xdfff
98− then do
99− let c = ((a - 0xd800) `shiftL` 10) + (b - 0xdc00) +
100− 0x10000
101− ([h,encodeUtf8 . T.singleton . chr $ c]++) <$> unescape
102− else fail "invalid UTF-16 surrogates"
103− rest <|> return [h]
82+unescape = Prelude.reverse <$> go [] where
83+ go acc = do
84+ let backslash = 92
85+ h <- A.takeWhile (/=backslash)
86+ let rest = do
87+ w <- A.word8 backslash *> A.satisfy (`B.elem` "\"\\/ntbrfu")
88+ case B.findIndex (==w) "\"\\/ntbrf" of
89+ Just i -> go (B.singleton (B.index "\"\\/\n\t\b\r\f" i):h:acc)
90+ Nothing -> do
91+ a <- reparse hexadecimal =<< A.take 4
92+ if a < 0xd800 || a > 0xdfff
93+ then go (encodeUtf8 (T.singleton . chr $ a):h:acc)
94+ else do
95+ b <- string "\\u" *> (reparse hexadecimal =<< A.take 4)
96+ if a <= 0xdbff && b >= 0xdc00 && b <= 0xdfff
97+ then let c = ((a - 0xd800) `shiftL` 10) + (b - 0xdc00) +
98+ 0x10000
99+ in go (encodeUtf8 (T.singleton . chr $ c):h:acc)
100+ else fail "invalid UTF-16 surrogates"
101+ rest <|> return (h:acc)