Skip a byte order mark (BOM) if it exists.
http://code.google.com/p/android/issues/detail?id=18508
This commit is contained in:
parent
415437810a
commit
befcfd908b
@ -205,12 +205,10 @@ public final class JsonReader implements Closeable {
|
|||||||
private int limit = 0;
|
private int limit = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Track the number of newlines and columns preceding the current buffer. To
|
* The offset of the first character in the buffer.
|
||||||
* compute the line and column of a position in the buffer, compute the line
|
|
||||||
* and column in the buffer and add the preceding values.
|
|
||||||
*/
|
*/
|
||||||
private int bufferStartLine;
|
private int bufferStartLine = 1;
|
||||||
private int bufferStartColumn;
|
private int bufferStartColumn = 1;
|
||||||
|
|
||||||
private final List<JsonScope> stack = new ArrayList<JsonScope>();
|
private final List<JsonScope> stack = new ArrayList<JsonScope>();
|
||||||
{
|
{
|
||||||
@ -829,7 +827,7 @@ public final class JsonReader implements Closeable {
|
|||||||
for (int i = 0; i < pos; i++) {
|
for (int i = 0; i < pos; i++) {
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
bufferStartLine++;
|
bufferStartLine++;
|
||||||
bufferStartColumn = 0;
|
bufferStartColumn = 1;
|
||||||
} else {
|
} else {
|
||||||
bufferStartColumn++;
|
bufferStartColumn++;
|
||||||
}
|
}
|
||||||
@ -846,6 +844,13 @@ public final class JsonReader implements Closeable {
|
|||||||
int total;
|
int total;
|
||||||
while ((total = in.read(buffer, limit, buffer.length - limit)) != -1) {
|
while ((total = in.read(buffer, limit, buffer.length - limit)) != -1) {
|
||||||
limit += total;
|
limit += total;
|
||||||
|
|
||||||
|
// if this is the first read, consume an optional byte order mark (BOM) if it exists
|
||||||
|
if (bufferStartLine == 1 && bufferStartColumn == 1 && limit > 1 && buffer[0] == '\ufeff') {
|
||||||
|
pos++;
|
||||||
|
bufferStartColumn--;
|
||||||
|
}
|
||||||
|
|
||||||
if (limit >= minimum) {
|
if (limit >= minimum) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -860,19 +865,19 @@ public final class JsonReader implements Closeable {
|
|||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result + 1; // the first line is '1'
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getColumnNumber() {
|
private int getColumnNumber() {
|
||||||
int result = bufferStartColumn;
|
int result = bufferStartColumn;
|
||||||
for (int i = 0; i < pos; i++) {
|
for (int i = 0; i < pos; i++) {
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
result = 0;
|
result = 1;
|
||||||
} else {
|
} else {
|
||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result + 1; // the first column is '1'
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int nextNonWhitespace() throws IOException {
|
private int nextNonWhitespace() throws IOException {
|
||||||
@ -1150,7 +1155,8 @@ public final class JsonReader implements Closeable {
|
|||||||
* with this reader's content.
|
* with this reader's content.
|
||||||
*/
|
*/
|
||||||
private IOException syntaxError(String message) throws IOException {
|
private IOException syntaxError(String message) throws IOException {
|
||||||
throw new MalformedJsonException(message + " @" + getLineNumber() + ":" + getColumnNumber());
|
throw new MalformedJsonException(message
|
||||||
|
+ " at line " + getLineNumber() + " column " + getColumnNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence getSnippet() {
|
private CharSequence getSnippet() {
|
||||||
|
@ -765,28 +765,47 @@ public final class JsonReaderTest extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFailWithPosition() throws IOException {
|
public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException {
|
||||||
JsonReader reader = new JsonReader(new StringReader("[\n\n\n\n\n0,}]"));
|
JsonReader reader = new JsonReader(new StringReader("\ufeff[]"));
|
||||||
|
reader.beginArray();
|
||||||
|
reader.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBomForbiddenAsOtherCharacterInDocument() throws IOException {
|
||||||
|
JsonReader reader = new JsonReader(new StringReader("[\ufeff]"));
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
reader.nextInt();
|
|
||||||
try {
|
try {
|
||||||
reader.peek();
|
reader.endArray();
|
||||||
fail();
|
fail();
|
||||||
} catch (IOException expected) {
|
} catch (IOException expected) {
|
||||||
assertEquals("Expected literal value @6:3", expected.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFailWithPosition() throws IOException {
|
||||||
|
testFailWithPosition("Expected literal value at line 6 column 3",
|
||||||
|
"[\n\n\n\n\n0,}]");
|
||||||
|
}
|
||||||
|
|
||||||
public void testFailWithPositionGreaterThanBufferSize() throws IOException {
|
public void testFailWithPositionGreaterThanBufferSize() throws IOException {
|
||||||
String spaces = repeat(' ', 8192);
|
String spaces = repeat(' ', 8192);
|
||||||
JsonReader reader = new JsonReader(new StringReader("[\n\n" + spaces + "\n\n\n0,}]"));
|
testFailWithPosition("Expected literal value at line 6 column 3",
|
||||||
|
"[\n\n" + spaces + "\n\n\n0,}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFailWithPositionIsOffsetByBom() throws IOException {
|
||||||
|
testFailWithPosition("Expected literal value at line 1 column 4",
|
||||||
|
"\ufeff[0,}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testFailWithPosition(String message, String json) throws IOException {
|
||||||
|
JsonReader reader = new JsonReader(new StringReader(json));
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
try {
|
try {
|
||||||
reader.peek();
|
reader.peek();
|
||||||
fail();
|
fail();
|
||||||
} catch (IOException expected) {
|
} catch (IOException expected) {
|
||||||
assertEquals("Expected literal value @6:3", expected.getMessage());
|
assertEquals(message, expected.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user