1 package com.sharkysoft.printf;
2
3 import com.sharkysoft.printf.engine.IntegerFormatter;
4 import com.sharkysoft.printf.engine.StringFormatter;
5
6 final class Formatter_c extends Formatter_Field
7 {
8
9 private static final IntegerFormatter gpUnicodeFmt = new IntegerFormatter();
10
11 private static final IntegerFormatter gpAsciiFmt = new IntegerFormatter();
12
13 static
14 {
15 gpUnicodeFmt.setMinDigits(4);
16 gpUnicodeFmt.setRadix(16);
17 gpUnicodeFmt.setZeroPrefix("//u");
18 gpUnicodeFmt.setPosPrefix("//u");
19 gpAsciiFmt.setMinDigits(3);
20 gpAsciiFmt.setRadix(8);
21 gpAsciiFmt.setZeroPrefix("//");
22 gpAsciiFmt.setPosPrefix("//");
23 }
24
25 private final boolean mzAlternate;
26
27 Formatter_c(final FormatSpecifier mpPfs)
28 {
29 super(mpPfs, new StringFormatter());
30 mzAlternate = mpPfs.mcAlternate == FormatSpecifier.ALTERNATE_ON;
31 }
32
33 void format(final PrintfState ipState)
34 {
35 adjustWidth(ipState);
36 final char vcC = ((Character) ipState.mapArgs[ipState.mnArgIndex++]).charValue();
37 final String vsOutput;
38 if (mzAlternate)
39 switch (vcC)
40 {
41 case '"' :
42 vsOutput = "//\"";
43 break;
44 case '\'' :
45 vsOutput = "//'";
46 break;
47 case '\n' :
48 vsOutput = "//n";
49 break;
50 case '\r' :
51 vsOutput = "//r";
52 break;
53 case '\b' :
54 vsOutput = "//b";
55 break;
56 case '\t' :
57 vsOutput = "//t";
58 break;
59 case '\f' :
60 vsOutput = "//f";
61 break;
62 default :
63 if (isprint(vcC))
64 vsOutput = "" + vcC;
65 else if (vcC < 256)
66 vsOutput = gpAsciiFmt.format((int) vcC);
67 else
68 vsOutput = gpUnicodeFmt.format((int) vcC);
69 }
70 else
71 vsOutput = "" + vcC;
72 ipState.mpOutput.append(mpFormatter.format(vsOutput));
73 }
74
75 final int argsRequired()
76 {
77 return 1 + (mzVariableWidth ? 1 : 0);
78 }
79
80 /***
81 * <p><b>Details:</b> Returns <code>true</code> if c is a printing character.
82 * For ASCII values, c is a printing character if and only if c is in
83 * {32..127}. This method does not support Unicode values, but it may in the
84 * future.
85 */
86 static boolean isprint(int c)
87 {
88 if (c > 255)
89 throw new com.sharkysoft.util.NotImplementedException("c=" + c);
90 return 32 <= c && c <= 126;
91 }
92
93 final Class[] argTypes() {
94 if (mzVariableWidth) {
95 return new Class[] { Number.class, Character.class };
96 } else {
97 return new Class[] { Character.class };
98 }
99 }
100 }
101