diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-10-16 06:11:39 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-10-16 06:11:39 -0300 |
| commit | d2be5b73d7a5653ad5c8273c17284346baa6f1c7 (patch) | |
| tree | 9d3c6adb193f53588bd5d004fdf80c0381685351 /base/src/main/java/bjc/utils/ioutils/LevelSplitter.java | |
| parent | 0308029629a12711b849ea7765639b9b1f9e03d2 (diff) | |
| parent | d1d01769e7c55f7f62dc01cadf420d5f63424584 (diff) | |
Merge branch 'master' of github.com:bculkin2442/bjc-utils2
Diffstat (limited to 'base/src/main/java/bjc/utils/ioutils/LevelSplitter.java')
| -rw-r--r-- | base/src/main/java/bjc/utils/ioutils/LevelSplitter.java | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java b/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java new file mode 100644 index 0000000..83b391b --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java @@ -0,0 +1,274 @@ +package bjc.utils.ioutils; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Splits a string on a delimiter, respecting grouping delimiters. + * + * By default, grouping delimiters are (), [], {}, and <>, as well as single and + * double quoted strings. + * + * @author bjculkin + * + */ +public class LevelSplitter { + /** + * Defaultly configured level splitter. + */ + public final static LevelSplitter def = new LevelSplitter(); + + /** + * Check if a string contains any one of a specified number of things, + * respecting groups. + * + * @param haystack + * The string to look in. + * @param needles + * The strings to look for. + * @return Whether or not any of the strings were contained outside of + * groups. + */ + public boolean levelContains(String haystack, String... needles) { + int nestLevel = 0; + int i = 0; + + boolean prevCharWasSlash = false; + boolean inString = false; + + char stringEnder = ' '; + + while (i < haystack.length()) { + if (inString == false && nestLevel == 0) { + for (String needle : needles) { + if (haystack.regionMatches(i, needle, 0, needle.length())) { + return true; + } + } + } + + if (inString) { + if (prevCharWasSlash == true) { + prevCharWasSlash = false; + } else if (haystack.charAt(i) == stringEnder) { + inString = false; + } + } else { + switch (haystack.charAt(i)) { + case '\'': + inString = true; + stringEnder = '\''; + break; + case '\"': + inString = true; + stringEnder = '\"'; + break; + case '(': + case '[': + case '{': + case '<': + nestLevel += 1; + break; + case ')': + case ']': + case '}': + case '>': + nestLevel = Math.max(0, nestLevel - 1); + break; + } + } + + i += 1; + } + + return false; + } + + /** + * Split a string, respecting groups. + * + * @param phrase + * The string to split. + * @param splits + * The strings to split on. + * @return A list of split strings. If keepDelims is true, it also + * includes the delimiters in between the split strings. + */ + public List<String> levelSplit(String phrase, String... splits) { + return levelSplit(phrase, false, splits); + } + + /** + * Split a string, respecting groups. + * + * @param phrase + * The string to split. + * @param keepDelims + * Whether or not to include the delimiters in the + * results. + * @param splits + * The strings to split on. + * @return A list of split strings. If keepDelims is true, it also + * includes the delimiters in between the split strings. + */ + public List<String> levelSplit(String phrase, boolean keepDelims, String... splits) { + String work = phrase; + + List<String> strangs = new ArrayList<>(); + + int nestLevel = 0; + int i = 0; + + boolean prevCharWasSlash = false; + boolean inString = false; + + char stringEnder = ' '; + + // Shortcut empty strings + if (phrase.equals("")) { + strangs.add(""); + + return strangs; + } + + while (i < work.length()) { + if (inString == false && nestLevel == 0) { + for (String split : splits) { + if (work.regionMatches(i, split, 0, split.length())) { + strangs.add(work.substring(0, i)); + + if (keepDelims) strangs.add(split); + + work = work.substring(i + split.length()); + i = 0; + + continue; + } + } + } + + if (inString) { + if (prevCharWasSlash == true) { + prevCharWasSlash = false; + } else if (work.charAt(i) == stringEnder) { + inString = false; + } + } else { + /* + * @TODO Ben Culkin 9/4/18 + * + * This currently crashes if the string ends + * with one of the delimiters in question. + */ + switch (work.charAt(i)) { + case '\'': + inString = true; + stringEnder = '\''; + break; + case '\"': + inString = true; + stringEnder = '\"'; + break; + case '(': + case '[': + case '{': + case '<': + nestLevel += 1; + break; + case ')': + case ']': + case '}': + case '>': + nestLevel = Math.max(0, nestLevel - 1); + break; + } + } + + i += 1; + } + + strangs.add(work); + + return strangs; + } + + // @TODO @FIXME + // + // This doesn't seem like its working + @SuppressWarnings("javadoc") + public List<String> levelSplitRX(String phrase, String patt) { + return levelSplit(phrase, false, patt); + } + + @SuppressWarnings("javadoc") + public List<String> levelSplitRX(String phrase, boolean keepDelims, String patt) { + Pattern pat = Pattern.compile(patt); + + String work = phrase; + Matcher mat = pat.matcher(work); + + List<String> strangs = new ArrayList<>(); + + int nestLevel = 0; + int i = 0; + + boolean prevCharWasSlash = false; + boolean inString = false; + + char stringEnder = ' '; + + while (i < work.length()) { + if (inString == false && nestLevel == 0) { + if (mat.find(i)) { + strangs.add(work.substring(0, i)); + if (keepDelims) strangs.add(mat.group()); + work = work.substring(mat.end()); + i = 0; + + mat = pat.matcher(work); + + continue; + } + } + + if (inString) { + if (prevCharWasSlash == true) { + prevCharWasSlash = false; + } else if (work.charAt(i) == stringEnder) { + inString = false; + } + } else { + switch (work.charAt(i)) { + case '\'': + inString = true; + stringEnder = '\''; + break; + case '\"': + inString = true; + stringEnder = '\"'; + break; + case '(': + case '[': + case '{': + case '<': + nestLevel += 1; + break; + case ')': + case ']': + case '}': + case '>': + nestLevel = Math.max(0, nestLevel - 1); + break; + } + } + + i += 1; + } + + strangs.add(work); + + return strangs; + } +} |
