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