Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#112]Corrected skip methods behavior of JsonParserImpl; #113

Merged
merged 5 commits into from
Feb 26, 2024
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ nbproject/
*err_pid*.log
/tck-impl/.gradle/
/tck-impl/build/
/.sdkmanrc
266 changes: 131 additions & 135 deletions impl/src/main/java/org/eclipse/parsson/JsonParserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.AbstractMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
Expand Down Expand Up @@ -190,25 +191,26 @@ public Stream<JsonValue> getArrayStream() {
}
Spliterator<JsonValue> spliterator =
new Spliterators.AbstractSpliterator<JsonValue>(Long.MAX_VALUE, Spliterator.ORDERED) {
@Override
public Spliterator<JsonValue> trySplit() {
return null;
}
@Override
public boolean tryAdvance(Consumer<? super JsonValue> action) {
if (action == null) {
throw new NullPointerException();
}
if (! hasNext()) {
return false;
}
if (next() == JsonParser.Event.END_ARRAY) {
return false;
}
action.accept(getValue());
return true;
}
};
@Override
public Spliterator<JsonValue> trySplit() {
return null;
}

@Override
public boolean tryAdvance(Consumer<? super JsonValue> action) {
if (action == null) {
throw new NullPointerException();
}
if (!hasNext()) {
return false;
}
if (next() == JsonParser.Event.END_ARRAY) {
return false;
}
action.accept(getValue());
return true;
}
};
return StreamSupport.stream(spliterator, false);
}

Expand All @@ -220,35 +222,36 @@ public Stream<Map.Entry<String, JsonValue>> getObjectStream() {
}
Spliterator<Map.Entry<String, JsonValue>> spliterator =
new Spliterators.AbstractSpliterator<Map.Entry<String, JsonValue>>(Long.MAX_VALUE, Spliterator.ORDERED) {
@Override
public Spliterator<Map.Entry<String,JsonValue>> trySplit() {
return null;
}
@Override
public boolean tryAdvance(Consumer<? super Map.Entry<String, JsonValue>> action) {
if (action == null) {
throw new NullPointerException();
}
if (! hasNext()) {
return false;
}
JsonParser.Event e = next();
if (e == JsonParser.Event.END_OBJECT) {
return false;
}
if (e != JsonParser.Event.KEY_NAME) {
throw new JsonException(JsonMessages.INTERNAL_ERROR());
}
String key = getString();
if (! hasNext()) {
throw new JsonException(JsonMessages.INTERNAL_ERROR());
}
next();
JsonValue value = getValue();
action.accept(new AbstractMap.SimpleImmutableEntry<>(key, value));
return true;
}
};
@Override
public Spliterator<Map.Entry<String, JsonValue>> trySplit() {
return null;
}

@Override
public boolean tryAdvance(Consumer<? super Map.Entry<String, JsonValue>> action) {
if (action == null) {
throw new NullPointerException();
}
if (!hasNext()) {
return false;
}
JsonParser.Event e = next();
if (e == JsonParser.Event.END_OBJECT) {
return false;
}
if (e != JsonParser.Event.KEY_NAME) {
throw new JsonException(JsonMessages.INTERNAL_ERROR());
}
String key = getString();
if (!hasNext()) {
throw new JsonException(JsonMessages.INTERNAL_ERROR());
}
next();
JsonValue value = getValue();
action.accept(new AbstractMap.SimpleImmutableEntry<>(key, value));
return true;
}
};
return StreamSupport.stream(spliterator, false);
}

Expand All @@ -260,29 +263,30 @@ public Stream<JsonValue> getValueStream() {
}
Spliterator<JsonValue> spliterator =
new Spliterators.AbstractSpliterator<JsonValue>(Long.MAX_VALUE, Spliterator.ORDERED) {
@Override
public Spliterator<JsonValue> trySplit() {
return null;
}
@Override
public boolean tryAdvance(Consumer<? super JsonValue> action) {
if (action == null) {
throw new NullPointerException();
}
if (! hasNext()) {
return false;
}
next();
action.accept(getValue());
return true;
}
};
@Override
public Spliterator<JsonValue> trySplit() {
return null;
}

@Override
public boolean tryAdvance(Consumer<? super JsonValue> action) {
if (action == null) {
throw new NullPointerException();
}
if (!hasNext()) {
return false;
}
next();
action.accept(getValue());
return true;
}
};
return StreamSupport.stream(spliterator, false);
}

@Override
public void skipArray() {
if (currentEvent == Event.START_ARRAY) {
if (currentContext instanceof ArrayContext) {
currentContext.skip();
currentContext = stack.pop();
currentEvent = Event.END_ARRAY;
Expand All @@ -291,7 +295,7 @@ public void skipArray() {

@Override
public void skipObject() {
if (currentEvent == Event.START_OBJECT) {
if (currentContext instanceof ObjectContext) {
currentContext.skip();
currentContext = stack.pop();
currentEvent = Event.END_OBJECT;
Expand Down Expand Up @@ -418,27 +422,35 @@ private boolean isEmpty() {
}
}

private abstract static class Context {
private abstract class Context {
Context next;
abstract Event getNextEvent();
abstract void skip();
}

private final class NoneContext extends Context {
@Override
public Event getNextEvent() {
// Handle 1. { 2. [ 3. value
JsonToken token = tokenizer.nextToken();
if (token == JsonToken.CURLYOPEN) {
protected Event nextEventIfValueOrObjectOrArrayStart(JsonToken token) {
if (token.isValue()) {
return token.getEvent();
} else if (token == JsonToken.CURLYOPEN) {
stack.push(currentContext);
currentContext = new ObjectContext();
return Event.START_OBJECT;
} else if (token == JsonToken.SQUAREOPEN) {
stack.push(currentContext);
currentContext = new ArrayContext();
return Event.START_ARRAY;
} else if (token.isValue()) {
return token.getEvent();
}
return null;
}
}

private final class NoneContext extends Context {
@Override
public Event getNextEvent() {
// Handle 1. { 2. [ 3. value
JsonToken token = tokenizer.nextToken();
Event event = nextEventIfValueOrObjectOrArrayStart(token);
if (event != null) {
return event;
}
throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]");
}
Expand All @@ -455,9 +467,38 @@ private JsonParsingException parsingException(JsonToken token, String expectedTo
JsonMessages.PARSER_INVALID_TOKEN(token, location, expectedTokens), location);
}

private final class ObjectContext extends Context {
private abstract class SkippingContext extends Context {
private final JsonToken openToken;
private final JsonToken closeToken;

private SkippingContext(JsonToken openToken, JsonToken closeToken) {
this.openToken = Objects.requireNonNull(openToken);
this.closeToken = Objects.requireNonNull(closeToken);
}

@Override
void skip() {
JsonToken token;
int depth = 1;
do {
token = tokenizer.nextToken();
if (token == closeToken) {
depth--;
}
if (token == openToken) {
depth++;
}
} while (!(token == closeToken && depth == 0));
}
}

private final class ObjectContext extends SkippingContext {
private boolean firstValue = true;

private ObjectContext() {
super(JsonToken.CURLYOPEN, JsonToken.CURLYCLOSE);
}

/*
* Some more things could be optimized. For example, instead
* tokenizer.nextToken(), one could use tokenizer.matchColonToken() to
Expand All @@ -484,16 +525,9 @@ public Event getNextEvent() {
throw parsingException(token, "[COLON]");
}
token = tokenizer.nextToken();
if (token.isValue()) {
return token.getEvent();
} else if (token == JsonToken.CURLYOPEN) {
stack.push(currentContext);
currentContext = new ObjectContext();
return Event.START_OBJECT;
} else if (token == JsonToken.SQUAREOPEN) {
stack.push(currentContext);
currentContext = new ArrayContext();
return Event.START_ARRAY;
Event event = nextEventIfValueOrObjectOrArrayStart(token);
if (event != null) {
return event;
}
throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]");
} else {
Expand All @@ -516,29 +550,15 @@ public Event getNextEvent() {
throw parsingException(token, "[STRING]");
}
}

@Override
void skip() {
JsonToken token;
int depth = 1;
do {
token = tokenizer.nextToken();
switch (token) {
case CURLYCLOSE:
depth--;
break;
case CURLYOPEN:
depth++;
break;
}
} while (!(token == JsonToken.CURLYCLOSE && depth == 0));
}

}

private final class ArrayContext extends Context {
private final class ArrayContext extends SkippingContext {
private boolean firstValue = true;

private ArrayContext() {
super(JsonToken.SQUAREOPEN, JsonToken.SQUARECLOSE);
}

// Handle 1. ] 2. value 3. ,value
@Override
public Event getNextEvent() {
Expand All @@ -563,36 +583,12 @@ public Event getNextEvent() {
}
token = tokenizer.nextToken();
}
if (token.isValue()) {
return token.getEvent();
} else if (token == JsonToken.CURLYOPEN) {
stack.push(currentContext);
currentContext = new ObjectContext();
return Event.START_OBJECT;
} else if (token == JsonToken.SQUAREOPEN) {
stack.push(currentContext);
currentContext = new ArrayContext();
return Event.START_ARRAY;

Event event = nextEventIfValueOrObjectOrArrayStart(token);
if (event != null) {
return event;
}
throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]");
}

@Override
void skip() {
JsonToken token;
int depth = 1;
do {
token = tokenizer.nextToken();
switch (token) {
case SQUARECLOSE:
depth--;
break;
case SQUAREOPEN:
depth++;
break;
}
} while (!(token == JsonToken.SQUARECLOSE && depth == 0));
}
}

}
Loading