Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions src/main/java/org/json/CharSequenceReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package org.json;

import java.io.Reader;

/**
* a Reader to read from a {@link CharSequence} e.g. a {@link String}.
*/
public class CharSequenceReader extends Reader {

private final CharSequence charSequence;
private int index;
private int markedIndex;

/**
* creates a new CharSequenceReader to read from the given CharSequence
* @param charSequence the input to read.
*/
public CharSequenceReader(CharSequence charSequence) {
this.charSequence = charSequence;
}

/**
* reads the next character from the input.
* @return returns the read character or -1 if the end of the input is reached.
*/
@Override
public int read() {
if (index < charSequence.length()) {
return charSequence.charAt(index++);
}
return -1;
}


/**
* reads a maximum number of characters from the input into the charBuffer starting at the offset
* and returns the number of actual read characters.
*
* @param charBuffer the target charBuffer to write the read characters into
* @param offset the offset index where to start writing into the charBuffer
* @param length the maximum number of characters to read
* @return the number of characters read into the charBuffer or -1 if the end of the input is reached.
*/
@Override
public int read(char[] charBuffer, int offset, int length) {
if (charBuffer == null) {
throw new NullPointerException("The target charBuffer cannot be null");
} else if (offset < 0) {
throw new IndexOutOfBoundsException("Offset must not be negative");
} else if (length < 0) {
throw new IndexOutOfBoundsException("Length must not be negative");
} else if (offset + length > charBuffer.length) {
throw new IndexOutOfBoundsException("Offset + length must not be larger than the charBuffer length");
} else if (index >= charSequence.length()) {
return -1;
}

int charsToRead = Math.min(length, charSequence.length() - index);
for (int i = 0; i < charsToRead; i++) {
charBuffer[offset + i] = charSequence.charAt(index++);
}

return charsToRead;
}

/**
* returns true to indicate that mark is supported.
* @return true
*/
@Override
public boolean markSupported() {
return true;
}

/**
* marks the reader on the current position to later jump back to it by using {@link #reset()}.
* @param readAheadLimit will be ignored. This reader has no readAheadLimit.
*/
@Override
public void mark(int readAheadLimit) {
markedIndex = this.index;
}

/**
* resets the reader to the previous marked position used by {@link #mark(int)}.
*/
@Override
public void reset() {
index = markedIndex;
}


/**
* does nothing.
*/
@Override
public void close() {

}

}
2 changes: 1 addition & 1 deletion src/main/java/org/json/JSONTokener.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public JSONTokener(InputStream inputStream) {
* @param s A source string.
*/
public JSONTokener(String s) {
this(new StringReader(s));
this(new CharSequenceReader(s));
}


Expand Down
88 changes: 88 additions & 0 deletions src/test/java/org/json/junit/CharSequenceReaderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.json.junit;

import org.json.CharSequenceReader;
import org.junit.Test;

import static org.junit.Assert.*;

public class CharSequenceReaderTest {

@Test
public void testReadSingleCharacter() {
CharSequenceReader reader = new CharSequenceReader("test");
assertEquals('t', reader.read());
assertEquals('e', reader.read());
assertEquals('s', reader.read());
assertEquals('t', reader.read());
assertEquals(-1, reader.read());
assertEquals(-1, reader.read());
}

@Test
public void testReadToCharBuffer() {
CharSequenceReader reader = new CharSequenceReader("test");
char[] buffer = new char[10];
int read = reader.read(buffer, 2, 3);
assertEquals(3, read);
assertArrayEquals(new char[]{0, 0, 't', 'e', 's', 0, 0, 0, 0, 0}, buffer);
}

@Test
public void testReadPastEnd() {
CharSequenceReader reader = new CharSequenceReader("test");
char[] buffer = new char[5];
assertEquals(4, reader.read(buffer, 0, 5));
assertEquals(-1, reader.read(buffer, 0, 5));
}

@Test
public void testMarkAndReset() {
CharSequenceReader reader = new CharSequenceReader("test");
assertEquals('t', reader.read());
reader.mark(0);
assertEquals('e', reader.read());
assertEquals('s', reader.read());
reader.reset();
assertEquals('e', reader.read());
}

@Test(expected = NullPointerException.class)
public void testReadToNullBuffer() {
CharSequenceReader reader = new CharSequenceReader("test");
reader.read(null, 0, 1);
}

@Test(expected = IndexOutOfBoundsException.class)
public void testNegativeOffset() {
CharSequenceReader reader = new CharSequenceReader("test");
char[] buffer = new char[10];
reader.read(buffer, -1, 5);
}

@Test(expected = IndexOutOfBoundsException.class)
public void testNegativeLength() {
CharSequenceReader reader = new CharSequenceReader("test");
char[] buffer = new char[10];
reader.read(buffer, 0, -5);
}

@Test(expected = IndexOutOfBoundsException.class)
public void testOffsetPlusLengthExceedsBuffer() {
CharSequenceReader reader = new CharSequenceReader("test");
char[] buffer = new char[5];
reader.read(buffer, 3, 3);
}

@Test
public void testCloseDoesNothing() {
CharSequenceReader reader = new CharSequenceReader("test");
reader.close();
assertEquals('t', reader.read());
}

@Test
public void testMarkSupported() {
CharSequenceReader reader = new CharSequenceReader("test");
assertTrue(reader.markSupported());
}
}
Loading