Skip to content

Commit

Permalink
small improvement (min,max)
Browse files Browse the repository at this point in the history
  • Loading branch information
hohwille committed Dec 25, 2023
1 parent b857099 commit ecb9a47
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1417,11 +1417,14 @@ public boolean skipOver(String substring, boolean ignoreCase, CharFilter stopFil
}

@Override
public String readWhile(CharFilter filter, int max) {
public String readWhile(CharFilter filter, int min, int max) {

if (max < 0) {
throw new IllegalArgumentException("Max must NOT be negative: " + max);
}
if (max < min) {
throw new IllegalArgumentException("Min (" + min + ") must be less or requal to max (" + max + ")");
}
StringBuilder builder = null;
if (this.offset >= this.limit) {
fill();
Expand All @@ -1439,7 +1442,7 @@ public String readWhile(CharFilter filter, int max) {
while (this.offset < end) {
char c = this.buffer[this.offset];
if (!filter.accept(c)) {
return getAppended(builder, start, this.offset);
return requireMin(getAppended(builder, start, this.offset), min, filter);
}
handleChar(c);
this.offset++;
Expand All @@ -1448,11 +1451,30 @@ public String readWhile(CharFilter filter, int max) {
remain -= len;
builder = append(builder, start, this.offset);
if ((remain == 0) || !fill()) {
return eot(builder, true);
return requireMin(eot(builder, true), min, filter);
}
}
}

/**
* @param actual the actual number of characters.
* @param min the minimum number of characters required.
* @param filter the {@link CharFilter} that was used.
*/
protected void requireMin(int actual, int min, CharFilter filter) {

if (actual < min) {
throw new IllegalStateException(
"Required at least " + min + " character(s) (" + filter.getDescription() + ") but found only " + actual);
}
}

private String requireMin(String result, int min, CharFilter filter) {

requireMin(result.length(), min, filter);
return result;
}

/**
* @return the {@link String} with the characters that have already been parsed but are still available in the
* underlying buffer. May be used for debugging or error messages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ public void require(String expected, boolean ignoreCase) {
}

@Override
public String readWhile(CharFilter filter, int max) {
public String readWhile(CharFilter filter, int min, int max) {

int currentPos = this.offset;
int len = skipWhile(filter, max);
Expand Down
24 changes: 15 additions & 9 deletions core/src/main/java/io/github/mmm/scanner/CharStreamScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -305,17 +305,20 @@ default String readUntil(CharFilter filter, boolean acceptEnd, String stop, bool
/**
* @param stopFilter the {@link CharFilter} that decides which characters to {@link CharFilter#accept(char) accept} as
* stop characters.
* @param maxLength the (maximum) length of the characters to consume.
* @param min the minimum number of characters expected.
* @param max the (maximum) length of the characters to consume.
* @return the {@link String} with all consumed characters excluding the stop character. If no {@code stop} character
* was found until {@code maxLength} characters have been consumed, this method behaves like {@link #read(int)
* read(maxLength)}.
* @throws IllegalStateException if less than the minimum number of characters have been
* {@link CharFilter#accept(char) rejected}.
* @see #read(int)
* @see #readWhile(CharFilter, int)
* @see #readWhile(CharFilter, int, int)
* @see #peekUntil(CharFilter, int)
*/
default String readUntil(CharFilter stopFilter, int maxLength) {
default String readUntil(CharFilter stopFilter, int min, int max) {

return readWhile(stopFilter.negate(), maxLength);
return readWhile(stopFilter.negate(), min, max);
}

/**
Expand All @@ -326,13 +329,13 @@ default String readUntil(CharFilter stopFilter, int maxLength) {
*
* @see #skipWhile(CharFilter)
*
* @param filter is used to {@link CharFilter#accept(char) decide} which characters should be accepted.
* @param filter used to {@link CharFilter#accept(char) decide} which characters should be accepted.
* @return a string with all characters {@link CharFilter#accept(char) accepted} by the given {@code filter}. Will be
* the empty string if no character was accepted.
*/
default String readWhile(CharFilter filter) {

return readWhile(filter, Integer.MAX_VALUE);
return readWhile(filter, 0, Integer.MAX_VALUE);
}

/**
Expand All @@ -345,13 +348,16 @@ default String readWhile(CharFilter filter) {
*
* @see #skipWhile(char)
*
* @param filter is used to {@link CharFilter#accept(char) decide} which characters should be accepted.
* @param max is the maximum number of characters that should be read.
* @param filter used to {@link CharFilter#accept(char) decide} which characters should be accepted.
* @param min the minimum number of characters expected.
* @param max the maximum number of characters that should be read.
* @return a string with all characters {@link CharFilter#accept(char) accepted} by the given {@code filter} limited
* to the length of {@code max} and the {@link #hasNext() end} of this scanner. Will be the empty string if no
* character was accepted.
* @throws IllegalStateException if less than the minimum number of characters have been
* {@link CharFilter#accept(char) accepted}.
*/
String readWhile(CharFilter filter, int max);
String readWhile(CharFilter filter, int min, int max);

/**
* @return a {@link String} with the data until the end of the current line or the end of the data. Will be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,12 +712,12 @@ public void testReadWhile() {
// then
assertThat(scanner.readWhile(textFilter)).isEqualTo("abc");
assertThat(scanner.readWhile(textFilter)).isEmpty();
assertThat(scanner.readWhile(textFilter, 0)).isEmpty();
assertThat(scanner.readWhile(textFilter, 0, 0)).isEmpty();
assertThat(scanner.readWhile(spaceFilter)).isEqualTo(" ");
assertThat(scanner.readWhile(textFilter)).isEqualTo("def");
assertThat(scanner.readWhile(spaceFilter)).isEqualTo(" ");
assertThat(scanner.readWhile(textFilter, 2)).isEqualTo("gh");
assertThat(scanner.readWhile(textFilter, 2)).isEqualTo("i");
assertThat(scanner.readWhile(textFilter, 0, 2)).isEqualTo("gh");
assertThat(scanner.readWhile(textFilter, 0, 2)).isEqualTo("i");
assertThat(scanner.hasNext()).isFalse();
assertThat(scanner.getPosition()).isEqualTo(12);
assertThat(scanner.getColumn()).isEqualTo(13);
Expand Down

0 comments on commit ecb9a47

Please sign in to comment.