@@ -53,10 +53,12 @@ public class JSONTokener {
5353 private final Reader reader ;
5454 /** flag to indicate that a previous character was requested. */
5555 private boolean usePrevious ;
56+ /** the number of characters read in the previous line. */
57+ private long characterPreviousLine ;
5658
5759
5860 /**
59- * Construct a JSONTokener from a Reader.
61+ * Construct a JSONTokener from a Reader. The caller must close the Reader.
6062 *
6163 * @param reader A reader.
6264 */
@@ -69,12 +71,13 @@ public JSONTokener(Reader reader) {
6971 this .previous = 0 ;
7072 this .index = 0 ;
7173 this .character = 1 ;
74+ this .characterPreviousLine = 0 ;
7275 this .line = 1 ;
7376 }
7477
7578
7679 /**
77- * Construct a JSONTokener from an InputStream.
80+ * Construct a JSONTokener from an InputStream. The caller must close the input stream.
7881 * @param inputStream The source.
7982 */
8083 public JSONTokener (InputStream inputStream ) {
@@ -103,12 +106,23 @@ public void back() throws JSONException {
103106 if (this .usePrevious || this .index <= 0 ) {
104107 throw new JSONException ("Stepping back two steps is not supported" );
105108 }
106- this .index --;
107- this .character --;
109+ this .decrementIndexes ();
108110 this .usePrevious = true ;
109111 this .eof = false ;
110112 }
111113
114+ /**
115+ * Decrements the indexes for the {@link #back()} method based on the previous character read.
116+ */
117+ private void decrementIndexes () {
118+ this .index --;
119+ if (this .previous =='\r' || this .previous == '\n' ) {
120+ this .line --;
121+ this .character =this .characterPreviousLine ;
122+ } else if (this .character > 0 ){
123+ this .character --;
124+ }
125+ }
112126
113127 /**
114128 * Get the hex value of a character (base16).
@@ -183,26 +197,39 @@ public char next() throws JSONException {
183197 } catch (IOException exception ) {
184198 throw new JSONException (exception );
185199 }
186-
187- if (c <= 0 ) { // End of stream
188- this .eof = true ;
189- return 0 ;
190- }
191200 }
192- this .index += 1 ;
193- if (this .previous == '\r' ) {
194- this .line += 1 ;
195- this .character = c == '\n' ? 0 : 1 ;
196- } else if (c == '\n' ) {
197- this .line += 1 ;
198- this .character = 0 ;
199- } else {
200- this .character += 1 ;
201+ if (c <= 0 ) { // End of stream
202+ this .eof = true ;
203+ return 0 ;
201204 }
205+ this .incrementIndexes (c );
202206 this .previous = (char ) c ;
203207 return this .previous ;
204208 }
205209
210+ /**
211+ * Increments the internal indexes according to the previous character
212+ * read and the character passed as the current character.
213+ * @param c the current character read.
214+ */
215+ private void incrementIndexes (int c ) {
216+ if (c > 0 ) {
217+ this .index ++;
218+ if (c =='\r' ) {
219+ this .line ++;
220+ this .characterPreviousLine = this .character ;
221+ this .character =0 ;
222+ }else if (c =='\n' ) {
223+ if (this .previous != '\r' ) {
224+ this .line ++;
225+ this .characterPreviousLine = this .character ;
226+ }
227+ this .character =0 ;
228+ } else {
229+ this .character ++;
230+ }
231+ }
232+ }
206233
207234 /**
208235 * Consume the next character, and check that it matches a specified
@@ -447,21 +474,24 @@ public char skipTo(char to) throws JSONException {
447474 do {
448475 c = this .next ();
449476 if (c == 0 ) {
477+ // in some readers, reset() may throw an exception if
478+ // the remaining portion of the input is greater than
479+ // the mark size (1,000,000 above).
450480 this .reader .reset ();
451481 this .index = startIndex ;
452482 this .character = startCharacter ;
453483 this .line = startLine ;
454- return c ;
484+ return 0 ;
455485 }
456486 } while (c != to );
487+ this .reader .mark (1 );
457488 } catch (IOException exception ) {
458489 throw new JSONException (exception );
459490 }
460491 this .back ();
461492 return c ;
462493 }
463494
464-
465495 /**
466496 * Make a JSONException to signal a syntax error.
467497 *
0 commit comments