summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-10-16 06:11:39 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-10-16 06:11:39 -0300
commitd2be5b73d7a5653ad5c8273c17284346baa6f1c7 (patch)
tree9d3c6adb193f53588bd5d004fdf80c0381685351 /base/src/main/java/bjc/utils/ioutils/LevelSplitter.java
parent0308029629a12711b849ea7765639b9b1f9e03d2 (diff)
parentd1d01769e7c55f7f62dc01cadf420d5f63424584 (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.java274
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;
+ }
+}