Skip to content

Commit

Permalink
add peekWhile
Browse files Browse the repository at this point in the history
  • Loading branch information
hohwille committed May 22, 2023
1 parent 2be729d commit aee6bc2
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
50 changes: 50 additions & 0 deletions core/src/main/java/io/github/mmm/scanner/CharReaderScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.io.IOException;
import java.io.Reader;

import io.github.mmm.base.filter.CharFilter;
import io.github.mmm.base.text.TextFormatMessageHandler;

/**
Expand Down Expand Up @@ -154,6 +155,47 @@ public String peekString(int count) {
}
}

@Override
public String peekWhile(CharFilter filter, int maxLen) {

if (!hasNext()) {
return "";
}
int rest = this.limit - this.offset;
if (rest > maxLen) {
rest = maxLen;
}
int len = 0;
while (len < rest) {
char c = this.buffer[this.offset + len];
if (!filter.accept(c)) {
return new String(this.buffer, this.offset, len);
}
len++;
}
if (fillLookahead()) {
int fullRest = rest + this.lookaheadLimit;
if ((maxLen > fullRest) && !isEos()) {
throwLookaheadError(maxLen);
}
len = 0;
int end = maxLen - rest;
while (len < end) {
char c = this.lookaheadBuffer[len];
if (!filter.accept(c)) {
break;
}
len++;
}
StringBuilder sb = new StringBuilder(rest + len);
sb.append(this.buffer, this.offset, rest);
sb.append(this.lookaheadBuffer, 0, len);
return sb.toString();
} else {
return new String(this.buffer, this.offset, rest);
}
}

@Override
public String getBufferToParse() {

Expand Down Expand Up @@ -408,4 +450,12 @@ protected boolean expectRestWithLookahead(char[] stopChars, boolean ignoreCase,
return true;
}

@Override
protected void reset() {

super.reset();
this.lookaheadLimit = 0;
this.position = 0;
}

}
28 changes: 28 additions & 0 deletions core/src/main/java/io/github/mmm/scanner/CharSequenceScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,34 @@ public String peekString(int count) {
return result;
}

@Override
public String peekWhile(CharFilter filter, int maxLen) {

if (maxLen < 0) {
throw new IllegalArgumentException("Max must NOT be negative: " + maxLen);
}
int len = 0;
int end = this.offset + maxLen;
if (end < 0) { // overflow?
end = maxLen;
}
if (end > this.limit) {
end = this.limit;
}
while (len < end) {
char c = this.buffer[len];
if (!filter.accept(c)) {
break;
}
len++;
}
if (len == 0) {
return "";
} else {
return new String(this.buffer, this.offset, len);
}
}

@Override
public String readUntil(CharFilter filter, boolean acceptEot) {

Expand Down
11 changes: 11 additions & 0 deletions core/src/main/java/io/github/mmm/scanner/CharStreamScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ public interface CharStreamScanner extends TextFormatProcessor {
*/
String peekString(int count);

/**
* @param filter the {@link CharFilter} {@link CharFilter#accept(char) accepting} only the characters to peek.
* @param maxLen the maximum number of characters to peek (get as lookahead without modifying this stream).
* @return a {@link String} with the {@link #peek() peeked} characters of the given {@code maxLen} or less if a
* character was hit that is <em>not</em> {@link CharFilter#accept(char) accepted} by the given {@code filter}
* or the end-of-text has been reached before. The state of this stream remains unchanged.
* @see #readWhile(CharFilter)
* @see #skip(int)
*/
String peekWhile(CharFilter filter, int maxLen);

/**
* This method reads the number of {@link #next() next characters} given by {@code count} and returns them as string.
* If there are less characters {@link #hasNext() available} the returned string will be shorter than {@code count}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,28 @@ public void testReadWhile() {
assertThat(scanner.getLine()).isEqualTo(1);
}

@Test
public void testPeekWhile() {

// given
String string = "abc def ghi";
CharFilter textFilter = CharFilter.LATIN_LETTER;
CharFilter spaceFilter = CharFilter.WHITESPACE;
// when
CharStreamScanner scanner = scanner(string, 3);
// then
assertThat(scanner.peekWhile(textFilter, 3)).isEqualTo("abc");
scanner.skip(3);
assertThat(scanner.peekWhile(textFilter, 3)).isEmpty();
scanner.skip(1);
assertThat(scanner.peekWhile(textFilter, 3)).isEqualTo("def");
scanner.skip(3);
assertThat(scanner.peekWhile(textFilter, 3)).isEmpty();
scanner.skip(2);
assertThat(scanner.peekWhile(textFilter, 2)).isEqualTo("gh");
assertThat(scanner.peekWhile(textFilter, 3)).isEqualTo("ghi");
}

@Test
public void testReadLine() {

Expand Down

0 comments on commit aee6bc2

Please sign in to comment.