io.setl.json.io.MutableLocation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of canonical-json Show documentation
Show all versions of canonical-json Show documentation
An implementation of the Canonical JSON format with support for javax.json and Jackson
The newest version!
package io.setl.json.io;
/**
* Implementation of the JsonLocation interface.
*
* The stream offset refers to the character position in the stream, not the byte position.
*
* The column and line numbers are provided as a best effort and may not match a visual representation of the data.
*
* Tabs are allowed as whitespace between JSON elements. Tabs increment the column count as if there were an 8 character tab-stop.
*
* JSON strings can contain many special Unicode characters, including zero-width characters, characters that combine with other characters, and characters
* that cause the text direction to be reversed. The special meaning of these characters is ignored when calculating the column number.
*
*
* Examples of confusing locations
*
* String
* Location of the 'X' (0058)
* UTF-16
*
* "abcXf" 5 0022 0061 0062 0063 0058 0066 0022
* "cXf" 5 0022 200b 200b 0063 0058 0066 0022
The 'a' and 'b' have been replaced by zero-width spaces
* "àcXf" 5 0022 0061 0300 0063 0058 0066 0022
The accent on the 'a' is a separate character.
*
*
* @author Simon Greatrix on 10/01/2020.
*/
public class MutableLocation extends Location {
private static final int TAB_STOP = 8;
private boolean lastWasCR = false;
/** New instance. */
public MutableLocation() {
// do nothing
}
/**
* Set the column number.
*
* @param columnNumber the column number
*/
public void setColumnNumber(long columnNumber) {
this.columnNumber = columnNumber;
}
/**
* Set the line number.
*
* @param lineNumber the line number
*/
public void setLineNumber(long lineNumber) {
this.lineNumber = lineNumber;
}
/**
* Set the stream offset.
*
* @param streamOffset the stream offset
*/
public void setStreamOffset(long streamOffset) {
this.streamOffset = streamOffset;
}
/**
* Update this location from reading the given character from the stream.
*
* @param ch the character.
*/
public void update(int ch) {
if (ch >= ' ') {
streamOffset++;
columnNumber++;
return;
}
if (ch == -1) {
// EOF reached, so don't update the position.
return;
}
// we read a character, so update the position
streamOffset++;
if (ch == '\t') {
// 1..8 -> 9, 9..16 -> 17, 17..24 -> 25
long diff = TAB_STOP - ((columnNumber - 1) % TAB_STOP);
columnNumber += diff;
return;
}
// Either \n or second part of \r\n
if (ch == '\n') {
columnNumber = 0;
if (lastWasCR) {
lastWasCR = false;
} else {
lineNumber++;
}
return;
}
if (ch == '\r') {
columnNumber = 0;
lineNumber++;
lastWasCR = true;
return;
}
// C0 character that is not \t, \r nor \n. We should never see these characters in JSON documents, so I guess an error message is imminent.
lastWasCR = false;
columnNumber++;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy