1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.util.TypeUtils; 13 14 import hunt.util.Common; 15 import hunt.text.StringBuilder; 16 import hunt.Exceptions; 17 18 import std.conv; 19 import std.string; 20 import std.typecons; 21 22 /** 23 */ 24 alias Pair(F, S) = Tuple!(F, "first", S, "second"); 25 Pair!(F, S) makePair(F, S)(F first, S second) { 26 return tuple!("first", "second")(first, second); 27 } 28 29 unittest { 30 Pair!(string, int) p = makePair("age", 20); 31 32 assert(p.first == "age"); 33 assert(p.second == 20); 34 } 35 36 /** 37 */ 38 class TypeUtils { 39 40 static string getSimpleName(TypeInfo info) { 41 string name = info.toString(); 42 ptrdiff_t index = lastIndexOf(name, '.'); 43 if(index == -1) 44 return name; 45 else 46 return name[index+1 .. $]; 47 } 48 49 /** 50 * Returns the number of zero bits preceding the highest-order 51 * ("leftmost") one-bit in the two's complement binary representation 52 * of the specified {@code int} value. Returns 32 if the 53 * specified value has no one-bits in its two's complement representation, 54 * in other words if it is equal to zero. 55 * 56 * <p>Note that this method is closely related to the logarithm base 2. 57 * For all positive {@code int} values x: 58 * <ul> 59 * <li>floor(log<sub>2</sub>(x)) = {@code 31 - numberOfLeadingZeros(x)} 60 * <li>ceil(log<sub>2</sub>(x)) = {@code 32 - numberOfLeadingZeros(x - 1)} 61 * </ul> 62 * 63 * @param i the value whose number of leading zeros is to be computed 64 * @return the number of zero bits preceding the highest-order 65 * ("leftmost") one-bit in the two's complement binary representation 66 * of the specified {@code int} value, or 32 if the value 67 * is equal to zero. 68 * @since 1.5 69 */ 70 static int numberOfLeadingZeros(int i) { 71 // HD, Figure 5-6 72 if (i == 0) 73 return 32; 74 int n = 1; 75 if (i >>> 16 == 0) { 76 n += 16; 77 i <<= 16; 78 } 79 if (i >>> 24 == 0) { 80 n += 8; 81 i <<= 8; 82 } 83 if (i >>> 28 == 0) { 84 n += 4; 85 i <<= 4; 86 } 87 if (i >>> 30 == 0) { 88 n += 2; 89 i <<= 2; 90 } 91 n -= i >>> 31; 92 return n; 93 } 94 95 /** 96 * @param c An ASCII encoded character 0-9 a-f A-F 97 * @return The byte value of the character 0-16. 98 */ 99 static byte convertHexDigit(byte c) { 100 byte b = cast(byte)((c & 0x1f) + ((c >> 6) * 0x19) - 0x10); 101 if (b < 0 || b > 15) 102 throw new NumberFormatException("!hex " ~ to!string(c)); 103 return b; 104 } 105 106 /* ------------------------------------------------------------ */ 107 108 /** 109 * @param c An ASCII encoded character 0-9 a-f A-F 110 * @return The byte value of the character 0-16. 111 */ 112 static int convertHexDigit(char c) { 113 int d = ((c & 0x1f) + ((c >> 6) * 0x19) - 0x10); 114 if (d < 0 || d > 15) 115 throw new NumberFormatException("!hex " ~ to!string(c)); 116 return d; 117 } 118 119 /* ------------------------------------------------------------ */ 120 121 /** 122 * @param c An ASCII encoded character 0-9 a-f A-F 123 * @return The byte value of the character 0-16. 124 */ 125 static int convertHexDigit(int c) { 126 int d = ((c & 0x1f) + ((c >> 6) * 0x19) - 0x10); 127 if (d < 0 || d > 15) 128 throw new NumberFormatException("!hex " ~ to!string(c)); 129 return d; 130 } 131 132 /* ------------------------------------------------------------ */ 133 static void toHex(byte b, Appendable buf) { 134 try { 135 int d = 0xf & ((0xF0 & b) >> 4); 136 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 137 d = 0xf & b; 138 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 139 } 140 catch (IOException e) { 141 throw new RuntimeException(e); 142 } 143 } 144 145 /* ------------------------------------------------------------ */ 146 static void toHex(int value, Appendable buf) { 147 int d = 0xf & ((0xF0000000 & value) >> 28); 148 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 149 d = 0xf & ((0x0F000000 & value) >> 24); 150 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 151 d = 0xf & ((0x00F00000 & value) >> 20); 152 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 153 d = 0xf & ((0x000F0000 & value) >> 16); 154 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 155 d = 0xf & ((0x0000F000 & value) >> 12); 156 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 157 d = 0xf & ((0x00000F00 & value) >> 8); 158 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 159 d = 0xf & ((0x000000F0 & value) >> 4); 160 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 161 d = 0xf & value; 162 buf.append(cast(char)((d > 9 ? ('A' - 10) : '0') + d)); 163 164 // Integer.toString(0, 36); 165 } 166 167 /* ------------------------------------------------------------ */ 168 static void toHex(long value, Appendable buf) { 169 toHex(cast(int)(value >> 32), buf); 170 toHex(cast(int) value, buf); 171 } 172 173 /* ------------------------------------------------------------ */ 174 static string toHexString(byte b) { 175 return toHexString([b], 0, 1); 176 } 177 178 /* ------------------------------------------------------------ */ 179 static string toHexString(byte[] b) { 180 return toHexString(b, 0, cast(int) b.length); 181 } 182 183 /* ------------------------------------------------------------ */ 184 static string toHexString(byte[] b, int offset, int length) { 185 StringBuilder buf = new StringBuilder(); 186 for (int i = offset; i < offset + length; i++) { 187 int bi = 0xff & b[i]; 188 int c = '0' + (bi / 16) % 16; 189 if (c > '9') 190 c = 'A' + (c - '0' - 10); 191 buf.append(cast(char) c); 192 c = '0' + bi % 16; 193 if (c > '9') 194 c = 'a' + (c - '0' - 10); 195 buf.append(cast(char) c); 196 } 197 return buf.toString(); 198 } 199 200 /* ------------------------------------------------------------ */ 201 static byte[] fromHexString(string s) { 202 if (s.length % 2 != 0) 203 throw new IllegalArgumentException(s); 204 byte[] array = new byte[s.length / 2]; 205 for (int i = 0; i < array.length; i++) { 206 int b = to!int(s[i * 2 .. i * 2 + 2], 16); 207 array[i] = cast(byte)(0xff & b); 208 } 209 return array; 210 } 211 212 static int parseInt(string s, int offset, int length, int base) { 213 return to!int(s[offset .. offset + length], base); 214 } 215 216 }