From 8d5de3136ccbdea33b289e373a5bbc06cb0a2d58 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Sun, 25 Dec 2011 07:09:46 +0000 Subject: [PATCH] Inline character unescaping. This saves ~10% on the READER_LONG benchmark. --- .../com/google/gson/stream/JsonReader.java | 18 +++++++++++++-- .../google/gson/stream/JsonReaderTest.java | 22 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java index 45a68476..4a54dc15 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonReader.java +++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java @@ -1145,9 +1145,23 @@ public class JsonReader implements Closeable { if (pos + 4 > limit && !fillBuffer(4)) { throw syntaxError("Unterminated escape sequence"); } - String hex = stringPool.get(buffer, pos, 4); + // Equivalent to Integer.parseInt(stringPool.get(buffer, pos, 4), 16); + char result = 0; + for (int i = pos, end = i + 4; i < end; i++) { + char c = buffer[i]; + result <<= 4; + if (c >= '0' && c <= '9') { + result += (c - '0'); + } else if (c >= 'a' && c <= 'f') { + result += (c - 'a' + 10); + } else if (c >= 'A' && c <= 'F') { + result += (c - 'A' + 10); + } else { + throw new NumberFormatException("\\u" + stringPool.get(buffer, pos, 4)); + } + } pos += 4; - return (char) Integer.parseInt(hex, 16); + return result; case 't': return '\t'; diff --git a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java index c8653139..ba0f8666 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java @@ -161,6 +161,28 @@ public final class JsonReaderTest extends TestCase { assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } + public void testUnescapingInvalidCharacters() throws IOException { + String json = "[\"\\u000g\"]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + try { + reader.nextString(); + fail(); + } catch (NumberFormatException expected) { + } + } + + public void testUnescapingTruncatedCharacters() throws IOException { + String json = "[\"\\u000"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + try { + reader.nextString(); + fail(); + } catch (IOException expected) { + } + } + public void testIntegersWithFractionalPartSpecified() throws IOException { JsonReader reader = new JsonReader(new StringReader("[1.0,1.0,1.0]")); reader.beginArray();