From c82e3b3b2de0633317ec8fc85925e91422820597 Mon Sep 17 00:00:00 2001 From: "Benjamin J. Culkin" Date: Sun, 8 Oct 2017 22:39:59 -0300 Subject: Start splitting into maven modules --- .../main/java/bjc/utils/ioutils/CLFormatter.java | 531 --------------------- .../main/java/bjc/utils/ioutils/CLParameters.java | 109 ----- .../main/java/bjc/utils/ioutils/NumberUtils.java | 405 ---------------- .../src/main/java/bjc/utils/ioutils/Prompter.java | 47 -- .../java/bjc/utils/ioutils/RegexStringEditor.java | 230 --------- .../bjc/utils/ioutils/RuleBasedConfigReader.java | 265 ---------- .../bjc/utils/ioutils/RuleBasedReaderPragmas.java | 100 ---- .../java/bjc/utils/ioutils/SimpleProperties.java | 170 ------- .../main/java/bjc/utils/ioutils/blocks/Block.java | 88 ---- .../java/bjc/utils/ioutils/blocks/BlockReader.java | 73 --- .../bjc/utils/ioutils/blocks/BlockReaders.java | 81 ---- .../bjc/utils/ioutils/blocks/BoundBlockReader.java | 61 --- .../utils/ioutils/blocks/FilteredBlockReader.java | 97 ---- .../ioutils/blocks/FlatMappedBlockReader.java | 86 ---- .../utils/ioutils/blocks/LayeredBlockReader.java | 81 ---- .../utils/ioutils/blocks/MappedBlockReader.java | 54 --- .../utils/ioutils/blocks/PushbackBlockReader.java | 106 ---- .../utils/ioutils/blocks/SerialBlockReader.java | 102 ---- .../utils/ioutils/blocks/SimpleBlockReader.java | 115 ----- .../utils/ioutils/blocks/ToggledBlockReader.java | 63 --- .../utils/ioutils/blocks/TriggeredBlockReader.java | 70 --- 21 files changed, 2934 deletions(-) delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java (limited to 'BJC-Utils2/src/main/java/bjc/utils/ioutils') diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java deleted file mode 100644 index eefd532..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java +++ /dev/null @@ -1,531 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.HashMap; -import java.util.IllegalFormatConversionException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UnknownFormatConversionException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import bjc.utils.PropertyDB; -import bjc.utils.esodata.Tape; -import bjc.utils.esodata.SingleTape; - -import static bjc.utils.PropertyDB.applyFormat; -import static bjc.utils.PropertyDB.getCompiledRegex; -import static bjc.utils.PropertyDB.getRegex; - -public class CLFormatter { - public static class CLModifiers { - public final boolean atMod; - public final boolean colonMod; - - public CLModifiers(boolean at, boolean colon) { - atMod = at; - colonMod = colon; - } - - public static CLModifiers fromString(String modString) { - boolean atMod = false; - boolean colonMod = false; - if(modString != null) { - atMod = modString.contains("@"); - colonMod = modString.contains(":"); - } - - return new CLModifiers(atMod, colonMod); - } - } - - public static class EscapeException extends RuntimeException { - public final boolean endIteration; - - public EscapeException() { - endIteration = false; - } - - public EscapeException(boolean end) { - endIteration = end; - } - } - - @FunctionalInterface - public interface Directive { - /* - * @TODO fill in parameters - */ - public void format(); - } - - private static final String prefixParam = getRegex("clFormatPrefix"); - private static final Pattern pPrefixParam = Pattern.compile(prefixParam); - - private static final String formatMod = getRegex("clFormatModifier"); - - private static final String prefixList = applyFormat("delimSeparatedList", prefixParam, ","); - - private static final String directiveName = getRegex("clFormatName"); - - private static final String formatDirective = applyFormat("clFormatDirective", prefixList, formatMod, directiveName); - private static final Pattern pFormatDirective = Pattern.compile(formatDirective); - - private Map extraDirectives; - - public CLFormatter() { - extraDirectives = new HashMap<>(); - } - - private void checkItem(Object itm, char directive) { - if(itm == null) - throw new IllegalArgumentException(String.format("No argument provided for %c directive", directive)); - } - - public String formatString(String format, Object... params) { - StringBuffer sb = new StringBuffer(); - /* Put the parameters where we can easily handle them. */ - Tape tParams = new SingleTape(params); - - doFormatString(format, sb, tParams); - - return sb.toString(); - } - - private void doFormatString(String format, StringBuffer sb, Tape tParams) { - Matcher dirMatcher = pFormatDirective.matcher(format); - - while(dirMatcher.find()) { - dirMatcher.appendReplacement(sb, ""); - - String dirName = dirMatcher.group("name"); - String dirFunc = dirMatcher.group("funcname"); - String dirMods = dirMatcher.group("modifiers"); - String dirParams = dirMatcher.group("params"); - - CLParameters arrParams = CLParameters.fromDirective(dirParams.split("(?": - /* @TODO - * Figure out how to implement - * tabulation/justification in a - * reasonable manner. - */ - throw new IllegalArgumentException("Layout-control directives aren't implemented yet."); - case "F": - case "E": - case "G": - case "$": - /* @TODO implement floating point directives. */ - throw new IllegalArgumentException("Floating-point directives aren't implemented yet."); - case "S": - case "W": - /* @TODO - * figure out if we want to implement - * someting for these directives instead - * of punting. - * */ - throw new IllegalArgumentException("S and W aren't implemented. Use A instead"); - default: - String msg = String.format("Unknown format directive '%s'", dirName); - throw new UnknownFormatConversionException(msg); - } - } - - dirMatcher.appendTail(sb); - } - - private void handleCDirective(StringBuffer buff, Object parm, CLModifiers mods) { - if(!(parm instanceof Character)) { - throw new IllegalFormatConversionException('C', parm.getClass()); - } - - char ch = (Character) parm; - int codepoint = (int) ch; - - if(mods.colonMod) { - /* - * Colon mod means print Unicode character name. - */ - buff.append(Character.getName(codepoint)); - } else { - buff.append(ch); - } - } - - private void handleFreshlineDirective(StringBuffer buff, CLParameters params) { - int nTimes = 1; - - if(params.length() > 1) { - nTimes = params.getInt(0, "occurance count", '&'); - } - - if(buff.charAt(buff.length() - 1) == '\n') nTimes -= 1; - - for(int i = 0; i < nTimes; i++) { - buff.append("\n"); - } - } - - private void handleLiteralDirective(StringBuffer buff, CLParameters params, String lit, char directive) { - int nTimes = 1; - - if(params.length() > 1) { - nTimes = params.getInt(0, "occurance count", directive); - } - - for(int i = 0; i < nTimes; i++) { - buff.append(lit); - } - } - - private void handleNumberDirective(StringBuffer buff, CLModifiers mods, CLParameters params, int argidx, long val, int radix) { - /* - * Initialize the two padding related parameters, and - * then fill them in from the directive parameters if - * they are present. - */ - int mincol = 0; - char padchar = ' '; - if(params.length() > (argidx + 2)) { - mincol = params.getIntDefault(argidx + 1, "minimum column count", 'R', 0); - } - if(params.length() > (argidx + 3)) { - padchar = params.getCharDefault(argidx + 2, "padding character", 'R', ' '); - } - - if(mods.colonMod) { - /* - * We're doing commas, so check if the two - * comma-related parameters were supplied. - */ - int commaInterval = 0; - char commaChar = ','; - if(params.length() > (argidx + 3)) { - commaChar = params.getCharDefault((argidx + 3), "comma character", 'R', ' '); - } - if(params.length() > (argidx + 4)) { - commaInterval = params.getIntDefault((argidx + 4), "comma interval", 'R', 0); - } - - NumberUtils.toCommaString(val, mincol, padchar, commaInterval, commaChar, mods.atMod, radix); - } else { - NumberUtils.toNormalString(val, mincol, padchar, mods.atMod, radix); - } - } - - private void handleRadixDirective(StringBuffer buff, CLModifiers mods, CLParameters params, Object arg) { - if(!(arg instanceof Number)) { - throw new IllegalFormatConversionException('R', arg.getClass()); - } - - /* - * @TODO see if this is the way we want to do this. - */ - long val = ((Number)arg).longValue(); - - if(params.length() == 0) { - if(mods.atMod) { - buff.append(NumberUtils.toRoman((Long)val, mods.colonMod)); - } else if(mods.colonMod) { - buff.append(NumberUtils.toOrdinal(val)); - } else { - buff.append(NumberUtils.toCardinal(val)); - } - } else { - if(params.length() < 1) - throw new IllegalArgumentException("R directive requires at least one parameter, the radix"); - - int radix = params.getInt(0, "radix", 'R'); - - handleNumberDirective(buff, mods, params, 0, val, radix); - } - } - - private void handleAestheticDirective(StringBuffer buff, Object item, CLModifiers mods, CLParameters params) { - int mincol = 0, colinc = 1, minpad = 0; - char padchar = ' '; - - if(params.length() > 1) { - mincol = params.getIntDefault(0, "minimum column count", 'A', 0); - } - - if(params.length() < 4) { - throw new IllegalArgumentException("Must provide either zero, one or four arguments to A directive"); - } - - colinc = params.getIntDefault(1, "padding increment", 'A', 1); - minpad = params.getIntDefault(2, "minimum amount of padding", 'A', 0); - padchar = params.getCharDefault(3, "padding character", 'A', ' '); - - StringBuilder work = new StringBuilder(); - - if(mods.atMod) { - for(int i = 0; i < minpad; i++) { - work.append(padchar); - } - - for(int i = work.length(); i < mincol; i++) { - for(int k = 0; k < colinc; k++) { - work.append(padchar); - } - } - } - - work.append(item.toString()); - - if(!mods.atMod) { - for(int i = 0; i < minpad; i++) { - work.append(padchar); - } - - for(int i = work.length(); i < mincol; i++) { - for(int k = 0; k < colinc; k++) { - work.append(padchar); - } - } - } - } - - private void handleGotoDirective(CLModifiers mods, CLParameters params, Tape formatParams) { - if(mods.colonMod) { - int num = 1; - if(params.length() > 1) { - num = params.getIntDefault(0, "number of arguments backward", '*', 1); - } - - formatParams.left(num); - } else if(mods.atMod) { - int num = 0; - if(params.length() > 1) { - num = params.getIntDefault(0, "argument index", '*', 0); - } - - formatParams.first(); - formatParams.right(num); - } else { - int num = 1; - if(params.length() > 1) { - num = params.getIntDefault(0, "number of arguments forward", '*', 1); - } - - formatParams.right(num); - } - } - - private void handleConditionalDirective(StringBuffer sb, CLModifiers mods, CLParameters arrParams, Tape formatParams, Matcher dirMatcher) { - StringBuffer condBody = new StringBuffer(); - - List clauses = new ArrayList<>(); - String defClause = null; - boolean isDefault = false; - - while(dirMatcher.find()) { - /* Process a list of clauses. */ - String dirName = dirMatcher.group("name"); - String dirMods = dirMatcher.group("modifiers"); - - if(dirName != null) { - /* Append everything up to this directive. */ - dirMatcher.appendReplacement(condBody, ""); - - if(dirName.equals("]")) { - /* End the conditional. */ - String clause = condBody.toString(); - if(isDefault) { - defClause = clause; - } else { - clauses.add(clause); - } - - break; - } else if(dirName.equals(";")) { - /* End the clause. */ - String clause = condBody.toString(); - if(isDefault) { - defClause = clause; - } else { - clauses.add(clause); - } - - /* Mark the next clause as the default. */ - if(dirMods.contains(":")) { - isDefault = true; - } - } else { - /* Not a special directive. */ - condBody.append(dirMatcher.group()); - } - } - } - - Object par = formatParams.item(); - if(mods.colonMod) { - formatParams.right(); - - if(par == null) { - throw new IllegalArgumentException("No parameter provided for [ directive."); - } else if(!(par instanceof Boolean)) { - throw new IllegalFormatConversionException('[', par.getClass()); - } - boolean res = (Boolean)par; - - String fmt; - if(res) fmt = clauses.get(1); - else fmt = clauses.get(0); - - doFormatString(fmt, sb, formatParams); - } else if(mods.atMod) { - if(par == null) { - throw new IllegalArgumentException("No parameter provided for [ directive."); - } else if(!(par instanceof Boolean)) { - throw new IllegalFormatConversionException('[', par.getClass()); - } - boolean res = (Boolean)par; - - if(res) { - doFormatString(clauses.get(0), sb, formatParams); - } else { - formatParams.right(); - } - } else { - int res; - if(arrParams.length() > 1) { - res = arrParams.getInt(0, "conditional choice", '['); - } else { - if(par == null) { - throw new IllegalArgumentException("No parameter provided for [ directive."); - } else if(!(par instanceof Number)) { - throw new IllegalFormatConversionException('[', par.getClass()); - } - res = ((Number)par).intValue(); - - formatParams.right(); - } - - if(res < 0 || res > clauses.size()) { - if(defClause != null) doFormatString(defClause, sb, formatParams); - } else { - doFormatString(clauses.get(res), sb, formatParams); - } - } - return; - } - - private void handleEscapeDirective(CLModifiers mods, CLParameters params, Tape formatParams) { - boolean shouldExit; - - switch(params.length()) { - case 0: - shouldExit = formatParams.size() == 0; - break; - case 1: - int num = params.getInt(0, "condition count", '^'); - shouldExit = num == 0; - break; - case 2: - int left = params.getInt(0, "left-hand condition", '^'); - int right = params.getInt(1, "right-hand condition", '^'); - shouldExit = left == right; - break; - case 3: - default: - int low = params.getInt(0, "lower-bound condition", '^'); - int mid = params.getInt(1, "interval condition", '^'); - int high = params.getInt(2, "upper-bound condition", '^'); - shouldExit = (low <= mid) && (mid <= high); - break; - } - - /* At negates it. */ - if(mods.atMod) shouldExit = !shouldExit; - - if(shouldExit) throw new EscapeException(mods.colonMod); - } - - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java deleted file mode 100644 index e4bb6fb..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java +++ /dev/null @@ -1,109 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.ArrayList; -import java.util.List; - -import bjc.utils.esodata.Tape; - -/** - * Represents a set of parameters to a CL format directive. - * - * @author Benjamin Culkin - */ -public class CLParameters { - private String[] params; - - public CLParameters(String[] params) { - this.params = params; - } - - public int length() { - return params.length; - } - - /** - * Creates a set of parameters from an array of parameters. - * - * Mostly, this just fills in V and # parameters. - * - * @param params - * The parameters of the directive. - * @param dirParams - * The parameters of the format string. - * - * @return A set of CL parameters. - */ - public static CLParameters fromDirective(String[] params, Tape dirParams) { - List parameters = new ArrayList<>(); - - for(String param : params) { - if(param.equalsIgnoreCase("V")) { - Object par = dirParams.item(); - boolean succ = dirParams.right(); - - if(par == null) { - throw new IllegalArgumentException("Expected a format parameter for V inline parameter"); - } - - if(par instanceof Number) { - int val = ((Number)par).intValue(); - - parameters.add(Integer.toString(val)); - } else if(par instanceof Character) { - char ch = ((Character)par); - - parameters.add(Character.toString(ch)); - } else { - throw new IllegalArgumentException("Incorrect type of parameter for V inline parameter"); - } - } else if(param.equals("#")) { - parameters.add(Integer.toString(dirParams.position())); - } else { - parameters.add(param); - } - } - - return new CLParameters(parameters.toArray(new String[0])); - } - - public char getCharDefault(int idx, String paramName, char directive, char def) { - if(!params[idx].equals("")) { - return getChar(idx, paramName, directive); - } - - return def; - } - - public char getChar(int idx, String paramName, char directive) { - String param = params[idx]; - - if(!param.startsWith("'")) { - throw new IllegalArgumentException(String.format("Invalid %s %s to %c directive", paramName, param, directive)); - } - - return param.charAt(1); - } - - public int getIntDefault(int idx, String paramName, char directive, int def) { - if(!params[idx].equals("")) { - - } - - return def; - } - - public int getInt(int idx, String paramName, char directive) { - String param = params[idx]; - - try { - return Integer.parseInt(param); - } catch (NumberFormatException nfex) { - String msg = String.format("Invalid %s %s to %c directive", paramName, param, directive); - - IllegalArgumentException iaex = new IllegalArgumentException(msg); - iaex.initCause(nfex); - - throw iaex; - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java deleted file mode 100644 index 1b754e2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java +++ /dev/null @@ -1,405 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.Map; -import java.util.function.BiFunction; -import java.util.function.LongPredicate; - -import static java.util.Map.Entry; - -public class NumberUtils { - /* - * @TODO Use U+305 for large roman numerals, as well as excels 'concise' - * numerals (as implemented by roman()). - */ - public static String toRoman(long number, boolean classic) { - StringBuilder work = new StringBuilder(); - - long currNumber = number; - - if(currNumber == 0) { - return "N"; - } - - if(currNumber < 0) { - currNumber *= -1; - - work.append("-"); - } - - if(currNumber >= 1000) { - int numM = (int)(currNumber / 1000); - currNumber = currNumber % 1000; - - for(int i = 0; i < numM; i++) { - work.append("M"); - } - } - - if(currNumber >= 900 && !classic) { - currNumber = currNumber % 900; - - work.append("CM"); - } - - if(currNumber >= 500) { - currNumber = currNumber % 500; - - work.append("D"); - } - - if(currNumber >= 400 && !classic) { - currNumber = currNumber % 400; - - work.append("CD"); - } - - if(currNumber >= 100) { - int numC = (int)(currNumber / 100); - currNumber = currNumber % 100; - - for(int i = 0; i < numC; i++) { - work.append("C"); - } - } - - if(currNumber >= 90 && !classic) { - currNumber = currNumber % 90; - - work.append("XC"); - } - - if(currNumber >= 50) { - currNumber = currNumber % 50; - - work.append("L"); - } - - if(currNumber >= 40 && !classic) { - currNumber = currNumber % 40; - - work.append("XL"); - } - - if(currNumber >= 10) { - int numX = (int)(currNumber / 10); - currNumber = currNumber % 10; - - for(int i = 0; i < numX; i++) { - work.append("X"); - } - } - - if(currNumber >= 9 && !classic) { - currNumber = currNumber % 9; - - work.append("IX"); - } - - if(currNumber >= 5) { - currNumber = currNumber % 5; - - work.append("V"); - } - - if(currNumber >= 4 && !classic) { - currNumber = currNumber % 4; - - work.append("IV"); - } - - if(currNumber >= 1) { - int numI = (int)(currNumber / 1); - currNumber = currNumber % 1; - - for(int i = 0; i < numI; i++) { - work.append("I"); - } - } - - return work.toString(); - } - - public static String toCardinal(long number) { - return toCardinal(number, null); - } - - private static String[] cardinals = new String[] { - "zero", "one", "two", "three", "four", "five", "six", "seven", - "eight", "nine", "ten", "eleven", "twelve", "thirteen", - "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", - "nineteen", "twenty", - }; - - public static class CardinalState { - public final Map customNumbers; - public final Map> customScales; - - public CardinalState(Map customNumbers, Map> customScales) { - this.customNumbers = customNumbers; - this.customScales = customScales; - } - - public String handleCustom(long number) { - if(customNumbers.containsKey(number)) { - return customNumbers.get(number); - } - - for(Entry> ent : customScales.entrySet()) { - if(ent.getKey().test(number)) { - return ent.getValue().apply(number, this); - } - } - - return null; - } - } - - public static String toCardinal(long number, CardinalState custom) { - if(custom != null) { - String res = custom.handleCustom(number); - - if(res != null) return res; - } - - if(number < 0) return "negative " + toCardinal(number * -1, custom); - - if(number <= 20) return cardinals[(int)number]; - - if(number < 100) { - if(number % 10 == 0) { - switch((int)number) { - case 30: - return "thirty"; - case 40: - return "forty"; - case 50: - return "fifty"; - case 60: - return "sixty"; - case 70: - return "seventy"; - case 80: - return "eighty"; - case 90: - return "ninety"; - default: - /* - * Shouldn't happen. - */ - assert(false); - } - } - - long numTens = (long)(number / 10); - long numOnes = number % 10; - - return toCardinal(numTens, custom) + "-" + toCardinal(numOnes, custom); - } - - if(number < 1000) { - long numHundreds = (long)(number / 100); - long rest = number % 100; - - return toCardinal(numHundreds, custom) + " hundred and " + toCardinal(rest, custom); - } - - long MILLION = (long)(Math.pow(10, 6)); - if(number < MILLION) { - long numThousands = (long)(number / 1000); - long rest = number % 1000; - - return toCardinal(numThousands, custom) + " thousand, " + toCardinal(rest, custom); - } - - long BILLION = (long)(Math.pow(10, 9)); - if(number < BILLION) { - long numMillions = (long)(number / MILLION); - long rest = number % MILLION; - - return toCardinal(numMillions, custom) + " million, " + toCardinal(rest, custom); - } - - long TRILLION = (long)(Math.pow(10, 12)); - if(number < TRILLION) { - long numBillions = (long)(number / BILLION); - long rest = number % BILLION; - - return toCardinal(numBillions, custom) + " billion, " + toCardinal(rest, custom); - } - - throw new IllegalArgumentException("Numbers greater than or equal to 1 trillion are not supported yet."); - } - - public static String toOrdinal(long number) { - if(number < 0) { - return "minus " + toOrdinal(number); - } - - if(number < 20) { - switch((int)number) { - case 0: - return "zeroth"; - case 1: - return "first"; - case 2: - return "second"; - case 3: - return "third"; - case 4: - return "fourth"; - case 5: - return "fifth"; - case 6: - return "sixth"; - case 7: - return "seventh"; - case 8: - return "eighth"; - case 9: - return "ninth"; - case 10: - return "tenth"; - case 11: - return "eleventh"; - case 12: - return "twelfth"; - case 13: - return "thirteenth"; - case 14: - return "fourteenth"; - case 15: - return "fifteenth"; - case 16: - return "sixteenth"; - case 17: - return "seventeenth"; - case 18: - return "eighteenth"; - case 19: - return "nineteenth"; - default: - /* - * Shouldn't happen. - */ - assert(false); - } - } - - if(number < 100) { - if(number % 10 == 0) { - switch((int)number) { - case 20: - return "twentieth"; - case 30: - return "thirtieth"; - case 40: - return "fortieth"; - case 50: - return "fiftieth"; - case 60: - return "sixtieth"; - case 70: - return "seventieth"; - case 80: - return "eightieth"; - case 90: - return "ninetieth"; - } - } - - long numPostfix = number % 10; - return toCardinal(number - numPostfix) + "-" + toOrdinal(numPostfix); - } - - long procNum = number % 100; - long tens = (long)(procNum / 10); - long ones = procNum % 10; - - if(tens == 1) { - return Long.toString(number) + "th"; - } - - switch((int)ones) { - case 1: - return Long.toString(number) + "st"; - case 2: - return Long.toString(number) + "nd"; - case 3: - return Long.toString(number) + "rd"; - default: - return Long.toString(number) + "th"; - } - } - - private static char[] radixChars = new char[62]; - static { - int idx = 0; - - for(char i = 0; i < 10; i++) { - radixChars[idx] = (char)('0' + i); - - idx += 1; - } - - for(char i = 0; i < 26; i++) { - radixChars[idx] = (char)('A' + i); - - idx += 1; - } - - for(char i = 0; i < 26; i++) { - radixChars[idx] = (char)('a' + i); - - idx += 1; - } - } - - public static String toCommaString(long val, int mincols, char padchar, int commaInterval, char commaChar, boolean signed, int radix) { - if(radix > radixChars.length) { - throw new IllegalArgumentException(String.format("Radix %d is larger than largest supported radix %d", radix, radixChars.length)); - } - - StringBuilder work = new StringBuilder(); - - boolean isNeg = false; - long currVal = val; - if(currVal < 0) { - isNeg = true; - currVal *= -1; - } - - if(currVal == 0) { - work.append(radixChars[0]); - } else { - int valCounter = 0; - - while(currVal != 0) { - valCounter += 1; - - int radDigit = (int)(currVal % radix); - work.append(radixChars[radDigit]); - currVal = (long)(currVal / radix); - - if(commaInterval != 0 && valCounter % commaInterval == 0) work.append(commaChar); - } - } - - if(isNeg) work.append("-"); - else if(signed) work.append("+"); - - work.reverse(); - - /* @TODO Should we have some way to specify how to pad? */ - if(work.length() < mincols) { - for(int i = work.length(); i < mincols; i++) { - work.append(padchar); - } - } - - return work.toString(); - } - - public static String toNormalString(long val, int mincols, char padchar, boolean signed, int radix) { - return toCommaString(val, mincols, padchar, 0, ',', signed, radix); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java deleted file mode 100644 index a6ec4c0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java +++ /dev/null @@ -1,47 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.PrintStream; - -import bjc.utils.ioutils.blocks.TriggeredBlockReader; - -/** - * A runnable for use with {@link TriggeredBlockReader} to prompt the user for - * input. - * - * @author bjculkin - * - */ -public final class Prompter implements Runnable { - private String promt; - private final PrintStream printer; - - /** - * Create a new prompter using the specified prompt. - * - * @param prompt - * The prompt to present. - * - * @param output - * The stream to print the prompt on. - */ - public Prompter(final String prompt, final PrintStream output) { - promt = prompt; - - printer = output; - } - - /** - * Set the prompt this prompter uses. - * - * @param prompt - * The prompt this prompter uses. - */ - public void setPrompt(final String prompt) { - promt = prompt; - } - - @Override - public void run() { - printer.print(promt); - } -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java deleted file mode 100644 index 71f6782..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java +++ /dev/null @@ -1,230 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.function.BiFunction; -import java.util.function.UnaryOperator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import bjc.utils.data.Toggle; -import bjc.utils.data.ValueToggle; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.functypes.ID; - -/** - * Editor methods for strings based off the command language for the Sam editor. - * - * @author EVE - * - */ -public class RegexStringEditor { - private static final UnaryOperator SID = ID.id(); - - /** - * Replace every occurrence of the pattern with the result of applying - * the action to the string matched by the pattern. - * - * @param input - * The input string to process. - * - * @param patt - * The pattern to match the string against. - * - * @param action - * The action to transform matches with. - * - * @return The string, with matches replaced with the action. - */ - public static String onOccurances(final String input, final Pattern patt, final UnaryOperator action) { - return reduceOccurances(input, patt, SID, action); - } - - /** - * Replace every occurrence between the patterns with the result of - * applying the action to the strings between the patterns. - * - * @param input - * The input string to process. - * - * @param patt - * The pattern to match the string against. - * - * @param action - * The action to transform matches with. - * - * @return The string, with strings between the matches replaced with - * the action. - */ - public static String betweenOccurances(final String input, final Pattern patt, - final UnaryOperator action) { - return reduceOccurances(input, patt, action, SID); - } - - /** - * Execute actions between and on matches of a regular expression. - * - * @param input - * The input string. - * - * @param rPatt - * The pattern to match against the string. - * - * @param betweenAction - * The function to execute between matches of the string. - * - * @param onAction - * The function to execute on matches of the string. - * - * @return The string, with both actions applied. - */ - public static String reduceOccurances(final String input, final Pattern rPatt, - final UnaryOperator betweenAction, final UnaryOperator onAction) { - /* - * Get all of the occurances. - */ - final IList occurances = listOccurances(input, rPatt); - - /* - * Execute the correct action on every occurance. - */ - final Toggle> actions = new ValueToggle<>(onAction, betweenAction); - final BiFunction reducer = (strang, state) -> { - return state.append(actions.get().apply(strang)); - }; - - /* - * Convert the list back to a string. - */ - return occurances.reduceAux(new StringBuilder(), reducer, StringBuilder::toString); - } - - /** - * Execute actions between and on matches of a regular expression. - * - * @param input - * The input string. - * - * @param rPatt - * The pattern to match against the string. - * - * @param betweenAction - * The function to execute between matches of the string. - * - * @param onAction - * The function to execute on matches of the string. - * - * @return The string, with both actions applied. - */ - public static IList mapOccurances(final String input, final Pattern rPatt, - final UnaryOperator betweenAction, final UnaryOperator onAction) { - /* - * Get all of the occurances. - */ - final IList occurances = listOccurances(input, rPatt); - - /* - * Execute the correct action on every occurance. - */ - final Toggle> actions = new ValueToggle<>(onAction, betweenAction); - return occurances.map(strang -> actions.get().apply(strang)); - } - - /** - * Separate a string into match/non-match segments. - * - * @param input - * The string to separate. - * - * @param rPatt - * The pattern to use for separation. - * - * @return The string, as a list of match/non-match segments, - * starting/ending with a non-match segment. - */ - public static IList listOccurances(final String input, final Pattern rPatt) { - final IList res = new FunctionalList<>(); - - /* - * Create the matcher and work buffer. - */ - final Matcher matcher = rPatt.matcher(input); - StringBuffer work = new StringBuffer(); - - /* - * For every match. - */ - while (matcher.find()) { - final String match = matcher.group(); - - /* - * Append the text until the match to the buffer. - */ - matcher.appendReplacement(work, ""); - - res.add(work.toString()); - res.add(match); - - /* - * Clear the buffer. - */ - work = new StringBuffer(); - } - - /* - * Add the text after the last match to the buffer. - */ - matcher.appendTail(work); - res.add(work.toString()); - - return res; - } - - /** - * Apply an operation to a string if it matches a regular expression. - * - * @param input - * The input string. - * - * @param patt - * The pattern to match against it. - * - * @param action - * The action to execute if it matches. - * - * @return The string, modified by the action if the pattern matched. - */ - public static String ifMatches(final String input, final Pattern patt, final UnaryOperator action) { - final Matcher matcher = patt.matcher(input); - - if (matcher.matches()) { - return action.apply(input); - } else { - return input; - } - } - - /** - * Apply an operation to a string if it matches a regular expression. - * - * @param input - * The input string. - * - * @param patt - * The pattern to match against it. - * - * @param action - * The action to execute if it doesn't match. - * - * @return The string, modified by the action if the pattern didn't - * match. - */ - public static String ifNotMatches(final String input, final Pattern patt, final UnaryOperator action) { - final Matcher matcher = patt.matcher(input); - - if (matcher.matches()) { - return input; - } else { - return action.apply(input); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java deleted file mode 100644 index 7c5205b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java +++ /dev/null @@ -1,265 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.InputStream; -import java.util.InputMismatchException; -import java.util.Scanner; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.Pair; -import bjc.utils.exceptions.UnknownPragmaException; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IMap; - -/** - * This class parses a rules based config file, and uses it to drive a provided - * set of actions - * - * @author ben - * - * @param - * The type of the state object to use - * - */ -public class RuleBasedConfigReader { - /* Function to execute when starting a rule. - * Takes the tokenizer, and a pair of the read token and application state - */ - private BiConsumer> start; - - /* - * Function to use when continuing a rule - * Takes a tokenizer and application state - */ - private BiConsumer continueRule; - - /* - * Function to use when ending a rule - * Takes an application state - */ - private Consumer end; - - /* - * Map of pragma names to pragma actions - * Pragma actions are functions taking a tokenizer and application state - */ - private final IMap> pragmas; - - /** - * Create a new rule-based config reader - * - * @param start - * The action to fire when starting a rule - * @param continueRule - * The action to fire when continuing a rule - * @param end - * The action to fire when ending a rule - */ - public RuleBasedConfigReader(final BiConsumer> start, - final BiConsumer continueRule, final Consumer end) { - this.start = start; - this.continueRule = continueRule; - this.end = end; - - this.pragmas = new FunctionalMap<>(); - } - - /** - * Add a pragma to this reader - * - * @param name - * The name of the pragma to add - * @param action - * The function to execute when this pragma is read - */ - public void addPragma(final String name, final BiConsumer action) { - if (name == null) throw new NullPointerException("Pragma name must not be null"); - else if (action == null) throw new NullPointerException("Pragma action must not be null"); - - pragmas.put(name, action); - } - - private void continueRule(final E state, final boolean isRuleOpen, final String line) { - // Make sure our input is correct - if (isRuleOpen == false) - throw new InputMismatchException("Cannot continue rule with no rule open"); - else if (continueRule == null) - throw new InputMismatchException("Rule continuation not supported for current grammar"); - - /* - * Accept the rule - */ - continueRule.accept(new FunctionalStringTokenizer(line.substring(1), " "), state); - } - - private boolean endRule(final E state, final boolean isRuleOpen) { - /* - * Ignore blank line without an open rule - */ - if (isRuleOpen == false) - /* - * Do nothing - */ - return false; - else { - /* - * Nothing happens on rule end - */ - if (end != null) { - /* - * Process the rule ending - */ - end.accept(state); - } - - /* - * Return a closed rule - */ - return false; - } - } - - /** - * Run a stream through this reader - * - * @param input - * The stream to get input - * @param initialState - * The initial state of the reader - * @return The final state of the reader - */ - public E fromStream(final InputStream input, final E initialState) { - if (input == null) throw new NullPointerException("Input stream must not be null"); - - /* - * Application state: We're giving this back later - */ - final E state = initialState; - - /* - * Prepare our input source - */ - try (Scanner source = new Scanner(input)) { - source.useDelimiter("\n"); - /* - * This is true when a rule's open - */ - final IHolder isRuleOpen = new Identity<>(false); - - /* - * Do something for every line of the file - */ - source.forEachRemaining((line) -> { - /* - * Skip comment lines - */ - if (line.startsWith("#") || line.startsWith("//")) - /* - * It's a comment - */ - return; - else if (line.equals("")) { - /* - * End the rule - */ - isRuleOpen.replace(endRule(state, isRuleOpen.getValue())); - } else if (line.startsWith("\t")) { - /* - * Continue the rule - */ - continueRule(state, isRuleOpen.getValue(), line); - } else { - /* - * Open a rule - */ - isRuleOpen.replace(startRule(state, isRuleOpen.getValue(), line)); - } - }); - } - - /* - * Return the state that the user has created - */ - return state; - } - - /** - * Set the action to execute when continuing a rule - * - * @param continueRule - * The action to execute on continuation of a rule - */ - public void setContinueRule(final BiConsumer continueRule) { - this.continueRule = continueRule; - } - - /** - * Set the action to execute when ending a rule - * - * @param end - * The action to execute on ending of a rule - */ - public void setEndRule(final Consumer end) { - this.end = end; - } - - /** - * Set the action to execute when starting a rule - * - * @param start - * The action to execute on starting of a rule - */ - public void setStartRule(final BiConsumer> start) { - if (start == null) throw new NullPointerException("Action on rule start must be non-null"); - - this.start = start; - } - - private boolean startRule(final E state, boolean isRuleOpen, final String line) { - /* - * Create the line tokenizer - */ - final FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(line, " "); - - /* - * Get the initial token - */ - final String nextToken = tokenizer.nextToken(); - - /* - * Handle pragmas - */ - if (nextToken.equals("pragma")) { - /* - * Get the pragma name - */ - final String token = tokenizer.nextToken(); - - /* - * Handle pragmas - */ - pragmas.getOrDefault(token, (tokenzer, stat) -> { - throw new UnknownPragmaException("Unknown pragma " + token); - }).accept(tokenizer, state); - } else { - /* - * Make sure input is correct - */ - if (isRuleOpen == true) - throw new InputMismatchException("Nested rules are currently not supported"); - - /* - * Start a rule - */ - start.accept(tokenizer, new Pair<>(nextToken, state)); - - isRuleOpen = true; - } - - return isRuleOpen; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java deleted file mode 100644 index e26a7ee..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java +++ /dev/null @@ -1,100 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.function.BiConsumer; - -import bjc.utils.exceptions.PragmaFormatException; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcutils.ListUtils; - -/** - * Contains factory methods for common pragma types - * - * @author ben - * - */ -public class RuleBasedReaderPragmas { - - /** - * Creates a pragma that takes a single integer argument - * - * @param - * The type of state that goes along with this pragma - * @param name - * The name of this pragma, for error message purpose - * @param consumer - * The function to invoke with the parsed integer - * @return A pragma that functions as described above. - */ - public static BiConsumer buildInteger(final String name, - final BiConsumer consumer) { - return (tokenizer, state) -> { - /* - * Check our input is correct - */ - if (!tokenizer.hasMoreTokens()) { - String fmt = "Pragma %s requires one integer argument"; - - throw new PragmaFormatException(String.format(fmt, name)); - } - - /* - * Read the argument - */ - final String token = tokenizer.nextToken(); - - try { - /* - * Run the pragma - */ - consumer.accept(Integer.parseInt(token), state); - } catch (final NumberFormatException nfex) { - /* - * Tell the user their argument isn't correct - */ - String fmt = "Argument %s to %s pragma isn't a valid integer, and this pragma requires an integer argument."; - - final PragmaFormatException pfex = new PragmaFormatException(String.format(fmt, token, name)); - - pfex.initCause(nfex); - - throw pfex; - } - }; - } - - /** - * Creates a pragma that takes any number of arguments and collapses - * them all into a single string - * - * @param - * The type of state that goes along with this pragma - * @param name - * The name of this pragma, for error message purpose - * @param consumer - * The function to invoke with the parsed string - * @return A pragma that functions as described above. - */ - public static BiConsumer buildStringCollapser( - final String name, final BiConsumer consumer) { - return (tokenizer, state) -> { - /* - * Check our input - */ - if (!tokenizer.hasMoreTokens()) { - String fmt = "Pragma %s requires one or more string arguments."; - - throw new PragmaFormatException(String.format(fmt, name)); - } - - /* - * Build our argument - */ - final String collapsed = ListUtils.collapseTokens(tokenizer.toList()); - - /* - * Run the pragma - */ - consumer.accept(collapsed, state); - }; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java deleted file mode 100644 index e6279c4..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java +++ /dev/null @@ -1,170 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.InputStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Scanner; -import java.util.Set; - -/** - * Simple file based properties. - * - * @author EVE - * - */ -public class SimpleProperties implements Map { - private final Map props; - - /** - * Create a new set of simple properties. - */ - public SimpleProperties() { - props = new HashMap<>(); - } - - /** - * Load properties from the provided input stream. - * - * The format is the name, a space, then the body. - * - * All leading/trailing spaces from the name & body are removed. - * - * @param is - * The stream to read from. - * - * @param allowDuplicates - * Whether or not duplicate keys should be allowed. - */ - public void loadFrom(final InputStream is, final boolean allowDuplicates) { - try (Scanner scn = new Scanner(is)) { - while (scn.hasNextLine()) { - final String ln = scn.nextLine().trim(); - - /* - * Skip blank lines/comments - */ - if (ln.equals("")) { - continue; - } - if (ln.startsWith("#")) { - continue; - } - - final int sepIdx = ln.indexOf(' '); - - /* - * Complain about improperly formatted lines. - */ - if (sepIdx == -1) { - final String fmt = "Properties must be a name, a space, then the body.\n\tOffending line is '%s'"; - final String msg = String.format(fmt, ln); - - throw new NoSuchElementException(msg); - } - - final String name = ln.substring(0, sepIdx).trim(); - final String body = ln.substring(sepIdx).trim(); - - /* - * Complain about duplicates, if that is wanted. - */ - if (!allowDuplicates && containsKey(name)) { - final String msg = String.format("Duplicate key '%s'", name); - - throw new IllegalStateException(msg); - } - - put(name, body); - } - } - } - - /** - * Output the set of read properties. - */ - public void outputProperties() { - System.out.println("Read properties:"); - - for (final Entry entry : entrySet()) { - System.out.printf("\t'%s'\t'%s'\n", entry.getKey(), entry.getValue()); - } - - System.out.println(); - } - - @Override - public int size() { - return props.size(); - } - - @Override - public boolean isEmpty() { - return props.isEmpty(); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public boolean containsKey(final Object key) { - return props.containsKey(key); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public boolean containsValue(final Object value) { - return props.containsValue(value); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public String get(final Object key) { - return props.get(key); - } - - @Override - public String put(final String key, final String value) { - return props.put(key, value); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public String remove(final Object key) { - return props.remove(key); - } - - @Override - public void putAll(final Map m) { - props.putAll(m); - } - - @Override - public void clear() { - props.clear(); - } - - @Override - public Set keySet() { - return props.keySet(); - } - - @Override - public Collection values() { - return props.values(); - } - - @Override - public Set> entrySet() { - return props.entrySet(); - } - - @Override - public boolean equals(final Object o) { - return props.equals(o); - } - - @Override - public int hashCode() { - return props.hashCode(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java deleted file mode 100644 index 15f3510..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java +++ /dev/null @@ -1,88 +0,0 @@ -package bjc.utils.ioutils.blocks; - -/** - * Represents a block of text read in from a source. - * - * @author EVE - * - */ -public class Block { - /** - * The contents of this block. - */ - public final String contents; - - /** - * The line of the source this block started on. - */ - public final int startLine; - - /** - * The line of the source this block ended on. - */ - public final int endLine; - - /** - * The number of this block. - */ - public final int blockNo; - - /** - * Create a new block. - * - * @param blockNo - * The number of this block. - * @param contents - * The contents of this block. - * @param startLine - * The line this block started on. - * @param endLine - * The line this block ended. - */ - public Block(final int blockNo, final String contents, final int startLine, final int endLine) { - this.contents = contents; - this.startLine = startLine; - this.endLine = endLine; - this.blockNo = blockNo; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + blockNo; - result = prime * result + (contents == null ? 0 : contents.hashCode()); - result = prime * result + endLine; - result = prime * result + startLine; - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Block)) return false; - - final Block other = (Block) obj; - - if (blockNo != other.blockNo) return false; - - if (contents == null) { - if (other.contents != null) return false; - } else if (!contents.equals(other.contents)) return false; - - if (endLine != other.endLine) return false; - if (startLine != other.startLine) return false; - - return true; - } - - @Override - public String toString() { - String fmt = "Block #%d (from lines %d to %d), length: %d characters"; - - return String.format(fmt, blockNo, startLine, endLine, contents.length()); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java deleted file mode 100644 index 3c695c6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java +++ /dev/null @@ -1,73 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.util.Iterator; -import java.util.function.Consumer; - -/** - * A source of blocks of characters, marked with line numbers as to block - * start/block end. - * - * @author bjculkin - * - */ -public interface BlockReader extends AutoCloseable, Iterator { - /** - * Check if this reader has an available block. - * - * @return Whether or not another block is available. - */ - boolean hasNextBlock(); - - /** - * Get the current block. - * - * @return The current block, or null if there is no current block. - */ - Block getBlock(); - - /** - * Move to the next block. - * - * @return Whether or not the next block was successfully read. - */ - boolean nextBlock(); - - /** - * Retrieve the number of blocks that have been read so far. - * - * @return The number of blocks read so far. - */ - int getBlockCount(); - - @Override - void close() throws IOException; - - /* - * Methods with default impls. - */ - - /** - * Execute an action for each remaining block. - * - * @param action - * The action to execute for each block - */ - default void forEachBlock(final Consumer action) { - while (hasNext()) { - action.accept(next()); - } - } - - @Override - default boolean hasNext() { - return hasNextBlock(); - } - - @Override - default Block next() { - nextBlock(); - - return getBlock(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java deleted file mode 100644 index 8bbb89c..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java +++ /dev/null @@ -1,81 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.Reader; - -/** - * Utility methods for constructing instances of {@link BlockReader} - * - * @author bjculkin - * - */ -public class BlockReaders { - /** - * Create a new simple block reader that works off a regex. - * - * @param blockDelim - * The regex that separates blocks. - * - * @param source - * The reader to get blocks from. - * - * @return A configured simple reader. - */ - public static SimpleBlockReader simple(final String blockDelim, final Reader source) { - return new SimpleBlockReader(blockDelim, source); - } - - /** - * Create a new pushback block reader. - * - * @param src - * The block reader to read blocks from. - * - * @return A configured pushback reader. - */ - public static PushbackBlockReader pushback(final BlockReader src) { - return new PushbackBlockReader(src); - } - - /** - * Create a new triggered block reader. - * - * @param source - * The block reader to read blocks from. - * - * @param action - * The action to execute before reading a block. - * - * @return A configured triggered block reader. - */ - public static BlockReader trigger(final BlockReader source, final Runnable action) { - return new TriggeredBlockReader(source, action); - } - - /** - * Create a new layered block reader. - * - * @param primary - * The first source to read blocks from. - * - * @param secondary - * The second source to read blocks from. - * - * @return A configured layered block reader. - */ - public static BlockReader layered(final BlockReader primary, final BlockReader secondary) { - return new LayeredBlockReader(primary, secondary); - } - - /** - * Create a new serial block reader. - * - * @param readers - * The readers to pull from, in the order to pull from - * them. - * - * @return A configured serial block reader. - */ - public static BlockReader serial(final BlockReader... readers) { - return new SerialBlockReader(readers); - } -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java deleted file mode 100644 index b1e82d7..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java +++ /dev/null @@ -1,61 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -public class BoundBlockReader implements BlockReader { - @FunctionalInterface - public interface Closer { - public void close() throws IOException; - } - - private BooleanSupplier checker; - private Supplier getter; - private Closer closer; - - private Block current; - - private int blockNo; - - public BoundBlockReader(BooleanSupplier blockChecker, Supplier blockGetter, Closer blockCloser) { - checker = blockChecker; - getter = blockGetter; - closer = blockCloser; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - return checker.getAsBoolean(); - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - if(checker.getAsBoolean()) { - current = getter.get(); - blockNo += 1; - - return true; - } - - return false; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - closer.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java deleted file mode 100644 index 0b43f7a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java +++ /dev/null @@ -1,97 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.function.Consumer; -import java.util.function.Predicate; - -public class FilteredBlockReader implements BlockReader { - /* - * The source of blocks. - */ - private BlockReader source; - - /* - * The current and next block. - * - * Both have already been checked for the predicate. - */ - private Block current; - private Block pending; - - /* - * Number of blocks that passed the predicate. - */ - private int blockNo; - - /* - * The predicate blocks must pass. - */ - private Predicate pred; - - /* - * The action to call on failure, if there is one. - */ - private Consumer failAction; - - public FilteredBlockReader(BlockReader src, Predicate predic) { - this(src, predic, null); - } - - public FilteredBlockReader(BlockReader src, Predicate predic, Consumer failAct) { - source = src; - pred = predic; - failAction = failAct; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - if(pending != null) return true; - - while(source.hasNextBlock()) { - /* - * Only say we have a next block if the next block would - * pass the predicate. - */ - pending = source.next(); - - if(pred.test(pending)) { - blockNo += 1; - return true; - } else { - failAction.accept(pending); - } - } - - return false; - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - if(pending != null || hasNextBlock()) { - current = pending; - pending = null; - - return true; - } - - return false; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - source.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java deleted file mode 100644 index f4d8439..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java +++ /dev/null @@ -1,86 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.Iterator; -import java.util.List; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -/** - * A block reader that supports applying a flatmap operation to blocks. - * - * The use-case in mind for this was tokenizing blocks. - * - * @author Benjamin Culkin - */ -public class FlatMappedBlockReader implements BlockReader { - /* - * The source reader. - */ - private BlockReader reader; - - /* - * The current block, and any blocks pending from the last source block. - */ - private Iterator pending; - private Block current; - - /* - * The operator to open blocks with. - */ - private Function> transform; - - /* - * The current block number. - */ - private int blockNo; - - public FlatMappedBlockReader(BlockReader source, Function> trans) { - reader = source; - transform = trans; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - return pending.hasNext() || reader.hasNextBlock(); - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - /* - * Attempt to get a new pending list if the one we have isn't - * valid. - */ - while(pending == null || !pending.hasNext()) { - if(!reader.hasNext()) return false; - - pending = transform.apply(reader.next()).iterator(); - } - - /* - * Advance the iterator. - */ - current = pending.next(); - blockNo += 1; - - return true; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - reader.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java deleted file mode 100644 index 967a1f2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java +++ /dev/null @@ -1,81 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -/** - * A block reader that supports draining all the blocks from one reading before - * swapping to another. - * - * This is more a 'prioritize blocks from one over the other', than a 'read all - * the blocks from one, then all the blocks from the other'. If you need that, - * look at {@link SerialBlockReader}. - * - * @author bjculkin - * - */ -public class LayeredBlockReader implements BlockReader { - /* - * The readers to drain from. - */ - private final BlockReader first; - private final BlockReader second; - - /* - * The current block number. - */ - private int blockNo; - - /** - * Create a new layered block reader. - * - * @param primary - * The first source to read blocks from. - * - * @param secondary - * The second source to read blocks from. - */ - public LayeredBlockReader(final BlockReader primary, final BlockReader secondary) { - first = primary; - second = secondary; - } - - @Override - public boolean hasNextBlock() { - return first.hasNextBlock() || second.hasNextBlock(); - } - - @Override - public Block getBlock() { - final Block firstBlock = first.getBlock(); - - /* - * Only drain a block from the second reader if none are - * available in the first reader. - */ - return firstBlock == null ? second.getBlock() : firstBlock; - } - - @Override - public boolean nextBlock() { - final boolean gotFirst = first.nextBlock(); - final boolean succ = gotFirst ? gotFirst : second.nextBlock(); - - if (succ) { - blockNo += 1; - } - - return succ; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - second.close(); - - first.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java deleted file mode 100644 index 12fa848..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.function.UnaryOperator; - -public class MappedBlockReader implements BlockReader { - private BlockReader reader; - - private Block current; - - private UnaryOperator transform; - - private int blockNo; - - public MappedBlockReader(BlockReader source, UnaryOperator trans) { - reader = source; - transform = trans; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - return reader.hasNextBlock(); - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - if(hasNextBlock()) { - current = transform.apply(reader.next()); - blockNo += 1; - - return true; - } - - return false; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - reader.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java deleted file mode 100644 index 0cc9dea..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java +++ /dev/null @@ -1,106 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.util.Deque; -import java.util.LinkedList; - -/** - * A block reader that supports pushing blocks onto the input queue so that they - * are provided before blocks read from an input source. - * - * @author bjculkin - * - */ -public class PushbackBlockReader implements BlockReader { - private final BlockReader source; - - /* - * The queue of pushed-back blocks. - */ - private final Deque waiting; - - private Block curBlock; - - private int blockNo; - - /** - * Create a new pushback block reader. - * - * @param src - * The block reader to use when no blocks are queued. - */ - public PushbackBlockReader(final BlockReader src) { - source = src; - - waiting = new LinkedList<>(); - } - - @Override - public boolean hasNextBlock() { - return !waiting.isEmpty() || source.hasNextBlock(); - } - - @Override - public Block getBlock() { - return curBlock; - } - - @Override - public boolean nextBlock() { - /* - * Drain pushed-back blocks first. - */ - if (!waiting.isEmpty()) { - curBlock = waiting.pop(); - - blockNo += 1; - - return true; - } else { - final boolean succ = source.nextBlock(); - curBlock = source.getBlock(); - - if (succ) { - blockNo += 1; - } - - return succ; - } - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - source.close(); - } - - /** - * Insert a block at the back of the queue of pending blocks. - * - * @param blk - * The block to put at the back. - */ - public void addBlock(final Block blk) { - waiting.add(blk); - } - - /** - * Insert a block at the front of the queue of pending blocks. - * - * @param blk - * The block to put at the front. - */ - public void pushBlock(final Block blk) { - waiting.push(blk); - } - - @Override - public String toString() { - return String.format("PushbackBlockReader [waiting=%s, curBlock=%s, blockNo=%s]", waiting, curBlock, - blockNo); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java deleted file mode 100644 index c229da1..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java +++ /dev/null @@ -1,102 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.util.Deque; - -/** - * Provides a means of concatenating two block readers. - * - * @author bjculkin - * - */ -public class SerialBlockReader implements BlockReader { - private Deque readerQueue; - - private int blockNo; - - /** - * Create a new serial block reader. - * - * @param readers - * The readers to pull from, in the order to pull from - * them. - */ - public SerialBlockReader(final BlockReader... readers) { - for (final BlockReader reader : readers) { - readerQueue.add(reader); - } - } - - @Override - public boolean hasNextBlock() { - if (readerQueue.isEmpty()) return false; - - /* - * Attempt to get a block from the first reader. - */ - boolean hasBlock = readerQueue.peek().hasNextBlock(); - boolean cont = hasBlock || readerQueue.isEmpty(); - - /* - * Close/dispose of readers until we get an open one. - */ - while (!cont) { - try { - readerQueue.pop().close(); - } catch (final IOException ioex) { - throw new IllegalStateException("Exception thrown by discarded reader", ioex); - } - - hasBlock = readerQueue.peek().hasNextBlock(); - cont = hasBlock || readerQueue.isEmpty(); - } - - return hasBlock; - } - - @Override - public Block getBlock() { - if (readerQueue.isEmpty()) - return null; - else return readerQueue.peek().getBlock(); - } - - @Override - public boolean nextBlock() { - if (readerQueue.isEmpty()) return false; - - boolean gotBlock = readerQueue.peek().nextBlock(); - boolean cont = gotBlock || readerQueue.isEmpty(); - - while (!cont) { - try { - readerQueue.pop().close(); - } catch (final IOException ioex) { - throw new IllegalStateException("Exception thrown by discarded reader", ioex); - } - - gotBlock = readerQueue.peek().nextBlock(); - cont = gotBlock || readerQueue.isEmpty(); - } - - if (cont) { - blockNo += 1; - } - - return cont; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - while (!readerQueue.isEmpty()) { - final BlockReader reader = readerQueue.pop(); - - reader.close(); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java deleted file mode 100644 index 734bde8..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java +++ /dev/null @@ -1,115 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.Reader; -import java.util.NoSuchElementException; -import java.util.Scanner; -import java.util.regex.Pattern; - -import bjc.utils.funcutils.StringUtils; -/** - * Simple implementation of {@link BlockReader} - * - * NOTE: The EOF marker is always treated as a delimiter. You are expected to - * handle blocks that may be shorter than you expect. - * - * @author EVE - * - */ -public class SimpleBlockReader implements BlockReader { - /* - * I/O source for blocks. - */ - private final Scanner blockReader; - - /* - * The current block. - */ - private Block currBlock; - - /* - * Info about the current block. - */ - private int blockNo; - private int lineNo; - - /** - * Create a new block reader. - * - * @param blockDelim - * The pattern that separates blocks. Note that the end - * of file is always considered to end a block. - * - * @param source - * The source to read blocks from. - */ - public SimpleBlockReader(final String blockDelim, final Reader source) { - blockReader = new Scanner(source); - - final String pattern = String.format("(?:%s)|\\Z", blockDelim); - final Pattern pt = Pattern.compile(pattern, Pattern.MULTILINE); - - blockReader.useDelimiter(pt); - - lineNo = 1; - } - - @Override - public boolean hasNextBlock() { - return blockReader.hasNext(); - } - - @Override - public Block getBlock() { - return currBlock; - } - - @Override - public boolean nextBlock() { - try { - /* - * Read in a new block, and keep the line numbers sane. - */ - final int blockStartLine = lineNo; - final String blockContents = blockReader.next(); - final int blockEndLine = lineNo + StringUtils.countMatches(blockContents, "\\R"); - - lineNo = blockEndLine; - blockNo += 1; - - currBlock = new Block(blockNo, blockContents, blockStartLine, blockEndLine); - - return true; - } catch (final NoSuchElementException nseex) { - currBlock = null; - - return false; - } - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - blockReader.close(); - } - - /** - * Set the delimiter used to separate blocks. - * - * @param delim - * The delimiter used to separate blocks. - */ - public void setDelimiter(final String delim) { - blockReader.useDelimiter(delim); - } - - @Override - public String toString() { - return String.format("SimpleBlockReader [currBlock=%s, blockNo=%s]", currBlock, blockNo); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java deleted file mode 100644 index 8f39b8f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java +++ /dev/null @@ -1,63 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import bjc.utils.data.BooleanToggle; - -public class ToggledBlockReader implements BlockReader { - private BlockReader leftSource; - private BlockReader rightSource; - - /* - * We choose the left source when this is true. - */ - private BooleanToggle leftToggle; - - private int blockNo; - - public ToggledBlockReader(BlockReader left, BlockReader right) { - leftSource = left; - rightSource = right; - - blockNo = 0; - - leftToggle = new BooleanToggle(); - } - - @Override - public boolean hasNextBlock() { - if(leftToggle.peek()) return leftSource.hasNextBlock(); - else return rightSource.hasNextBlock(); - } - - @Override - public Block getBlock() { - if(leftToggle.peek()) return leftSource.getBlock(); - else return rightSource.getBlock(); - } - - @Override - public boolean nextBlock() { - boolean succ; - - if(leftToggle.get()) { - succ = leftSource.nextBlock(); - } else { - succ = rightSource.nextBlock(); - } - - if(succ) blockNo += 1; - return succ; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - leftSource.close(); - rightSource.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java deleted file mode 100644 index 3a1e393..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java +++ /dev/null @@ -1,70 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -/** - * A block reader that fires an action before a block is actually read. - * - * @author bjculkin - * - */ -public class TriggeredBlockReader implements BlockReader { - private final BlockReader source; - - private int blockNo; - - /* - * The action to fire. - */ - private final Runnable action; - - /** - * Create a new triggered reader with the specified source/action. - * - * @param source - * The block reader to read blocks from. - * - * @param action - * The action to execute before reading a block. - */ - public TriggeredBlockReader(final BlockReader source, final Runnable action) { - this.source = source; - this.action = action; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - action.run(); - - return source.hasNextBlock(); - } - - @Override - public Block getBlock() { - return source.getBlock(); - } - - @Override - public boolean nextBlock() { - blockNo += 1; - - return source.nextBlock(); - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - source.close(); - } - - @Override - public String toString() { - return String.format("TriggeredBlockReader [source=%s]", source); - } -} -- cgit v1.2.3