summaryrefslogtreecommitdiff
path: root/clformat/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java
blob: 24af908ca19fc9f38345dd2bb2d74c2d85ae4ea2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package bjc.utils.ioutils.format.directives;

import java.io.*;
import java.util.*;

import bjc.utils.ioutils.format.*;
import bjc.utils.math.*;

import static bjc.utils.ioutils.format.directives.GeneralNumberDirective.NumberParams;

/**
 * Generalized radix directive.
 *
 * @author student
 *
 */
public class RadixDirective extends GeneralNumberDirective {
	@Override
	public Edict compile(CompileContext compCTX) {
		CLParameters params = compCTX.decr.parameters;
		CLModifiers mods = compCTX.decr.modifiers;

		RadixEdict.Mode mode;

		CLValue radixVal = CLValue.nil();

		NumberParams np = null;

		if (params.length() == 0) {
			if      (mods.atMod)    mode = RadixEdict.Mode.ROMAN;
			else if (mods.colonMod) mode = RadixEdict.Mode.ORDINAL;
			else                    mode = RadixEdict.Mode.CARDINAL;
		} else {
			mode = RadixEdict.Mode.NORMAL;

			if (params.length() < 1)
				throw new IllegalArgumentException(
						"R directive requires at least one parameter, the radix");

			params.mapIndex("radix", 0);
			radixVal = params.resolveKey("radix");

			np = getParams(compCTX, 0);
		}

		return new RadixEdict(mode, radixVal, np, mods.colonMod);
	}
}

class RadixEdict implements Edict {
	public static enum Mode {
		NORMAL, ROMAN, ORDINAL, CARDINAL
	}

	private Mode mode;

	private CLValue radixVal;

	private NumberParams np;

	private boolean isClassic;

	public RadixEdict(Mode mode, CLValue radix, NumberParams np, boolean isClassic) {
		this.mode = mode;

		this.radixVal = radix;

		this.np = np;
	}

	@Override
	public void format(FormatContext formCTX) throws IOException {
		Object item = formCTX.items.item();

		CLFormatter.checkItem(item, 'R');

		if (!(item instanceof Number)) {
			throw new IllegalFormatConversionException('R', item.getClass());
		}

		long val = ((Number) item).longValue();

		String res;
		switch (mode) {
		case ROMAN:
			res = NumberUtils.toRoman(val, isClassic);
			break;
		case ORDINAL:
			res = NumberUtils.toOrdinal(val);
			break;
		case CARDINAL:
			res = NumberUtils.toCardinal(val);
			break;
		case NORMAL: {
			int radix    = radixVal.asInt(formCTX.items, "radix", "R", 10);
			int mincol   = np.mincol.asInt(formCTX.items, "minimum column count", "R", 0);
			char padchar = np.padchar.asChar(formCTX.items, "padding character", "R", ' ');

			boolean signed = np.signed;

			if (np.commaMode) {
				char commaChar
						= np.commaChar.asChar(formCTX.items, "comma character", "R", ',');
				int commaInterval
						= np.commaInterval.asInt(formCTX.items, "comma interval", "R", 0);

				res = NumberUtils.toCommaString(val, mincol, padchar, commaInterval,
						commaChar, signed, radix);
			} else {
				res = NumberUtils.toNormalString(val, mincol, padchar, signed, radix);
			}

			break;
		}

		default:
			throw new IllegalArgumentException("Unsupported radix mode " + mode);
		}

		formCTX.writer.write(res);

		formCTX.items.right();
	}
}