package de.westnordost.streetcomplete.data.osm.tql; /** Convenience class to make it easier to go step by step through a string */ public class StringWithCursor { private String string; private int cursor = 0; public StringWithCursor(String string) { this.string = string; } /** Advances the cursor if str is the next thing at the cursor * @return whether the next string was the str */ public boolean nextIsAndAdvance(String str) { if(!nextIs(str)) return false; advanceBy(str.length()); return true; } public boolean nextIsAndAdvance(char c) { if(!nextIs(c)) return false; advance(); return true; } /** Advances the cursor if str or str.toUpperCase() is the next thing at the cursor * @return whether the next string was the str or str.toUpperCase */ public boolean nextIsAndAdvanceIgnoreCase(String str) { if(!nextIsIgnoreCase(str)) return false; advanceBy(str.length()); return true; } /** @return whether the cursor reached the end */ public boolean isAtEnd() { return cursor >= string.length(); } public boolean isAtEnd(int x) { return cursor + x >= string.length(); } public int findNext(String str) { return toDelta(string.indexOf(str, cursor)); } public int findNext(char c) { return findNext(c, 0); } public int findNext(char c, int offs) { return toDelta(string.indexOf(c, cursor + offs)); } public int getCursorPos() { return cursor; } /** Advance cursor by one and return the character that was at that position * @throws IndexOutOfBoundsException if cursor is already at the end */ public char advance() { char result = string.charAt(cursor); cursor = Math.min(string.length(), cursor + 1); return result; } /** Advance cursor by x and return the string that inbetween the two positions. * If cursor+x is beyond the end of the string, the method will just return the string until * the end of the string * @throws IndexOutOfBoundsException if x < 0 */ public String advanceBy(int x) { int end = cursor + x; String result; if(string.length() < end) { result = string.substring(cursor); cursor = string.length(); } else { result = string.substring(cursor, end); cursor = end; } return result; } private Character getChar() { if(cursor >= string.length()) return null; return string.charAt(cursor); } public boolean previousIs(char c) { return c == string.charAt(cursor-1); } public boolean nextIs(char c) { return getChar() != null && c == getChar(); } public boolean nextIs(String str) { return string.startsWith(str, cursor); } public boolean nextIsIgnoreCase(String str) { return nextIs(str.toLowerCase()) || nextIs(str.toUpperCase()); } private int toDelta(int index) { if(index == -1) return string.length() - cursor; return index - cursor; } // good for debugging @Override public String toString() { return string.substring(0, cursor) + "►" + string.substring(cursor); } }