@@ -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 = 0 ;
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 */
@@ -74,7 +76,7 @@ public JSONTokener(Reader reader) {
7476
7577
7678 /**
77- * Construct a JSONTokener from an InputStream.
79+ * Construct a JSONTokener from an InputStream. The caller must close the input stream.
7880 * @param inputStream The source.
7981 */
8082 public JSONTokener (InputStream inputStream ) {
@@ -103,12 +105,23 @@ public void back() throws JSONException {
103105 if (this .usePrevious || this .index <= 0 ) {
104106 throw new JSONException ("Stepping back two steps is not supported" );
105107 }
106- this .index --;
107- this .character --;
108+ this .decrementIndexes ();
108109 this .usePrevious = true ;
109110 this .eof = false ;
110111 }
111112
113+ /**
114+ * Decrements the indexes for the {@link #back()} method based on the previous character read.
115+ */
116+ private void decrementIndexes () {
117+ this .index --;
118+ if (this .previous =='\r' || this .previous == '\n' ) {
119+ this .line --;
120+ this .character =this .characterPreviousLine ;
121+ } else if (this .character > 0 ){
122+ this .character --;
123+ }
124+ }
112125
113126 /**
114127 * Get the hex value of a character (base16).
@@ -183,26 +196,39 @@ public char next() throws JSONException {
183196 } catch (IOException exception ) {
184197 throw new JSONException (exception );
185198 }
186-
187- if (c <= 0 ) { // End of stream
188- this .eof = true ;
189- return 0 ;
190- }
191199 }
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 ;
200+ if (c <= 0 ) { // End of stream
201+ this .eof = true ;
202+ return 0 ;
201203 }
204+ this .incrementIndexes (c );
202205 this .previous = (char ) c ;
203206 return this .previous ;
204207 }
205208
209+ /**
210+ * Increments the internal indexes according to the previous character
211+ * read and the character passed as the current character.
212+ * @param c the current character read.
213+ */
214+ private void incrementIndexes (int c ) {
215+ if (c > 0 ) {
216+ this .index ++;
217+ if (c =='\r' ) {
218+ this .line ++;
219+ this .characterPreviousLine = this .character ;
220+ this .character =0 ;
221+ }else if (c =='\n' ) {
222+ if (this .previous != '\r' ) {
223+ this .line ++;
224+ this .characterPreviousLine = this .character ;
225+ }
226+ this .character =0 ;
227+ } else {
228+ this .character ++;
229+ }
230+ }
231+ }
206232
207233 /**
208234 * Consume the next character, and check that it matches a specified
@@ -447,21 +473,24 @@ public char skipTo(char to) throws JSONException {
447473 do {
448474 c = this .next ();
449475 if (c == 0 ) {
476+ // in some readers, reset() may throw an exception if
477+ // the remaining portion of the input is greater than
478+ // the mark size (1,000,000 above).
450479 this .reader .reset ();
451480 this .index = startIndex ;
452481 this .character = startCharacter ;
453482 this .line = startLine ;
454- return c ;
483+ return 0 ;
455484 }
456485 } while (c != to );
486+ this .reader .mark (1 );
457487 } catch (IOException exception ) {
458488 throw new JSONException (exception );
459489 }
460490 this .back ();
461491 return c ;
462492 }
463493
464-
465494 /**
466495 * Make a JSONException to signal a syntax error.
467496 *
0 commit comments