1 module hunt.util.ConverterUtils;
2 
3 import hunt.Exceptions;
4 import hunt.text.StringBuilder;
5 import hunt.util.Common;
6 import hunt.util.Traits;
7 
8 import std.conv;
9 import std.format;
10 import std.string;
11 import std.typecons;
12 import std.ascii;
13 
14 /**
15 */
16 struct ConverterUtils {
17 
18     /**
19      * @param c An ASCII encoded character 0-9 a-f A-F
20      * @return The byte value of the character 0-16.
21      */
22     static byte convertHexDigit(byte c) {
23         byte b = cast(byte)((c & 0x1f) + ((c >> 6) * 0x19) - 0x10);
24         if (b < 0 || b > 15)
25             throw new NumberFormatException("!hex " ~ to!string(c));
26         return b;
27     }
28 
29     /* ------------------------------------------------------------ */
30 
31     /**
32      * @param c An ASCII encoded character 0-9 a-f A-F
33      * @return The byte value of the character 0-16.
34      */
35     static int convertHexDigit(char c) {
36         int d = ((c & 0x1f) + ((c >> 6) * 0x19) - 0x10);
37         if (d < 0 || d > 15)
38             throw new NumberFormatException("!hex " ~ to!string(c));
39         return d;
40     }
41 
42     /* ------------------------------------------------------------ */
43 
44     /**
45      * @param c An ASCII encoded character 0-9 a-f A-F
46      * @return The byte value of the character 0-16.
47      */
48     static int convertHexDigit(int c) {
49         int d = ((c & 0x1f) + ((c >> 6) * 0x19) - 0x10);
50         if (d < 0 || d > 15)
51             throw new NumberFormatException("!hex " ~ to!string(c));
52         return d;
53     }
54 
55     /* ------------------------------------------------------------ */
56     static void toHex(byte b, Appendable buf) {
57         try {
58             int d = 0xf & ((0xF0 & b) >> 4);
59             buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
60             d = 0xf & b;
61             buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
62         }
63         catch (IOException e) {
64             throw new RuntimeException(e);
65         }
66     }
67 
68     /* ------------------------------------------------------------ */
69     static void toHex(int value, Appendable buf) {
70         int d = 0xf & ((0xF0000000 & value) >> 28);
71         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
72         d = 0xf & ((0x0F000000 & value) >> 24);
73         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
74         d = 0xf & ((0x00F00000 & value) >> 20);
75         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
76         d = 0xf & ((0x000F0000 & value) >> 16);
77         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
78         d = 0xf & ((0x0000F000 & value) >> 12);
79         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
80         d = 0xf & ((0x00000F00 & value) >> 8);
81         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
82         d = 0xf & ((0x000000F0 & value) >> 4);
83         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
84         d = 0xf & value;
85         buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d));
86 
87         // Integer.toString(0, 36);
88     }
89 
90     /* ------------------------------------------------------------ */
91     static void toHex(long value, Appendable buf) {
92         toHex(cast(int)(value >> 32), buf);
93         toHex(cast(int) value, buf);
94     }
95 
96     /* ------------------------------------------------------------ */
97     static string toHexString(byte b) {
98         return toHexString([b], 0, 1);
99     }
100 
101     /* ------------------------------------------------------------ */
102     static string toHexString(byte[] b) {
103         return toHexString(b, 0, cast(int) b.length);
104     }
105 
106     /* ------------------------------------------------------------ */
107     static string toHexString(byte[] b, int offset, int length) {
108         StringBuilder buf = new StringBuilder();
109         for (int i = offset; i < offset + length; i++) {
110             int bi = 0xff & b[i];
111             int c = '0' + (bi / 16) % 16;
112             if (c > '9')
113                 c = 'A' + (c - '0' - 10);
114             buf.append(cast(char) c);
115             c = '0' + bi % 16;
116             if (c > '9')
117                 c = 'a' + (c - '0' - 10);
118             buf.append(cast(char) c);
119         }
120         return buf.toString();
121     }
122 
123     static string toHexString(LetterCase letterCase = LetterCase.upper)(const(ubyte)[] b, 
124             string separator="", string prefix="") {
125         static if(letterCase == LetterCase.upper) {
126             string fmt = "%(" ~ prefix ~ "%02X" ~ separator ~ "%)";
127         } else {
128             string fmt = "%(" ~ prefix ~ "%02x" ~ separator ~ "%)";
129         }
130 
131         return format(fmt, b);
132     }
133 
134     /* ------------------------------------------------------------ */
135     /**
136     */
137     static T[] toBytes(T)(string s) if(isByteType!T) {
138         if (s.length % 2 != 0)
139             throw new IllegalArgumentException(s);
140         T[] r = new T[s.length/2];
141         for(size_t i=0; i<r.length; i++) {
142             size_t j = i+i;
143             r[i] = cast(T)to!(int)(s[j .. j+2], 16);
144         }
145         return r;
146     }
147 
148     /**
149     */
150     static byte[] fromHexString(string s) {
151         return toBytes!byte(s);
152         // if (s.length % 2 != 0)
153         //     throw new IllegalArgumentException(s);
154         // byte[] array = new byte[s.length / 2];
155         // for (int i = 0; i < array.length; i++) {
156         //     int b = to!int(s[i * 2 .. i * 2 + 2], 16);
157         //     array[i] = cast(byte)(0xff & b);
158         // }
159         // return array;
160     }
161 
162     static int parseInt(string s, int offset, int length, int base) {
163         return to!int(s[offset .. offset + length], base);
164     }
165 
166 }