package jadx.gui.utils.search; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.jetbrains.annotations.NotNull; public class StringRef implements CharSequence { private final String refStr; private final int offset; private final int length; private int hash; public static StringRef subString(String str, int from, int to) { return new StringRef(str, from, to - from); } public static StringRef subString(String str, int from) { return subString(str, from, str.length()); } public static StringRef fromStr(String str) { return new StringRef(str, 0, str.length()); } private StringRef(String str, int from, int length) { this.refStr = str; this.offset = from; this.length = length; } @Override public int length() { return length; } @Override public char charAt(int index) { return refStr.charAt(offset + index); } @Override public CharSequence subSequence(int start, int end) { return subString(refStr, start, end); } public StringRef trim() { int start = offset; int end = start + length; String str = refStr; while ((start < end) && (str.charAt(start) <= ' ')) { start++; } while ((start < end) && (str.charAt(end - 1) <= ' ')) { end--; } if ((start > offset) || (end < offset + length)) { return subString(str, start, end); } return this; } public int indexOf(String str) { return indexOf(str, 0); } public int indexOf(String str, int from) { return indexOf(refStr, offset, length, str, 0, str.length(), from); } private static int indexOf(String source, int sourceOffset, int sourceCount, String target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return -1; } char first = target.charAt(targetOffset); int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { if (source.charAt(i) != first) { while (++i <= max && source.charAt(i) != first) { } } if (i <= max) { int j = i + 1; int end = j + targetCount - 1; int k = targetOffset + 1; while (j < end && source.charAt(j) == target.charAt(k)) { j++; k++; } if (j == end) { return i - sourceOffset; } } } return -1; } public static List<StringRef> split(String str, String splitBy) { int len = str.length(); int targetLen = splitBy.length(); if (len == 0 || targetLen == 0) { return Collections.emptyList(); } int pos = -targetLen; List<StringRef> list = new ArrayList<StringRef>(); while (true) { int start = pos + targetLen; pos = indexOf(str, 0, len, splitBy, 0, targetLen, start); if (pos == -1) { if (start != len) { list.add(subString(str, start, len)); } break; } else { list.add(subString(str, start, pos)); } } return list; } public int hashCode() { int h = hash; int len = length; if (h == 0 && len > 0) { int off = offset; String str = this.refStr; for (int i = 0; i < len; i++) { h = 31 * h + str.charAt(off++); } hash = h; } return h; } public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof StringRef)) { return false; } StringRef otherSlice = (StringRef) other; int len = this.length; if (len != otherSlice.length) { return false; } int i = offset; int j = otherSlice.offset; String refStr = this.refStr; String otherRefStr = otherSlice.refStr; while (len-- != 0) { if (refStr.charAt(i++) != otherRefStr.charAt(j++)) { return false; } } return true; } @NotNull @Override public String toString() { int len = this.length; if (len == 0) { return ""; } int offset = this.offset; return refStr.substring(offset, offset + len); } }