StringUtils.java
package bjc.everge;
import java.util.*;
import java.util.regex.Pattern;
/**
* Utility methods for strings.
*
* @author Ben Culkin.
*/
public class StringUtils {
/**
* Is the class in debug mode or not?
*/
public static boolean isDebug = false;
/**
* Split a string on every occurrence of a string not preceded by an escape.
*
* @param escape
* The escape that stops splitting.
* @param splat
* The string to split on. If this starts with the escape sequence, things will work
* poorly.
* @param inp
* The string to split.
* @return The string split as specified above.
*/
public static String[] escapeSplit(String escape, String splat, String inp) {
/*
* Special case some stuffs.
*/
// No input
if (inp == null || inp.equals("")) {
return new String[] {inp};
}
// Input does not contain any delimiters
if (!inp.contains(splat)) {
return new String[] {inp};
}
// No escape, so we can just split normally
if (escape == null || escape.equals("")) {
return inp.split(Pattern.quote(splat));
}
List<String> ret = new ArrayList<>();
/*
* Set up working variables
*/
// Copy of parameters
String wrk = inp;
// Index of first occurrence of split string
int sidx = wrk.indexOf(splat);
// Index of first occurrence of escaped string
int eidx = wrk.indexOf(escape);
// Was the last thing we saw an escape?
// This is used to enable the handling of escaping escapes
boolean hadEscape = false;
// As long as there an occurrence of either the split/escape
while (sidx != -1 || eidx != -1) {
// If there is an escape before a split
if (eidx > 0 && eidx < sidx) {
if (isDebug) System.err.printf("[TRACE] Considering escape\n");
/*
* We potentially have an escaped sequence:
* - either an escaped split
* - or an escaped escape
*/
// Check for an escaped split
boolean hasEscapedSplit = wrk.startsWith(splat, eidx + escape.length());
if (hasEscapedSplit) {
// Skip over it
int ofst = eidx + splat.length();
wrk = sliceStringL(wrk, eidx, escape.length());
// Recalculate indexes
sidx = wrk.indexOf(splat, ofst);
eidx = wrk.indexOf(escape, ofst);
if (isDebug) {
System.err.printf("[TRACE] After esc. split (%s) %d/%d\n",
wrk, sidx, eidx);
}
// No pending escape
hadEscape = false;
continue;
}
// Check for an escaped escape
boolean hasEscapedEscape = wrk.startsWith(escape, eidx + escape.length());
if (hasEscapedEscape) {
// Skip over it
int ofst = eidx + escape.length();
wrk = sliceStringL(wrk, eidx, escape.length());
// Recalculate indexes
sidx = wrk.indexOf(splat, ofst);
eidx = wrk.indexOf(escape, ofst);
if (isDebug) {
System.err.printf("[TRACE] After esc. escape (%s)/(%s) %d/%d\n",
wrk, wrk.substring(ofst), sidx, eidx);
}
// There's a pending escape
hadEscape = true;
continue;
}
}
// Calculate whether there is currently an escape
boolean hasEscape = false;
{
boolean tmp = wrk.startsWith(escape, sidx - escape.length());
// boolean tmp = wrk.regionMatches(lo, escape, 0, escape.length());
hasEscape = hadEscape ? false : tmp;
}
// Handle anything that the pending escape may be applied to
while (sidx != -1 && hasEscape) {
int oidx = wrk.indexOf(splat, sidx + escape.length());
if (oidx == -1) break;
wrk = sliceStringL(wrk, oidx, escape.length());
sidx = oidx;
hasEscape = wrk.startsWith(escape, sidx - escape.length());
}
if (sidx == -1) {
break;
}
String tmp = wrk.substring(0, sidx);
if (isDebug) {
System.err.printf("[TRACE] Adding (%s) to returned splits; (%s)\n",
tmp, wrk.substring(sidx));
}
ret.add(tmp);
if (!tmp.equals("") && wrk.endsWith(tmp)) {
wrk = "";
} else {
if (wrk.indexOf(splat, sidx) != -1) {
wrk = wrk.substring(sidx + splat.length());
} else {
wrk = wrk.substring(sidx);
}
}
sidx = wrk.indexOf(splat);
eidx = wrk.indexOf(escape);
hadEscape = false;
}
if (!wrk.equals("")) ret.add(wrk);
return ret.toArray(new String[0]);
}
/**
* Slice a substring out of another string.
*
* @param strang
* The string to remove a substring from.
* @param lft
* The left-side of the substring to remove.
* @param rft
* The right-side of the substring to remove.
*
* @return The string, with the substring removed.
*/
public static String sliceString(String strang, int lft, int rft) {
String leftSide = strang.substring(0, lft);
String rightSide = strang.substring(rft);
return leftSide + rightSide;
}
/**
* Slice a substring out of another string.
*
* @param strang
* The string to remove a substring from.
* @param lft
* The left-side of the substring to remove.
* @param len
* The length of the substring to remove.
*
* @return The string, with the substring removed.
*/
public static String sliceStringL(String strang, int lft, int len) {
String leftSide = strang.substring(0, lft);
String rightSide = strang.substring(lft + len);
return leftSide + rightSide;
}
}