Browse Source

Merge pull request #327 from jochenberger/speed-up-filter-compiler

avoid some costly calls to String#trim()
pull/328/head
kallestenflo 8 years ago committed by GitHub
parent
commit
e7a6e77435
  1. 36
      json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java
  2. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java
  3. 22
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java

36
json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java

@ -17,14 +17,16 @@ public class CharacterIndex {
private final CharSequence charSequence;
private int position;
private int endPosition;
public CharacterIndex(CharSequence charSequence) {
this.charSequence = charSequence;
this.position = 0;
this.endPosition = charSequence.length() - 1;
}
public int length() {
return charSequence.length();
return endPosition + 1;
}
public char charAt(int idx) {
@ -39,6 +41,10 @@ public class CharacterIndex {
return (charSequence.charAt(position) == c);
}
public boolean lastCharIs(char c) {
return charSequence.charAt(endPosition) == c;
}
public boolean nextCharIs(char c) {
return inBounds(position + 1) && (charSequence.charAt(position + 1) == c);
}
@ -47,12 +53,21 @@ public class CharacterIndex {
return setPosition(position + charCount);
}
public int decrementEndPosition(int charCount) {
return setEndPosition(endPosition - charCount);
}
public int setPosition(int newPosition) {
//position = min(newPosition, charSequence.length() - 1);
position = newPosition;
return position;
}
private int setEndPosition(int newPosition) {
endPosition = newPosition;
return endPosition;
}
public int position(){
return position;
}
@ -244,7 +259,7 @@ public class CharacterIndex {
}
public boolean currentIsTail() {
return position >= charSequence.length()-1;
return position >= endPosition;
}
public boolean hasMoreCharacters() {
@ -252,7 +267,7 @@ public class CharacterIndex {
}
public boolean inBounds(int idx) {
return (idx >= 0) && (idx < charSequence.length());
return (idx >= 0) && (idx <= endPosition);
}
public boolean inBounds() {
return inBounds(position);
@ -281,9 +296,22 @@ public class CharacterIndex {
}
public CharacterIndex skipBlanks() {
while (inBounds() && currentChar() == SPACE){
while (inBounds() && position < endPosition && currentChar() == SPACE){
incrementPosition(1);
}
return this;
}
private CharacterIndex skipBlanksAtEnd() {
while (inBounds() && position < endPosition && lastCharIs(SPACE)){
decrementEndPosition(1);
}
return this;
}
public CharacterIndex trim() {
skipBlanks();
skipBlanksAtEnd();
return this;
}
}

18
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java

@ -54,20 +54,22 @@ public class FilterCompiler {
}
private FilterCompiler(String filterString) {
filterString = filterString.trim();
if (!filterString.startsWith("[") || !filterString.endsWith("]")) {
filter = new CharacterIndex(filterString);
filter.trim();
if (!filter.currentCharIs('[') || !filter.lastCharIs(']')) {
throw new InvalidPathException("Filter must start with '[' and end with ']'. " + filterString);
}
filterString = filterString.substring(1, filterString.length() - 1).trim();
if (!filterString.startsWith("?")) {
filter.incrementPosition(1);
filter.decrementEndPosition(1);
filter.trim();
if (!filter.currentCharIs('?')) {
throw new InvalidPathException("Filter must start with '[?' and end with ']'. " + filterString);
}
filterString = filterString.substring(1).trim();
if (!filterString.startsWith("(") || !filterString.endsWith(")")) {
filter.incrementPosition(1);
filter.trim();
if (!filter.currentCharIs('(') || !filter.lastCharIs(')')) {
throw new InvalidPathException("Filter must start with '[?(' and end with ')]'. " + filterString);
}
filter = new CharacterIndex(filterString);
}
public Predicate compile() {

22
json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java

@ -45,9 +45,13 @@ public class PathCompiler {
private final LinkedList<Predicate> filterStack;
private final CharacterIndex path;
private PathCompiler(String path, LinkedList<Predicate> filterStack) {
private PathCompiler(String path, LinkedList<Predicate> filterStack){
this(new CharacterIndex(path), filterStack);
}
private PathCompiler(CharacterIndex path, LinkedList<Predicate> filterStack){
this.filterStack = filterStack;
this.path = new CharacterIndex(path);
this.path = path;
}
private Path compile() {
@ -57,16 +61,18 @@ public class PathCompiler {
public static Path compile(String path, final Predicate... filters) {
try {
path = path.trim();
CharacterIndex ci = new CharacterIndex(path);
ci.trim();
if(!(path.charAt(0) == DOC_CONTEXT) && !(path.charAt(0) == EVAL_CONTEXT)){
path = "$." + path;
if(!( ci.charAt(0) == DOC_CONTEXT) && !( ci.charAt(0) == EVAL_CONTEXT)){
ci = new CharacterIndex("$." + path);
ci.trim();
}
if(path.endsWith(".")){
if(ci.lastCharIs('.')){
fail("Path must not end with a '.' or '..'");
}
LinkedList filterStack = new LinkedList<Predicate>(asList(filters));
Path p = new PathCompiler(path.trim(), filterStack).compile();
LinkedList<Predicate> filterStack = new LinkedList<Predicate>(asList(filters));
Path p = new PathCompiler(ci, filterStack).compile();
return p;
} catch (Exception e) {
InvalidPathException ipe;

Loading…
Cancel
Save