summaryrefslogtreecommitdiff
path: root/base/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'base/src/main/java')
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java122
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java627
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/CLParameters.java93
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/CharacterDirective.java34
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/ConditionalDirective.java117
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/Directive.java26
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/EscapeDirective.java42
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/FreshlineDirective.java25
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/GeneralNumberDirective.java45
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/GotoDirective.java37
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/IterationDirective.java78
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/LiteralDirective.java33
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java80
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/RadixDirective.java44
-rw-r--r--base/src/main/java/bjc/utils/math/NumberUtils.java (renamed from base/src/main/java/bjc/utils/ioutils/NumberUtils.java)2
15 files changed, 812 insertions, 593 deletions
diff --git a/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java b/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java
index 869834b..9cc10d2 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java
@@ -1,61 +1,61 @@
-package bjc.utils.ioutils.format;
-
-import java.util.regex.Matcher;
-
-import bjc.utils.esodata.Tape;
-
-public class AestheticDirective implements Directive {
-
- @Override
- public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
- Matcher dirMatcher) {
- CLFormatter.checkItem(item, 'A');
-
- 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);
- }
- }
- }
-
- tParams.right();
- }
-
-}
+package bjc.utils.ioutils.format;
+
+import java.util.regex.Matcher;
+
+import bjc.utils.esodata.Tape;
+
+class AestheticDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ CLFormatter.checkItem(item, 'A');
+
+ 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);
+ }
+ }
+ }
+
+ tParams.right();
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java b/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java
index 8abc0ff..408bb3b 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java
@@ -1,456 +1,171 @@
-package bjc.utils.ioutils.format;
-
-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.esodata.Tape;
-import bjc.utils.ioutils.NumberUtils;
-import bjc.utils.esodata.SingleTape;
-
-import static bjc.utils.PropertyDB.applyFormat;
-
-import static bjc.utils.PropertyDB.getRegex;
-
-public class CLFormatter {
- 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 static Map<String, Directive> builtinDirectives;
- private Map<String, Directive> extraDirectives;
-
- static {
- builtinDirectives = new HashMap<>();
-
- builtinDirectives.put("A", new AestheticDirective());
- }
-
- public CLFormatter() {
- extraDirectives = new HashMap<>();
- }
-
- public static 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;
- }
-
- if (builtinDirectives.containsKey(dirName)) {
- builtinDirectives.get(dirName).format(sb, item, mods, arrParams, tParams, dirMatcher);
- }
-
- switch (dirName) {
- 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 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);
- }
-
-}
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.SingleTape;
+import bjc.utils.esodata.Tape;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UnknownFormatConversionException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static bjc.utils.PropertyDB.applyFormat;
+import static bjc.utils.PropertyDB.getRegex;
+
+/**
+ * An implementation of CL's FORMAT.
+ *
+ * @author EVE
+ *
+ */
+public class CLFormatter {
+ private static final String prefixParam = getRegex("clFormatPrefix");
+
+ 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 static Map<String, Directive> builtinDirectives;
+
+ private Map<String, Directive> extraDirectives;
+
+ static {
+ builtinDirectives = new HashMap<>();
+
+ builtinDirectives.put("A", new AestheticDirective());
+
+ builtinDirectives.put("C", new CharacterDirective());
+
+ builtinDirectives.put("B", new NumberDirective(-1, 2));
+ builtinDirectives.put("O", new NumberDirective(-1, 8));
+ builtinDirectives.put("D", new NumberDirective(-1, 10));
+ builtinDirectives.put("X", new NumberDirective(-1, 16));
+
+ builtinDirectives.put("R", new RadixDirective());
+
+ builtinDirectives.put("&", new FreshlineDirective());
+
+ builtinDirectives.put("%", new LiteralDirective("\n", '%'));
+ builtinDirectives.put("|", new LiteralDirective("\f", '|'));
+ builtinDirectives.put("~", new LiteralDirective("~", '~'));
+
+ builtinDirectives.put("*", new GotoDirective());
+
+ builtinDirectives.put("^", new EscapeDirective());
+ builtinDirectives.put("[", new ConditionalDirective());
+ }
+
+ /**
+ * Create a new CL formatter.
+ */
+ public CLFormatter() {
+ extraDirectives = new HashMap<>();
+ }
+
+ static void checkItem(Object itm, char directive) {
+ if(itm == null) throw new IllegalArgumentException(
+ String.format("No argument provided for %c directive", directive));
+ }
+
+ /**
+ * Format a string in the style of CL's FORMAT.
+ *
+ * @param format
+ * The format string to use.
+ * @param params
+ * The parameters for the string.
+ * @return The formatted string.
+ */
+ 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();
+ }
+
+ 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;
+ }
+
+ if(extraDirectives.containsKey(dirName)) {
+ extraDirectives.get(dirName).format(sb, item, mods, arrParams, tParams, dirMatcher,
+ this);
+
+ continue;
+ }
+
+ if(builtinDirectives.containsKey(dirName)) {
+ builtinDirectives.get(dirName).format(sb, item, mods, arrParams, tParams, dirMatcher,
+ this);
+
+ continue;
+ }
+
+ if(dirName == null) dirName = "<null>";
+
+ switch(dirName) {
+ 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);
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java b/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java
index e3a03f6..5bdcbbf 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java
@@ -13,10 +13,21 @@ import bjc.utils.esodata.Tape;
public class CLParameters {
private String[] params;
+ /**
+ * Create a new set of CL format parameters.
+ *
+ * @param params
+ * The CL format parameters to use.
+ */
public CLParameters(String[] params) {
this.params = params;
}
+ /**
+ * Get the length of the parameter list.
+ *
+ * @return The length of the parameters.
+ */
public int length() {
return params.length;
}
@@ -27,34 +38,34 @@ public class CLParameters {
* Mostly, this just fills in V and # parameters.
*
* @param params
- * The parameters of the directive.
+ * The parameters of the directive.
* @param dirParams
- * The parameters of the format string.
+ * 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")) {
+ for(String param : params) {
+ if(param.equalsIgnoreCase("V")) {
Object par = dirParams.item();
boolean succ = dirParams.right();
- if (!succ) {
+ if(!succ) {
throw new IllegalStateException("Couldn't advance tape for parameter");
}
- if (par == null) {
+ if(par == null) {
throw new IllegalArgumentException(
"Expected a format parameter for V inline parameter");
}
- if (par instanceof Number) {
+ if(par instanceof Number) {
int val = ((Number) par).intValue();
parameters.add(Integer.toString(val));
- } else if (par instanceof Character) {
+ } else if(par instanceof Character) {
char ch = ((Character) par);
parameters.add(Character.toString(ch));
@@ -62,7 +73,7 @@ public class CLParameters {
throw new IllegalArgumentException(
"Incorrect type of parameter for V inline parameter");
}
- } else if (param.equals("#")) {
+ } else if(param.equals("#")) {
parameters.add(Integer.toString(dirParams.position()));
} else {
parameters.add(param);
@@ -72,39 +83,89 @@ public class CLParameters {
return new CLParameters(parameters.toArray(new String[0]));
}
+ /**
+ * Get an optional character parameter with a default value.
+ *
+ * @param idx
+ * The index the parameter is at.
+ * @param paramName
+ * The name of the parameter.
+ * @param directive
+ * The directive this parameter belongs to.
+ * @param def
+ * The default value for the parameter.
+ * @return The value of the parameter if it exists, or the default
+ * otherwise.
+ */
public char getCharDefault(int idx, String paramName, char directive, char def) {
- if (!params[idx].equals("")) {
+ if(!params[idx].equals("")) {
return getChar(idx, paramName, directive);
}
return def;
}
+ /**
+ * Get a mandatory character parameter.
+ *
+ * @param idx
+ * The index the parameter is at.
+ * @param paramName
+ * The name of the parameter.
+ * @param directive
+ * The directive this parameter belongs to.
+ * @return The value for the parameter.
+ */
public char getChar(int idx, String paramName, char directive) {
String param = params[idx];
- if (!param.startsWith("'")) {
+ if(!param.startsWith("'")) {
throw new IllegalArgumentException(
String.format("Invalid %s %s to %c directive", paramName, param, directive));
}
return param.charAt(1);
}
-
+
+ /**
+ * Get an optional integer parameter with a default value.
+ *
+ * @param idx
+ * The index the parameter is at.
+ * @param paramName
+ * The name of the parameter.
+ * @param directive
+ * The directive this parameter belongs to.
+ * @param def
+ * The default value for the parameter.
+ * @return The value of the parameter if it exists, or the default
+ * otherwise.
+ */
public int getIntDefault(int idx, String paramName, char directive, int def) {
- if (!params[idx].equals("")) {
-
+ if(!params[idx].equals("")) {
+ return getInt(idx, paramName, directive);
}
return def;
}
-
+
+ /**
+ * Get a mandatory integer parameter.
+ *
+ * @param idx
+ * The index the parameter is at.
+ * @param paramName
+ * The name of the parameter.
+ * @param directive
+ * The directive this parameter belongs to.
+ * @return The value for the parameter.
+ */
public int getInt(int idx, String paramName, char directive) {
String param = params[idx];
try {
return Integer.parseInt(param);
- } catch (NumberFormatException nfex) {
+ } catch(NumberFormatException nfex) {
String msg = String.format("Invalid %s %s to %c directive", paramName, param, directive);
IllegalArgumentException iaex = new IllegalArgumentException(msg);
diff --git a/base/src/main/java/bjc/utils/ioutils/format/CharacterDirective.java b/base/src/main/java/bjc/utils/ioutils/format/CharacterDirective.java
new file mode 100644
index 0000000..7ff74bb
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/CharacterDirective.java
@@ -0,0 +1,34 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.IllegalFormatConversionException;
+import java.util.regex.Matcher;
+
+class CharacterDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer buff, Object parm, CLModifiers mods, CLParameters arrParams,
+ Tape<Object> tParams, Matcher dirMatcher, CLFormatter fmt) {
+ CLFormatter.checkItem(parm, 'C');
+
+ if(!(parm instanceof Character)) {
+ throw new IllegalFormatConversionException('C', parm.getClass());
+ }
+
+ char ch = (Character) parm;
+ int codepoint = ch;
+
+ if(mods.colonMod) {
+ /*
+ * Colon mod means print Unicode character name.
+ */
+ buff.append(Character.getName(codepoint));
+ } else {
+ buff.append(ch);
+ }
+
+ tParams.right();
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/ConditionalDirective.java b/base/src/main/java/bjc/utils/ioutils/format/ConditionalDirective.java
new file mode 100644
index 0000000..5ae842c
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/ConditionalDirective.java
@@ -0,0 +1,117 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.ArrayList;
+import java.util.IllegalFormatConversionException;
+import java.util.List;
+import java.util.regex.Matcher;
+
+class ConditionalDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams,
+ Tape<Object> formatParams, Matcher dirMatcher, CLFormatter fmt) {
+ 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 frmt;
+ if(res)
+ frmt = clauses.get(1);
+ else
+ frmt = clauses.get(0);
+
+ fmt.doFormatString(frmt, 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) {
+ fmt.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) fmt.doFormatString(defClause, sb, formatParams);
+ } else {
+ fmt.doFormatString(clauses.get(res), sb, formatParams);
+ }
+ }
+ return;
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/Directive.java b/base/src/main/java/bjc/utils/ioutils/format/Directive.java
index aa6695f..0b1e889 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/Directive.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/Directive.java
@@ -1,14 +1,14 @@
-package bjc.utils.ioutils.format;
-
-import java.util.regex.Matcher;
-
-import bjc.utils.esodata.Tape;
-
-@FunctionalInterface
-public interface Directive {
- /*
- * @TODO fill in parameters
- */
- public void format(StringBuffer sb, Object item, CLModifiers mods,
- CLParameters arrParams, Tape<Object> tParams, Matcher dirMatcher);
+package bjc.utils.ioutils.format;
+
+import java.util.regex.Matcher;
+
+import bjc.utils.esodata.Tape;
+
+@FunctionalInterface
+public interface Directive {
+ /*
+ * @TODO fill in parameters
+ */
+ public void format(StringBuffer sb, Object item, CLModifiers mods,
+ CLParameters arrParams, Tape<Object> tParams, Matcher dirMatcher, CLFormatter fmt);
} \ No newline at end of file
diff --git a/base/src/main/java/bjc/utils/ioutils/format/EscapeDirective.java b/base/src/main/java/bjc/utils/ioutils/format/EscapeDirective.java
new file mode 100644
index 0000000..4f44479
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/EscapeDirective.java
@@ -0,0 +1,42 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.regex.Matcher;
+
+class EscapeDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape<Object> formatParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ 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/base/src/main/java/bjc/utils/ioutils/format/FreshlineDirective.java b/base/src/main/java/bjc/utils/ioutils/format/FreshlineDirective.java
new file mode 100644
index 0000000..8ae0c72
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/FreshlineDirective.java
@@ -0,0 +1,25 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.regex.Matcher;
+
+class FreshlineDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer buff, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ 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");
+ }
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/GeneralNumberDirective.java b/base/src/main/java/bjc/utils/ioutils/format/GeneralNumberDirective.java
new file mode 100644
index 0000000..6a90f94
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/GeneralNumberDirective.java
@@ -0,0 +1,45 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.math.NumberUtils;
+
+abstract class GeneralNumberDirective implements Directive {
+ protected static 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', ' ');
+ }
+
+ String res;
+
+ 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);
+ }
+
+ res = NumberUtils.toCommaString(val, mincol, padchar, commaInterval, commaChar, mods.atMod,
+ radix);
+ } else {
+ res = NumberUtils.toNormalString(val, mincol, padchar, mods.atMod, radix);
+ }
+
+ buff.append(res);
+ }
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/GotoDirective.java b/base/src/main/java/bjc/utils/ioutils/format/GotoDirective.java
new file mode 100644
index 0000000..b09053e
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/GotoDirective.java
@@ -0,0 +1,37 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.regex.Matcher;
+
+class GotoDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape<Object> formatParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ 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);
+ }
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/IterationDirective.java b/base/src/main/java/bjc/utils/ioutils/format/IterationDirective.java
new file mode 100644
index 0000000..353ff94
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/IterationDirective.java
@@ -0,0 +1,78 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.ArrayList;
+import java.util.IllegalFormatConversionException;
+import java.util.List;
+import java.util.regex.Matcher;
+
+class IterationDirective implements Directive {
+
+ @Override
+ public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ CLFormatter.checkItem(item, '{');
+
+ StringBuffer condBody = new StringBuffer();
+
+ while(dirMatcher.find()) {
+ /* Process a list of clauses. */
+ String dirName = dirMatcher.group("name");
+
+ if(dirName != null) {
+ /* Append everything up to this directive. */
+ dirMatcher.appendReplacement(condBody, "");
+
+ if(dirName.equals("}")) {
+ /* End the iteration. */
+ break;
+ }
+
+ /* Not a special directive. */
+ condBody.append(dirMatcher.group());
+ }
+ }
+
+ String frmt = condBody.toString();
+ Object iter = item;
+
+ if(frmt.equals("")) {
+ /* Grab an argument. */
+ if(!(item instanceof String)) {
+ throw new IllegalFormatConversionException('{', String.class);
+ }
+
+ frmt = (String) item;
+
+ if(!tParams.right()) {
+ throw new IllegalArgumentException("Not enough parameters to '{' directive");
+ }
+
+ iter = tParams.item();
+ }
+
+ int maxItr = Integer.MAX_VALUE;
+
+ if(arrParams.length() > 0) {
+ maxItr = arrParams.getInt(0, "maximum iterations", '{');
+ }
+
+ if(mods.atMod && mods.colonMod) {
+
+ } else if(mods.atMod) {
+
+ } else if(mods.colonMod) {
+ if(!(item instanceof Iterable<?>)) {
+ throw new IllegalFormatConversionException('{', item.getClass());
+ }
+ } else {
+ if(!(item instanceof Iterable<?>)) {
+ throw new IllegalFormatConversionException('{', item.getClass());
+ }
+ }
+
+ tParams.right();
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/LiteralDirective.java b/base/src/main/java/bjc/utils/ioutils/format/LiteralDirective.java
new file mode 100644
index 0000000..77d26cc
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/LiteralDirective.java
@@ -0,0 +1,33 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+
+import java.util.regex.Matcher;
+
+class LiteralDirective implements Directive {
+
+ private char directive;
+ private String lit;
+
+ public LiteralDirective(String lit, char directive) {
+ this.directive = directive;
+ this.lit = lit;
+ }
+
+
+ @Override
+ public void format(StringBuffer buff, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ int nTimes = 1;
+
+ if(params.length() > 1) {
+ nTimes = params.getInt(0, "occurance count", directive);
+ }
+
+ for(int i = 0; i < nTimes; i++) {
+ buff.append(lit);
+ }
+
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java b/base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java
index d5d4b29..28e61ea 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java
@@ -1,46 +1,34 @@
-package bjc.utils.ioutils.format;
-
-import java.util.regex.Matcher;
-
-import bjc.utils.esodata.Tape;
-import bjc.utils.ioutils.NumberUtils;
-
-public class NumberDirective implements Directive {
-
- @Override
- public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
- Matcher dirMatcher) {
- /*
- * 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);
- }
- }
-
-}
+package bjc.utils.ioutils.format;
+
+import java.util.IllegalFormatConversionException;
+import java.util.regex.Matcher;
+
+import bjc.utils.esodata.Tape;
+
+class NumberDirective extends GeneralNumberDirective {
+
+ public NumberDirective(int argidx, int radix) {
+ this.argidx = argidx;
+ this.radix = radix;
+ }
+
+ private int argidx;
+ private int radix;
+
+ @Override
+ public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ CLFormatter.checkItem(item, 'B');
+
+ if(!(item instanceof Number)) {
+ throw new IllegalFormatConversionException('B', item.getClass());
+ }
+
+ long val = ((Number) item).longValue();
+
+ handleNumberDirective(sb, mods, params, argidx, val, radix);
+
+ tParams.right();
+ }
+
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/RadixDirective.java b/base/src/main/java/bjc/utils/ioutils/format/RadixDirective.java
new file mode 100644
index 0000000..3742582
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/RadixDirective.java
@@ -0,0 +1,44 @@
+package bjc.utils.ioutils.format;
+
+import bjc.utils.esodata.Tape;
+import bjc.utils.math.NumberUtils;
+
+import java.util.IllegalFormatConversionException;
+import java.util.regex.Matcher;
+
+class RadixDirective extends GeneralNumberDirective {
+
+ @Override
+ public void format(StringBuffer buff, Object arg, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) {
+ CLFormatter.checkItem(arg, 'R');
+
+ 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(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);
+ }
+
+ tParams.right();
+ }
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/NumberUtils.java b/base/src/main/java/bjc/utils/math/NumberUtils.java
index 1b754e2..9391040 100644
--- a/base/src/main/java/bjc/utils/ioutils/NumberUtils.java
+++ b/base/src/main/java/bjc/utils/math/NumberUtils.java
@@ -1,4 +1,4 @@
-package bjc.utils.ioutils;
+package bjc.utils.math;
import java.util.Map;
import java.util.function.BiFunction;