com.sangupta.jerry.io.AdvancedStringReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jerry-core Show documentation
Show all versions of jerry-core Show documentation
Common Java functionality for core functionality
The newest version!
/**
*
* jerry - Common Java Functionality
* Copyright (c) 2012-2017, Sandeep Gupta
*
* http://sangupta.com/projects/jerry-core
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sangupta.jerry.io;
/**
* A class that allows reading a {@link String} via simple tokens.
*
* @author sangupta
*
*/
public class AdvancedStringReader {
/**
* The string that we are working on. Can be null
.
*/
private final String str;
/**
* The length of the string we are working on. If the {@link #str} is
* null
, the value will be -1
.
*/
private final int length;
/**
* The pointer in the string from where next read will happen
*/
private int current = 0;
/**
* Create a new instance of {@link AdvancedStringReader}.
*
* @param str the string to operate upon
*
*/
public AdvancedStringReader(String str) {
if(str == null) {
this.str = null;
this.length = -1;
return;
}
this.str = str;
this.length = str.length();
}
/**
* Check if the reader has more tokens that you can read.
*
* @return true
if there are more characters that can be read,
* false
otherwise
*/
public boolean hasNext() {
return this.current < this.length;
}
/**
* Read the string from current position to the next occurrence of the given
* character.
*
* @param separator
* the character till which we are going to read
*
* @return the sub-string thus extracted
*/
public String readTillNext(char separator) {
return this.readTillNext(String.valueOf(separator), 1);
}
/**
* Read the character at the current position but do not move ahead.
*
* @return the next available character
*/
public char peekAhead() {
return this.peekAhead(0);
}
/**
* Look ahead in the string a given number of characters.
*
* @param ahead
* the position from current to look ahead
*
* @return the character at the position
*/
public char peekAhead(int ahead) {
int pos = this.current + ahead;
if(pos > this.length) {
return ((char) -1);
}
return this.str.charAt(pos);
}
/**
* Read the string from current position to the given number of characters
* ahead.
*
* @param ahead
* the number of position to read ahead
*
* @return the {@link String} representation of the characters thus read
*/
public String readTillPosition(int ahead) {
int pos = this.current + ahead;
if(pos > this.length) {
pos = this.length;
}
String result = this.str.substring(this.current, pos);
this.current = pos;
return result;
}
/**
* Read the string from current position to the next nth occurrence of the
* given character.
*
* @param separator
* the character till which we are going to read
*
* @param occurence
* the times the character will be included before we stop
* further reading
*
* @return the sub-string thus extracted
*/
public String readTillNext(char separator, int occurence) {
return this.readTillNext(String.valueOf(separator), occurence);
}
/**
* Peek the next available position of the given character from the current
* position.
*
* @param c
* the character to look ahead
*
* @return the index if found, or -1
*/
public int peekIndex(char c) {
for(int index = this.current; index < this.length; index++) {
if(this.str.charAt(index) == c) {
return index - this.current;
}
}
return -1;
}
/**
* Read ahead till we encounter the given separator or there are no more
* tokens in the queue.
*
* @param separator
* the separator being looked at
*
* @return the {@link String} thus read
*/
public String readTillNext(String separator) {
return this.readTillNext(separator, 1);
}
/**
* Read ahead till the next given occurrence of the given separator or if
* there are no more tokens in the queue.
*
* @param separator
* the separator being looked at
*
* @param occurence
* the occurrence to find
*
* @return the {@link String} thus read
*
*/
public String readTillNext(String separator, int occurence) {
if(!this.hasNext()) {
return null;
}
int numFound = 0;
int index = -1;
int searchFrom = this.current;
do {
index = this.str.indexOf(separator, searchFrom);
if(index < 0) {
int start = this.current;
this.current = str.length();
return this.str.substring(start);
}
numFound++;
if(numFound == occurence) {
break;
}
searchFrom = index + 1;
} while(true);
String extracted = this.str.substring(this.current, index);
this.current = index + separator.length();
return extracted;
}
/**
* Read the entire remaining string in this reader.
*
* @return the remaining sub-string, null
if there are no more
* tokens to be read
*/
public String readRemaining() {
if(!this.hasNext()) {
return null;
}
return this.str.substring(this.current);
}
/**
* Skip reading next N characters
*
* @param numCharacters
* the number of characters to skip reading.
*
* @return the number of characters actually skipped.
*/
public int skipNext(int numCharacters) {
if(!this.hasNext()) {
return 0;
}
int end = this.current + numCharacters;
if (end > this.length) {
end = this.length;
}
int skipped = end - this.current;
this.current = end;
return skipped;
}
/**
* Read string from current position to number of characters ahead.
*
* @param numCharacters
* the number of characters to read
*
* @return the {@link String} thus read
*/
public String readNext(int numCharacters) {
if(!this.hasNext()) {
return null;
}
int end = this.current + numCharacters;
if(end > this.length) {
end = this.length;
}
String result = this.str.substring(this.current, end);
this.current = end;
return result;
}
public String readAfter(char character) {
if(!this.hasNext()) {
return null;
}
int index;
for(index = this.current; index < this.length; index++) {
if(this.str.charAt(index) == character) {
break;
}
}
index++;
this.current = this.length;
return this.str.substring(index);
}
public String readFrom(char character) {
if(!this.hasNext()) {
return null;
}
int index;
for(index = this.current; index < this.length; index++) {
if(this.str.charAt(index) == character) {
break;
}
}
this.current = this.length;
return this.str.substring(index);
}
public String peekNext(int numCharacters) {
if(!this.hasNext()) {
return null;
}
int end = this.current + numCharacters;
if(end > this.length) {
end = this.length;
}
return this.str.substring(this.current, end);
}
/**
* Read the string between the first occurrence of starting character, and
* the next subsequent occurrence of the closing character. If the starting
* character cannot be found, will return null
. If the starting
* character is found, but closing character cannot be found, will return
* the entire string after and including the starting character.
*
* @param starting
* the character to start reading from
*
* @param closing
* the character to stop reading at
*
* @return the sub-string thus extracted, or null
if there are
* no more characters remaining.
*/
public String readBetween(char starting, char closing) {
if(!this.hasNext()) {
return null;
}
if(starting == closing) {
// this is a special case
// find the two indexes
int start = this.str.indexOf(starting, this.current);
if(start == -1) {
return null;
}
start++;
int end = this.str.indexOf(closing, start + 1);
if(end == -1) {
end = this.length;
}
this.current = end + 1;
return this.str.substring(start, end);
}
int count = 0;
int start = -1;
boolean found = false;
for(int index = this.current; index < this.length; index++) {
char c = this.str.charAt(index);
if(c == starting) {
if(!found) {
start = index;
}
count++;
found = true;
continue;
}
if(c == closing) {
count--;
found = true;
if(found && count == 0) {
this.current = index + 1;
return this.str.substring(start + 1, index);
}
}
}
return null;
}
/**
* Peek the first non-white-space character available. The {@link #current}
* pointer is not moved ahead.
*
* @return the first non-white-space character available to read next.
*/
public char peekNextNonWhitespace() {
int start = this.current;
do {
if(start >= this.length) {
return 0;
}
char c = this.str.charAt(start);
if(Character.isWhitespace(c)) {
start++;
continue;
}
return c;
} while(true);
}
/**
* Skip all whitespace characters that follow the {@link #current} reading
* position.
*
* @return the number of characters skipped
*/
public int skipWhiteSpace() {
int count = 0;
do {
if(this.current >= this.length) {
return count;
}
char c = this.str.charAt(this.current);
if(Character.isWhitespace(c)) {
this.current++;
count++;
continue;
}
return count;
} while(true);
}
/**
* Reset the reading position to the start of the actual string. This sets the
* {@link #current} pointer back to zero.
*/
public void reset() {
this.current = 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy