You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
8.3 KiB
280 lines
8.3 KiB
package com.jayway.jsonpath.internal; |
|
|
|
import com.jayway.jsonpath.InvalidPathException; |
|
|
|
public class CharacterIndex { |
|
|
|
private static final char OPEN_BRACKET = '('; |
|
private static final char CLOSE_BRACKET = ')'; |
|
private static final char CLOSE_SQUARE_BRACKET = ']'; |
|
private static final char SPACE = ' '; |
|
private static final char ESCAPE = '\\'; |
|
private static final char TICK = '\''; |
|
private static final char MINUS = '-'; |
|
private static final char PERIOD = '.'; |
|
private static final char REGEX = '/'; |
|
|
|
private final CharSequence charSequence; |
|
private int position; |
|
|
|
public CharacterIndex(CharSequence charSequence) { |
|
this.charSequence = charSequence; |
|
this.position = 0; |
|
} |
|
|
|
public int length() { |
|
return charSequence.length(); |
|
} |
|
|
|
public char charAt(int idx) { |
|
return charSequence.charAt(idx); |
|
} |
|
|
|
public char currentChar() { |
|
return charSequence.charAt(position); |
|
} |
|
|
|
public boolean currentCharIs(char c) { |
|
return (charSequence.charAt(position) == c); |
|
} |
|
|
|
public boolean nextCharIs(char c) { |
|
return inBounds(position + 1) && (charSequence.charAt(position + 1) == c); |
|
} |
|
|
|
public int incrementPosition(int charCount) { |
|
return setPosition(position + charCount); |
|
} |
|
|
|
public int setPosition(int newPosition) { |
|
//position = min(newPosition, charSequence.length() - 1); |
|
position = newPosition; |
|
return position; |
|
} |
|
|
|
public int position(){ |
|
return position; |
|
} |
|
|
|
public int indexOfClosingSquareBracket(int startPosition) { |
|
int readPosition = startPosition; |
|
while (inBounds(readPosition)) { |
|
if(charAt(readPosition) == CLOSE_SQUARE_BRACKET){ |
|
return readPosition; |
|
} |
|
readPosition++; |
|
} |
|
return -1; |
|
} |
|
public int indexOfMatchingCloseChar(int startPosition, char openChar, char closeChar, boolean skipStrings, boolean skipRegex) { |
|
if(charAt(startPosition) != openChar){ |
|
throw new InvalidPathException("Expected " + openChar + " but found " + charAt(startPosition)); |
|
} |
|
|
|
int opened = 1; |
|
int readPosition = startPosition + 1; |
|
while (inBounds(readPosition)) { |
|
if (skipStrings) { |
|
if (charAt(readPosition) == TICK) { |
|
boolean escaped = false; |
|
while (inBounds(readPosition)) { |
|
readPosition++; |
|
if (escaped) { |
|
escaped = false; |
|
continue; |
|
} |
|
if (charAt(readPosition) == ESCAPE) { |
|
escaped = true; |
|
continue; |
|
} |
|
if (charAt(readPosition) == TICK) { |
|
readPosition++; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
if (skipRegex) { |
|
if (charAt(readPosition) == REGEX) { |
|
while (inBounds(readPosition)) { |
|
readPosition++; |
|
if (charAt(readPosition) == REGEX) { |
|
readPosition++; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
if (charAt(readPosition) == openChar) { |
|
opened++; |
|
} |
|
if (charAt(readPosition) == closeChar) { |
|
opened--; |
|
if (opened == 0) { |
|
return readPosition; |
|
} |
|
} |
|
readPosition++; |
|
} |
|
return -1; |
|
} |
|
public int indexOfClosingBracket(int startPosition, boolean skipStrings, boolean skipRegex) { |
|
return indexOfMatchingCloseChar(startPosition, OPEN_BRACKET, CLOSE_BRACKET, skipStrings, skipRegex); |
|
} |
|
|
|
public int indexOfNextSignificantChar(char c) { |
|
return indexOfNextSignificantChar(position, c); |
|
} |
|
|
|
public int indexOfNextSignificantChar(int startPosition, char c) { |
|
int readPosition = startPosition + 1; |
|
while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) { |
|
readPosition++; |
|
} |
|
if (charAt(readPosition) == c) { |
|
return readPosition; |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
public int nextIndexOf(char c) { |
|
return nextIndexOf(position + 1, c); |
|
} |
|
|
|
public int nextIndexOf(int startPosition, char c) { |
|
int readPosition = startPosition; |
|
while (!isOutOfBounds(readPosition)) { |
|
if (charAt(readPosition) == c) { |
|
return readPosition; |
|
} |
|
readPosition++; |
|
} |
|
return -1; |
|
} |
|
|
|
public int nextIndexOfUnescaped(char c) { |
|
return nextIndexOfUnescaped(position + 1, c); |
|
} |
|
|
|
public int nextIndexOfUnescaped(int startPosition, char c) { |
|
int readPosition = startPosition; |
|
char prev1; |
|
char prev2; |
|
while (!isOutOfBounds(readPosition)) { |
|
prev1 = charAtOr(readPosition - 1, ' '); |
|
prev2 = charAtOr(readPosition - 2, ' '); |
|
boolean ignore = (prev1 == '\\' && prev2 == '\\'); |
|
boolean escaped = (prev1 == '\\' && !ignore); |
|
|
|
if (charAt(readPosition) == c && !escaped) { |
|
return readPosition; |
|
} |
|
readPosition++; |
|
} |
|
return -1; |
|
} |
|
|
|
public char charAtOr(int postition, char defaultChar){ |
|
if(!inBounds(postition)) return defaultChar; |
|
else return charAt(postition); |
|
} |
|
|
|
public boolean nextSignificantCharIs(int startPosition, char c) { |
|
int readPosition = startPosition + 1; |
|
while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) { |
|
readPosition++; |
|
} |
|
return !isOutOfBounds(readPosition) && charAt(readPosition) == c; |
|
} |
|
|
|
public boolean nextSignificantCharIs(char c) { |
|
return nextSignificantCharIs(position, c); |
|
} |
|
|
|
public char nextSignificantChar() { |
|
return nextSignificantChar(position); |
|
} |
|
|
|
public char nextSignificantChar(int startPosition) { |
|
int readPosition = startPosition + 1; |
|
while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) { |
|
readPosition++; |
|
} |
|
if (!isOutOfBounds(readPosition)) { |
|
return charAt(readPosition); |
|
} else { |
|
return ' '; |
|
} |
|
} |
|
|
|
public int indexOfPreviousSignificantChar(int startPosition){ |
|
int readPosition = startPosition - 1; |
|
while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) { |
|
readPosition--; |
|
} |
|
if (!isOutOfBounds(readPosition)) { |
|
return readPosition; |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
public int indexOfPreviousSignificantChar(){ |
|
return indexOfPreviousSignificantChar(position); |
|
} |
|
|
|
public char previousSignificantChar(int startPosition) { |
|
int previousSignificantCharIndex = indexOfPreviousSignificantChar(startPosition); |
|
if(previousSignificantCharIndex == -1) return ' '; |
|
else return charAt(previousSignificantCharIndex); |
|
} |
|
|
|
public char previousSignificantChar() { |
|
return previousSignificantChar(position); |
|
} |
|
|
|
public boolean currentIsTail() { |
|
return isOutOfBounds(position + 1); |
|
} |
|
|
|
public boolean hasMoreCharacters() { |
|
return inBounds(position + 1); |
|
} |
|
|
|
public boolean inBounds(int idx) { |
|
return (idx >= 0) && (idx < charSequence.length()); |
|
} |
|
public boolean inBounds() { |
|
return inBounds(position); |
|
} |
|
|
|
public boolean isOutOfBounds(int idx) { |
|
return !inBounds(idx); |
|
} |
|
|
|
public CharSequence subSequence(int start, int end) { |
|
return charSequence.subSequence(start, end); |
|
} |
|
|
|
public CharSequence charSequence() { |
|
return charSequence; |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
return charSequence.toString(); |
|
} |
|
|
|
public boolean isNumberCharacter(int readPosition) { |
|
char c = charAt(readPosition); |
|
return Character.isDigit(c) || c == MINUS || c == PERIOD; |
|
} |
|
|
|
public CharacterIndex skipBlanks() { |
|
while (inBounds() && currentChar() == SPACE){ |
|
incrementPosition(1); |
|
} |
|
return this; |
|
} |
|
} |