diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 22:39:59 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 22:39:59 -0300 |
| commit | c82e3b3b2de0633317ec8fc85925e91422820597 (patch) | |
| tree | 96567416ce23c5ce85601f9cedc3a94bb1c55cba /BJC-Utils2/src/main/java/bjc/utils/ioutils | |
| parent | b3ac1c8690c3e14c879913e5dcc03a5f5e14876e (diff) | |
Start splitting into maven modules
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/ioutils')
21 files changed, 0 insertions, 2934 deletions
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<String, Directive> 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<Object> tParams = new SingleTape(params);
-
- doFormatString(format, sb, tParams);
-
- return sb.toString();
- }
-
- private void doFormatString(String format, StringBuffer sb, Tape<Object> 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("(?<!'),"), tParams);
- CLModifiers mods = CLModifiers.fromString(dirMods);
-
- Object item = tParams.item();
- if(dirName == null && dirFunc != null) {
- /*
- * @TODO implement user-called functions.
- */
- continue;
- }
-
- switch(dirName) {
- case "A":
- checkItem(item, 'A');
- handleAestheticDirective(sb, item, mods, arrParams);
- tParams.right();
- break;
- case "B":
- checkItem(item, 'B');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('B', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 2);
- tParams.right();
- break;
- case "C":
- checkItem(item, 'C');
- handleCDirective(sb, item, mods);
- tParams.right();
- break;
- case "D":
- checkItem(item, 'D');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('D', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 10);
- tParams.right();
- break;
- case "O":
- checkItem(item, 'O');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('O', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 8);
- tParams.right();
- break;
- case "R":
- checkItem(item, 'R');
- handleRadixDirective(sb, mods, arrParams, item);
- tParams.right();
- break;
- case "X":
- checkItem(item, 'X');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('X', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 16);
- tParams.right();
- break;
- case "&":
- handleFreshlineDirective(sb, arrParams);
- break;
- case "%":
- handleLiteralDirective(sb, arrParams, "\n", '%');
- break;
- case "|":
- handleLiteralDirective(sb, arrParams, "\f", '|');
- break;
- case "~":
- handleLiteralDirective(sb, arrParams, "~", '~');
- break;
- case "*":
- handleGotoDirective(mods, arrParams, tParams);
- break;
- case "^":
- handleEscapeDirective(mods, arrParams, tParams);
- break;
- case "[":
- handleConditionalDirective(sb, mods, arrParams, tParams, dirMatcher);
- break;
- case "]":
- throw new IllegalArgumentException("Found conditional-end outside of conditional.");
- case ";":
- throw new IllegalArgumentException("Found conditional-seperator outside of conditional.");
- case "T":
- case "<":
- case ">":
- /* @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<Object> 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<Object> formatParams, Matcher dirMatcher) {
- StringBuffer condBody = new StringBuffer();
-
- List<String> 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<Object> 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<Object> dirParams) { - List<String> 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<Long, String> customNumbers; - public final Map<LongPredicate, BiFunction<Long, CardinalState, String>> customScales; - - public CardinalState(Map<Long, String> customNumbers, Map<LongPredicate, BiFunction<Long, CardinalState, String>> customScales) { - this.customNumbers = customNumbers; - this.customScales = customScales; - } - - public String handleCustom(long number) { - if(customNumbers.containsKey(number)) { - return customNumbers.get(number); - } - - for(Entry<LongPredicate, BiFunction<Long, CardinalState, String>> 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<String> 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<String> 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<String> 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<String> betweenAction, final UnaryOperator<String> onAction) { - /* - * Get all of the occurances. - */ - final IList<String> occurances = listOccurances(input, rPatt); - - /* - * Execute the correct action on every occurance. - */ - final Toggle<UnaryOperator<String>> actions = new ValueToggle<>(onAction, betweenAction); - final BiFunction<String, StringBuilder, StringBuilder> 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<String> mapOccurances(final String input, final Pattern rPatt, - final UnaryOperator<String> betweenAction, final UnaryOperator<String> onAction) { - /* - * Get all of the occurances. - */ - final IList<String> occurances = listOccurances(input, rPatt); - - /* - * Execute the correct action on every occurance. - */ - final Toggle<UnaryOperator<String>> 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<String> listOccurances(final String input, final Pattern rPatt) { - final IList<String> 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<String> 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<String> 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 <E> - * The type of the state object to use - * - */ -public class RuleBasedConfigReader<E> { - /* Function to execute when starting a rule. - * Takes the tokenizer, and a pair of the read token and application state - */ - private BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start; - - /* - * Function to use when continuing a rule - * Takes a tokenizer and application state - */ - private BiConsumer<FunctionalStringTokenizer, E> continueRule; - - /* - * Function to use when ending a rule - * Takes an application state - */ - private Consumer<E> end; - - /* - * Map of pragma names to pragma actions - * Pragma actions are functions taking a tokenizer and application state - */ - private final IMap<String, BiConsumer<FunctionalStringTokenizer, E>> 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<FunctionalStringTokenizer, IPair<String, E>> start, - final BiConsumer<FunctionalStringTokenizer, E> continueRule, final Consumer<E> 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<FunctionalStringTokenizer, E> 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<Boolean> 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<FunctionalStringTokenizer, E> 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<E> 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<FunctionalStringTokenizer, IPair<String, E>> 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 <StateType> - * 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 <StateType> BiConsumer<FunctionalStringTokenizer, StateType> buildInteger(final String name, - final BiConsumer<Integer, StateType> 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 <StateType> - * 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 <StateType> BiConsumer<FunctionalStringTokenizer, StateType> buildStringCollapser( - final String name, final BiConsumer<String, StateType> 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<String, String> { - private final Map<String, String> 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<String, String> 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<? extends String, ? extends String> m) { - props.putAll(m); - } - - @Override - public void clear() { - props.clear(); - } - - @Override - public Set<String> keySet() { - return props.keySet(); - } - - @Override - public Collection<String> values() { - return props.values(); - } - - @Override - public Set<java.util.Map.Entry<String, String>> 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<Block> { - /** - * 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<Block> 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<Block> getter; - private Closer closer; - - private Block current; - - private int blockNo; - - public BoundBlockReader(BooleanSupplier blockChecker, Supplier<Block> 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<Block> pred; - - /* - * The action to call on failure, if there is one. - */ - private Consumer<Block> failAction; - - public FilteredBlockReader(BlockReader src, Predicate<Block> predic) { - this(src, predic, null); - } - - public FilteredBlockReader(BlockReader src, Predicate<Block> predic, Consumer<Block> 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<Block> pending; - private Block current; - - /* - * The operator to open blocks with. - */ - private Function<Block, List<Block>> transform; - - /* - * The current block number. - */ - private int blockNo; - - public FlatMappedBlockReader(BlockReader source, Function<Block, List<Block>> 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<Block> transform; - - private int blockNo; - - public MappedBlockReader(BlockReader source, UnaryOperator<Block> 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<Block> 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<BlockReader> 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); - } -} |
