From bf9737ae3c61c638dca3a40ca847e784ddd750f3 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Sat, 13 Oct 2018 15:40:10 -0400 Subject: Pull out levelSplit/levelContains levelSplit/levelContains from the StringUtils class are now instead in the new LevelSplitter class in ioutils. This is so that new features of varying sorts can be added to those functions without cluttering up StringUtils. --- .../main/java/bjc/utils/funcutils/StringUtils.java | 217 +---------------- .../main/java/bjc/utils/ioutils/LevelSplitter.java | 260 +++++++++++++++++++++ 2 files changed, 261 insertions(+), 216 deletions(-) create mode 100644 base/src/main/java/bjc/utils/ioutils/LevelSplitter.java (limited to 'base') diff --git a/base/src/main/java/bjc/utils/funcutils/StringUtils.java b/base/src/main/java/bjc/utils/funcutils/StringUtils.java index 8e75f79..e8558c7 100644 --- a/base/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -7,6 +7,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import bjc.utils.data.BooleanToggle; +import bjc.utils.ioutils.LevelSplitter; import bjc.utils.parserutils.TokenUtils; import com.ibm.icu.text.BreakIterator; @@ -254,220 +255,4 @@ public class StringUtils { } return strings; } - - public static 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; - } - - public static List levelSplit(String phrase, String... splits) { - return levelSplit(phrase, false, splits); - } - - public static List levelSplit(String phrase, boolean keepDelims, String... splits) { - String work = phrase; - - List 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; - } - - public static List levelSplitRX(String phrase, String patt) { - return levelSplit(phrase, false, patt); - } - - // @TODO @FIXME - // - // This doesn't seem like its working - public static List levelSplitRX(String phrase, boolean keepDelims, String patt) { - Pattern pat = Pattern.compile(patt); - - String work = phrase; - Matcher mat = pat.matcher(work); - - List 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; - } } 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..7de0e28 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java @@ -0,0 +1,260 @@ +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 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 levelSplit(String phrase, boolean keepDelims, String... splits) { + String work = phrase; + + List 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 levelSplitRX(String phrase, String patt) { + return levelSplit(phrase, false, patt); + } + + @SuppressWarnings("javadoc") + public List levelSplitRX(String phrase, boolean keepDelims, String patt) { + Pattern pat = Pattern.compile(patt); + + String work = phrase; + Matcher mat = pat.matcher(work); + + List 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; + } +} -- cgit v1.2.3