diff options
-rw-r--r-- | core/java/android/util/JsonReader.java | 41 | ||||
-rw-r--r-- | core/tests/coretests/src/android/util/JsonReaderTest.java | 29 |
2 files changed, 69 insertions, 1 deletions
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index 132b595..09ce8e4 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -196,6 +196,12 @@ public final class JsonReader implements Closeable { private int pos = 0; private int limit = 0; + /* + * The offset of the first character in the buffer. + */ + private int bufferStartLine = 1; + private int bufferStartColumn = 1; + private final List<JsonScope> stack = new ArrayList<JsonScope>(); { push(JsonScope.EMPTY_DOCUMENT); @@ -711,6 +717,16 @@ public final class JsonReader implements Closeable { * false. */ private boolean fillBuffer(int minimum) throws IOException { + // Before clobbering the old characters, update where buffer starts + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + bufferStartLine++; + bufferStartColumn = 1; + } else { + bufferStartColumn++; + } + } + if (limit != pos) { limit -= pos; System.arraycopy(buffer, pos, buffer, 0, limit); @@ -729,6 +745,28 @@ public final class JsonReader implements Closeable { return false; } + private int getLineNumber() { + int result = bufferStartLine; + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + result++; + } + } + return result; + } + + private int getColumnNumber() { + int result = bufferStartColumn; + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + result = 1; + } else { + result++; + } + } + return result; + } + private int nextNonWhitespace() throws IOException { while (pos < limit || fillBuffer(1)) { int c = buffer[pos++]; @@ -1107,7 +1145,8 @@ public final class JsonReader implements Closeable { * with this reader's content. */ private IOException syntaxError(String message) throws IOException { - throw new MalformedJsonException(message + " near " + getSnippet()); + throw new MalformedJsonException(message + + " at line " + getLineNumber() + " column " + getColumnNumber()); } private CharSequence getSnippet() { diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index b5c2c27..440aeb5 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -856,4 +856,33 @@ public final class JsonReaderTest extends TestCase { } catch (IOException expected) { } } + + public void testFailWithPosition() throws IOException { + testFailWithPosition("Expected literal value at line 6 column 3", + "[\n\n\n\n\n0,}]"); + } + + public void testFailWithPositionGreaterThanBufferSize() throws IOException { + String spaces = repeat(' ', 8192); + testFailWithPosition("Expected literal value at line 6 column 3", + "[\n\n" + spaces + "\n\n\n0,}]"); + } + + private void testFailWithPosition(String message, String json) throws IOException { + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + reader.nextInt(); + try { + reader.peek(); + fail(); + } catch (IOException expected) { + assertEquals(message, expected.getMessage()); + } + } + + private String repeat(char c, int count) { + char[] array = new char[count]; + Arrays.fill(array, c); + return new String(array); + } } |