From 0b373102f64fd7bfd25837a24ffb4ccb44b9d7e9 Mon Sep 17 00:00:00 2001 From: bjculkin Date: Thu, 1 Mar 2018 14:16:15 -0500 Subject: Finish most of CL formatting. There are a couple of unimplemented directives, but the only ones I'd consider anywhere near crucial would be the floating-point ones, which I'm not sure what I should do with them. --- .../bjc/utils/data/TopDownTransformIterator.java | 141 +++++++++++++-------- .../main/java/bjc/utils/esodata/SingleTape.java | 14 ++ .../main/java/bjc/utils/funcutils/StringUtils.java | 19 +++ .../utils/ioutils/format/AestheticDirective.java | 61 --------- .../java/bjc/utils/ioutils/format/CLFormatter.java | 56 +++++++- .../utils/ioutils/format/CharacterDirective.java | 34 ----- .../utils/ioutils/format/ConditionalDirective.java | 117 ----------------- .../java/bjc/utils/ioutils/format/Directive.java | 35 ----- .../bjc/utils/ioutils/format/EscapeDirective.java | 42 ------ .../utils/ioutils/format/FreshlineDirective.java | 25 ---- .../ioutils/format/GeneralNumberDirective.java | 45 ------- .../bjc/utils/ioutils/format/GotoDirective.java | 37 ------ .../utils/ioutils/format/IterationDirective.java | 76 ----------- .../bjc/utils/ioutils/format/LiteralDirective.java | 32 ----- .../bjc/utils/ioutils/format/NumberDirective.java | 34 ----- .../bjc/utils/ioutils/format/RadixDirective.java | 44 ------- .../format/directives/AestheticDirective.java | 64 ++++++++++ .../format/directives/CharacterDirective.java | 37 ++++++ .../format/directives/ConditionalDirective.java | 120 ++++++++++++++++++ .../utils/ioutils/format/directives/Directive.java | 38 ++++++ .../ioutils/format/directives/EscapeDirective.java | 46 +++++++ .../format/directives/FreshlineDirective.java | 28 ++++ .../format/directives/GeneralNumberDirective.java | 47 +++++++ .../ioutils/format/directives/GotoDirective.java | 40 ++++++ .../format/directives/IterationDirective.java | 132 +++++++++++++++++++ .../format/directives/LiteralDirective.java | 35 +++++ .../ioutils/format/directives/NumberDirective.java | 37 ++++++ .../ioutils/format/directives/RadixDirective.java | 47 +++++++ 28 files changed, 842 insertions(+), 641 deletions(-) delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/CharacterDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/ConditionalDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/Directive.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/EscapeDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/FreshlineDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/GeneralNumberDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/GotoDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/IterationDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/LiteralDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java delete mode 100644 base/src/main/java/bjc/utils/ioutils/format/RadixDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java create mode 100644 base/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java (limited to 'base/src/main/java') diff --git a/base/src/main/java/bjc/utils/data/TopDownTransformIterator.java b/base/src/main/java/bjc/utils/data/TopDownTransformIterator.java index d4a676c..1e69071 100644 --- a/base/src/main/java/bjc/utils/data/TopDownTransformIterator.java +++ b/base/src/main/java/bjc/utils/data/TopDownTransformIterator.java @@ -16,6 +16,14 @@ import java.util.function.Function; * Figure out what is broken with this, and fix it so that step-wise * iteration works correctly. */ +/** + * An iterative top-down transform of a tree. + * + * @author EVE + * + * @param + * The type of the nodes in the tree. + */ public class TopDownTransformIterator implements Iterator> { private final Function picker; private final BiFunction, Consumer>>, ITree> transform; @@ -34,6 +42,16 @@ public class TopDownTransformIterator implements Iterator>> toYield; private Iterator> curYield; + /** + * Create a new tree iterator. + * + * @param pickr + * The function to use to pick how to process nodes. + * @param transfrm + * The transform to apply to the nodes. + * @param tree + * The tree to transform. + */ public TopDownTransformIterator(final Function pickr, final BiFunction, Consumer>>, ITree> transfrm, final ITree tree) { @@ -50,6 +68,12 @@ public class TopDownTransformIterator implements Iterator> src) { if(curYield != null) { toYield.push(curYield); @@ -63,25 +87,34 @@ public class TopDownTransformIterator implements Iterator flushYields(final ITree val) { if(curYield != null) { toYield.add(new SingleIterator<>(val)); - if(curYield.hasNext()) + if(curYield.hasNext()) { return curYield.next(); - else { - while(toYield.size() != 0 && !curYield.hasNext()) { - curYield = toYield.pop(); - } + } - if(toYield.size() == 0 && !curYield.hasNext()) { - curYield = null; - return val; - } else - return curYield.next(); + while(toYield.size() != 0 && !curYield.hasNext()) { + curYield = toYield.pop(); } - } else - return val; + + if(toYield.size() == 0 && !curYield.hasNext()) { + curYield = null; + return val; + } + + return curYield.next(); + } + + return val; } @Override @@ -89,17 +122,18 @@ public class TopDownTransformIterator implements Iterator implements Iterator implements Iterator(preParent.getHead()), - this::addYield)); } + + done = true; + return flushYields(transform.apply(new Tree<>(preParent.getHead()), this::addYield)); case PULLUP: final ITree intRes = transform.apply(preParent, this::addYield); @@ -155,10 +188,10 @@ public class TopDownTransformIterator implements Iterator implements Iterator res = null; - - if(postParent == null) { - res = new Tree<>(preParent.getHead()); + } - System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + res); + ITree res = null; - for(final ITree child : postChildren) { - res.addChild(child); - } + if(postParent == null) { + res = new Tree<>(preParent.getHead()); - // res = transform.apply(res, - // this::addYield); - } else { - res = postParent; + System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + res); - System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + res); - for(final ITree child : postChildren) { - res.addChild(child); - } + for(final ITree child : postChildren) { + res.addChild(child); } - done = true; - return flushYields(res); + // res = transform.apply(res, + // this::addYield); + } else { + res = postParent; + + System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + res); + for(final ITree child : postChildren) { + res.addChild(child); + } } - } else { - final ITree res = curChild.next(); - System.out.println("\t\tTRACE: adding node " + res + " to children"); - postChildren.add(res); + done = true; return flushYields(res); } + + final ITree res = curChild.next(); + System.out.println("\t\tTRACE: adding node " + res + " to children"); + postChildren.add(res); + + return flushYields(res); } } diff --git a/base/src/main/java/bjc/utils/esodata/SingleTape.java b/base/src/main/java/bjc/utils/esodata/SingleTape.java index 5218269..287f22d 100644 --- a/base/src/main/java/bjc/utils/esodata/SingleTape.java +++ b/base/src/main/java/bjc/utils/esodata/SingleTape.java @@ -55,6 +55,20 @@ public class SingleTape implements Tape { this(false); } + /** + * Create a new tape with values taken from an iterable. + * + * @param itr + * The iterable to get values from. + */ + public SingleTape(Iterable itr) { + this(false); + + for(T itm : itr) { + backing.add(itm); + } + } + /** * Create a new empty tape that follows the specified auto-extension * policy. diff --git a/base/src/main/java/bjc/utils/funcutils/StringUtils.java b/base/src/main/java/bjc/utils/funcutils/StringUtils.java index e753abd..0080dd1 100644 --- a/base/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -205,4 +205,23 @@ public class StringUtils { return num; } + + /** + * Get a substring until a specified string. + * + * @param strang + * The string to substring. + * @param vx + * The place to substring until. + * @return The specified substring. + */ + public static String substringTo(String strang, String vx) { + int idx = strang.indexOf(vx); + + if(idx == -1) { + return strang; + } + + return strang.substring(0, strang.indexOf(vx)); + } } diff --git a/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java b/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java deleted file mode 100644 index 16d9d12..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/AestheticDirective.java +++ /dev/null @@ -1,61 +0,0 @@ -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 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 408bb3b..f3d1777 100644 --- a/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java +++ b/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java @@ -2,6 +2,17 @@ package bjc.utils.ioutils.format; import bjc.utils.esodata.SingleTape; import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.directives.AestheticDirective; +import bjc.utils.ioutils.format.directives.CharacterDirective; +import bjc.utils.ioutils.format.directives.ConditionalDirective; +import bjc.utils.ioutils.format.directives.Directive; +import bjc.utils.ioutils.format.directives.EscapeDirective; +import bjc.utils.ioutils.format.directives.FreshlineDirective; +import bjc.utils.ioutils.format.directives.GotoDirective; +import bjc.utils.ioutils.format.directives.IterationDirective; +import bjc.utils.ioutils.format.directives.LiteralDirective; +import bjc.utils.ioutils.format.directives.NumberDirective; +import bjc.utils.ioutils.format.directives.RadixDirective; import java.util.HashMap; import java.util.Map; @@ -27,9 +38,9 @@ public class CLFormatter { 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 final String formatDirective = applyFormat("clFormatDirective", prefixList, formatMod, + directiveName); + private static final Pattern pFormatDirective = Pattern.compile(formatDirective); private static Map builtinDirectives; @@ -59,6 +70,7 @@ public class CLFormatter { builtinDirectives.put("^", new EscapeDirective()); builtinDirectives.put("[", new ConditionalDirective()); + builtinDirectives.put("{", new IterationDirective()); } /** @@ -68,7 +80,15 @@ public class CLFormatter { extraDirectives = new HashMap<>(); } - static void checkItem(Object itm, char directive) { + /** + * Check that an item is valid for a directive. + * + * @param itm + * The item to check. + * @param directive + * The directive to check for. + */ + public static void checkItem(Object itm, char directive) { if(itm == null) throw new IllegalArgumentException( String.format("No argument provided for %c directive", directive)); } @@ -92,7 +112,20 @@ public class CLFormatter { return sb.toString(); } - void doFormatString(String format, StringBuffer sb, Tape tParams) { + /** + * Fill in a partially started format string. + * + * Used mostly for directives that require formatting again with a + * different string. + * + * @param format + * The format to use. + * @param sb + * The buffer to file output into. + * @param tParams + * The parameters to use. + */ + public void doFormatString(String format, StringBuffer sb, Tape tParams) { Matcher dirMatcher = pFormatDirective.matcher(format); while(dirMatcher.find()) { @@ -136,6 +169,8 @@ public class CLFormatter { case ";": throw new IllegalArgumentException( "Found conditional-seperator outside of conditional."); + case "}": + throw new IllegalArgumentException("Found iteration-end outside of iteration"); case "T": case "<": case ">": @@ -159,6 +194,17 @@ public class CLFormatter { * punting. */ throw new IllegalArgumentException("S and W aren't implemented. Use A instead"); + case "?": + case "(": + case "P": + throw new IllegalArgumentException("These directives aren't implemented yet"); + case ")": + throw new IllegalArgumentException("Case-conversion end outside of case conversion"); + case "\n": + /* + * Ignored newline. + */ + break; default: String msg = String.format("Unknown format directive '%s'", dirName); throw new UnknownFormatConversionException(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 deleted file mode 100644 index 91ddabe..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/CharacterDirective.java +++ /dev/null @@ -1,34 +0,0 @@ -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 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 deleted file mode 100644 index 5ae842c..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/ConditionalDirective.java +++ /dev/null @@ -1,117 +0,0 @@ -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 formatParams, Matcher dirMatcher, CLFormatter fmt) { - StringBuffer condBody = new StringBuffer(); - - List clauses = new ArrayList<>(); - String defClause = null; - boolean isDefault = false; - - while(dirMatcher.find()) { - /* Process a list of clauses. */ - String dirName = dirMatcher.group("name"); - String dirMods = dirMatcher.group("modifiers"); - - if(dirName != null) { - /* Append everything up to this directive. */ - dirMatcher.appendReplacement(condBody, ""); - - if(dirName.equals("]")) { - /* End the conditional. */ - String clause = condBody.toString(); - if(isDefault) { - defClause = clause; - } else { - clauses.add(clause); - } - - break; - } else if(dirName.equals(";")) { - /* End the clause. */ - String clause = condBody.toString(); - if(isDefault) { - defClause = clause; - } else { - clauses.add(clause); - } - - /* - * Mark the next clause as the default. - */ - if(dirMods.contains(":")) { - isDefault = true; - } - } else { - /* Not a special directive. */ - condBody.append(dirMatcher.group()); - } - } - } - - Object par = formatParams.item(); - if(mods.colonMod) { - formatParams.right(); - - if(par == null) { - throw new IllegalArgumentException("No parameter provided for [ directive."); - } else if(!(par instanceof Boolean)) { - throw new IllegalFormatConversionException('[', par.getClass()); - } - boolean res = (Boolean) par; - - String 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 deleted file mode 100644 index fb03bbc..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/Directive.java +++ /dev/null @@ -1,35 +0,0 @@ -package bjc.utils.ioutils.format; - -import java.util.regex.Matcher; - -import bjc.utils.esodata.Tape; - -/** - * A CL format directive. - * - * @author EVE - * - */ -@FunctionalInterface -public interface Directive { - /** - * Execute this format directive. - * - * @param sb - * The buffer the string is being output to. - * @param item - * The current parameter being passed - * @param mods - * The directive modifiers - * @param arrParams - * The prefix parameters to the directive - * @param tParams - * All of the provided format parameters - * @param dirMatcher - * The matcher for format directives - * @param fmt - * The formatter itself. - */ - public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams, Tape 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 deleted file mode 100644 index 8db3a86..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/EscapeDirective.java +++ /dev/null @@ -1,42 +0,0 @@ -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 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 deleted file mode 100644 index 8ae0c72..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/FreshlineDirective.java +++ /dev/null @@ -1,25 +0,0 @@ -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 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 deleted file mode 100644 index 6a90f94..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/GeneralNumberDirective.java +++ /dev/null @@ -1,45 +0,0 @@ -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 deleted file mode 100644 index 767a77e..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/GotoDirective.java +++ /dev/null @@ -1,37 +0,0 @@ -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 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 deleted file mode 100644 index 81ce611..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/IterationDirective.java +++ /dev/null @@ -1,76 +0,0 @@ -package bjc.utils.ioutils.format; - -import bjc.utils.esodata.Tape; - -import java.util.IllegalFormatConversionException; -import java.util.regex.Matcher; - -class IterationDirective implements Directive { - - @Override - public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams, Tape 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 deleted file mode 100644 index 5110a9b..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/LiteralDirective.java +++ /dev/null @@ -1,32 +0,0 @@ -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 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 deleted file mode 100644 index 28e61ea..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/NumberDirective.java +++ /dev/null @@ -1,34 +0,0 @@ -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 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 deleted file mode 100644 index 668a0bd..0000000 --- a/base/src/main/java/bjc/utils/ioutils/format/RadixDirective.java +++ /dev/null @@ -1,44 +0,0 @@ -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 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/format/directives/AestheticDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java new file mode 100644 index 0000000..cbba104 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java @@ -0,0 +1,64 @@ +package bjc.utils.ioutils.format.directives; + +import java.util.regex.Matcher; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +public class AestheticDirective implements Directive { + + @Override + public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, Tape 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/directives/CharacterDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java new file mode 100644 index 0000000..8041cf4 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java @@ -0,0 +1,37 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +import java.util.IllegalFormatConversionException; +import java.util.regex.Matcher; + +public class CharacterDirective implements Directive { + + @Override + public void format(StringBuffer buff, Object parm, CLModifiers mods, CLParameters arrParams, + Tape 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/directives/ConditionalDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java new file mode 100644 index 0000000..98c62cb --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java @@ -0,0 +1,120 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +import java.util.ArrayList; +import java.util.IllegalFormatConversionException; +import java.util.List; +import java.util.regex.Matcher; + +public class ConditionalDirective implements Directive { + + @Override + public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams, + Tape formatParams, Matcher dirMatcher, CLFormatter fmt) { + StringBuffer condBody = new StringBuffer(); + + List clauses = new ArrayList<>(); + String defClause = null; + boolean isDefault = false; + + while(dirMatcher.find()) { + /* Process a list of clauses. */ + String dirName = dirMatcher.group("name"); + String dirMods = dirMatcher.group("modifiers"); + + if(dirName != null) { + /* Append everything up to this directive. */ + dirMatcher.appendReplacement(condBody, ""); + + if(dirName.equals("]")) { + /* End the conditional. */ + String clause = condBody.toString(); + if(isDefault) { + defClause = clause; + } else { + clauses.add(clause); + } + + break; + } else if(dirName.equals(";")) { + /* End the clause. */ + String clause = condBody.toString(); + if(isDefault) { + defClause = clause; + } else { + clauses.add(clause); + } + + /* + * Mark the next clause as the default. + */ + if(dirMods.contains(":")) { + isDefault = true; + } + } else { + /* Not a special directive. */ + condBody.append(dirMatcher.group()); + } + } + } + + Object par = formatParams.item(); + if(mods.colonMod) { + formatParams.right(); + + if(par == null) { + throw new IllegalArgumentException("No parameter provided for [ directive."); + } else if(!(par instanceof Boolean)) { + throw new IllegalFormatConversionException('[', par.getClass()); + } + boolean res = (Boolean) par; + + String 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/directives/Directive.java b/base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java new file mode 100644 index 0000000..6d558fc --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java @@ -0,0 +1,38 @@ +package bjc.utils.ioutils.format.directives; + +import java.util.regex.Matcher; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +/** + * A CL format directive. + * + * @author EVE + * + */ +@FunctionalInterface +public interface Directive { + /** + * Execute this format directive. + * + * @param sb + * The buffer the string is being output to. + * @param item + * The current parameter being passed + * @param mods + * The directive modifiers + * @param arrParams + * The prefix parameters to the directive + * @param tParams + * All of the provided format parameters + * @param dirMatcher + * The matcher for format directives + * @param fmt + * The formatter itself. + */ + public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams, Tape tParams, + Matcher dirMatcher, CLFormatter fmt); +} \ No newline at end of file diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java new file mode 100644 index 0000000..ba1acf5 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java @@ -0,0 +1,46 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; +import bjc.utils.ioutils.format.EscapeException; + +import java.util.regex.Matcher; + +public class EscapeDirective implements Directive { + + @Override + public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, + Tape 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/directives/FreshlineDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java new file mode 100644 index 0000000..e394a8d --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java @@ -0,0 +1,28 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +import java.util.regex.Matcher; + +public class FreshlineDirective implements Directive { + + @Override + public void format(StringBuffer buff, Object item, CLModifiers mods, CLParameters params, Tape 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/directives/GeneralNumberDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java new file mode 100644 index 0000000..34abcab --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java @@ -0,0 +1,47 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; +import bjc.utils.math.NumberUtils; + +public 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/directives/GotoDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java new file mode 100644 index 0000000..f3da9bb --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java @@ -0,0 +1,40 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +import java.util.regex.Matcher; + +public class GotoDirective implements Directive { + + @Override + public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters params, + Tape 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/directives/IterationDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java new file mode 100644 index 0000000..52b2e40 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java @@ -0,0 +1,132 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.SingleTape; +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +import java.util.IllegalFormatConversionException; +import java.util.regex.Matcher; + +public class IterationDirective implements Directive { + + @Override + public void format(StringBuffer sb, Object item, CLModifiers mods, CLParameters arrParams, Tape 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", '{'); + } + + int numItr = 0; + + if(mods.atMod && mods.colonMod) { + do { + if(numItr > maxItr) break; + numItr += 1; + + if(!(iter instanceof Iterable)) { + throw new IllegalFormatConversionException('{', iter.getClass()); + } + + @SuppressWarnings("unchecked") + Iterable nitr = (Iterable) iter; + Tape nParams = new SingleTape<>(nitr); + + fmt.doFormatString(frmt, sb, nParams); + + iter = tParams.right(); + } while(tParams.position() < tParams.size()); + } else if(mods.atMod) { + while(tParams.position() < tParams.size()) { + if(numItr > maxItr) break; + numItr += 1; + + fmt.doFormatString(frmt, sb, tParams); + } + } else if(mods.colonMod) { + if(!(item instanceof Iterable)) { + throw new IllegalFormatConversionException('{', item.getClass()); + } + + @SuppressWarnings("unchecked") + Iterable itr = (Iterable) item; + + for(Object obj : itr) { + if(numItr > maxItr) break; + numItr += 1; + + if(!(obj instanceof Iterable)) { + throw new IllegalFormatConversionException('{', obj.getClass()); + } + + @SuppressWarnings("unchecked") + Iterable nitr = (Iterable) obj; + Tape nParams = new SingleTape<>(nitr); + + fmt.doFormatString(frmt, sb, nParams); + } + } else { + if(!(item instanceof Iterable)) { + throw new IllegalFormatConversionException('{', item.getClass()); + } + + @SuppressWarnings("unchecked") + Iterable itr = (Iterable) item; + + Tape nParams = new SingleTape<>(itr); + + while(nParams.position() < nParams.size()) { + if(numItr > maxItr) break; + numItr += 1; + + fmt.doFormatString(frmt, sb, nParams); + } + } + + tParams.right(); + } + +} diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java new file mode 100644 index 0000000..ba00520 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java @@ -0,0 +1,35 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +import java.util.regex.Matcher; + +public 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 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/directives/NumberDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java new file mode 100644 index 0000000..98d6c16 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java @@ -0,0 +1,37 @@ +package bjc.utils.ioutils.format.directives; + +import java.util.IllegalFormatConversionException; +import java.util.regex.Matcher; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; + +public 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 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/directives/RadixDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java new file mode 100644 index 0000000..428c613 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java @@ -0,0 +1,47 @@ +package bjc.utils.ioutils.format.directives; + +import bjc.utils.esodata.Tape; +import bjc.utils.ioutils.format.CLFormatter; +import bjc.utils.ioutils.format.CLModifiers; +import bjc.utils.ioutils.format.CLParameters; +import bjc.utils.math.NumberUtils; + +import java.util.IllegalFormatConversionException; +import java.util.regex.Matcher; + +public class RadixDirective extends GeneralNumberDirective { + + @Override + public void format(StringBuffer buff, Object arg, CLModifiers mods, CLParameters params, Tape 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(); + } +} -- cgit v1.2.3