diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java b/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java index b93811c3..1aa28679 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java +++ b/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; + } } \ No newline at end of file diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java index e5eb39a3..67b512e4 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java +++ b/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() { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java index f83e953a..12e18798 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java @@ -45,9 +45,13 @@ public class PathCompiler { private final LinkedList filterStack; private final CharacterIndex path; - private PathCompiler(String path, LinkedList filterStack) { + private PathCompiler(String path, LinkedList filterStack){ + this(new CharacterIndex(path), filterStack); + } + + private PathCompiler(CharacterIndex path, LinkedList 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(asList(filters)); - Path p = new PathCompiler(path.trim(), filterStack).compile(); + LinkedList filterStack = new LinkedList(asList(filters)); + Path p = new PathCompiler(ci, filterStack).compile(); return p; } catch (Exception e) { InvalidPathException ipe;