1 // Written in D programming language 2 /** 3 * Utilities to convert hex strings to numbers. 4 * Authors : David L. 'SpottedTiger' Davis 5 * Licence : Public Domain / Contributed to Digital Mars 6 */ 7 module pgator.util.hexconv; 8 9 /// Hex string to an unsigned decimal whole number 10 /** 11 * Converts a Hex string from 0x0 to 0xFFFFFFFFFFFFFF 12 * into a ulong value 0 to 18,446,744,073,709,551,615 13 * also it handles the lowercase 'a' thru 'f'. 14 * 15 * Authors : David 'SpottedTiger' L. Davis 16 * Created : 03.May.05 17 * 18 * Example: 19 * ---------- 20 * ulong ul; 21 * 22 * ul = xtoul("0"c); 23 * assert( ul == 0x0 ); 24 * ul = xtoul("FF"c); 25 * assert( ul == 0xFF ); 26 * ul = xtoul("eea"c); 27 * assert( ul == 0xEEA ); 28 * ul = xtoul("AB"c); 29 * assert( ul == 0xAB ); 30 * ul = xtoul("ABCD"c); 31 * assert( ul == 0xABCD ); 32 * ul = xtoul("A12CD00"c); 33 * assert( ul == 0xA12CD00 ); 34 * ul = xtoul("FFFFFFFFFFFFFFFF"c); 35 * assert( ul == 0xFFFFFFFFFFFFFFFF ); 36 * ---------- 37 */ 38 ulong xtoul(string sx) 39 { 40 ulong ul = 0L; 41 int j = 7; 42 char c, c1, c2; 43 char[] st = cast(char[])sx; 44 size_t len = st.length; 45 46 const char[] zeros = "0000000000000000"c; 47 union u { ulong ul; char[8] c; } 48 49 u U; 50 51 if (len == 0 || len > 16) 52 throw new Exception( "xtoul() the string parameter is either an empty string,"c ~ 53 " or its length is greater than 16 characters."c ); 54 55 // isHex() 56 for (int i = 0; i < st.length; i++) 57 { 58 //c = ( sx[i] > 'F' ? sx[i] - 32 : sx[i] ); 59 c = st[i]; 60 61 if ((c >= '0' && c <= '9') || 62 (c >= 'A' && c <= 'F') || 63 (c >= 'a' && c <= 'f')) 64 continue; 65 else 66 throw new Exception("xtoul() invalid hex character used."c); 67 } 68 69 if (len < 16) 70 st = zeros[0..16 - len] ~ st; 71 72 j = 7; 73 for (int i = 0; i < 16; i += 2) 74 { 75 c1 = (st[i] > 'F' ? cast(char)(st[i] - 32) : st[i]); 76 c2 = (st[i + 1] > 'F' ? cast(char)(st[i + 1] - 32) : st[i + 1]); 77 c1 = cast(char)(cast(int)(c1 > 52 ? c1 - 55 : c1 - 48) << 4); 78 U.c[j--] = cast(char)(c1 + (c2 > 52 ? c2 - 55 : c2 - 48)); 79 } 80 81 return U.ul; 82 } 83 84 unittest 85 { 86 ulong ul; 87 88 ul = xtoul("0"c); 89 assert( ul == 0x0 ); 90 ul = xtoul("FF"c); 91 assert( ul == 0xFF ); 92 ul = xtoul("eea"c); 93 assert( ul == 0xEEA ); 94 ul = xtoul("AB"c); 95 assert( ul == 0xAB ); 96 ul = xtoul("ABCD"c); 97 assert( ul == 0xABCD ); 98 ul = xtoul("A12CD00"c); 99 assert( ul == 0xA12CD00 ); 100 ul = xtoul("FFFFFFFFFFFFFFFF"c); 101 assert( ul == 0xFFFFFFFFFFFFFFFF ); 102 } 103 104 /// Decimal unsigned whole number to Hex string 105 /** 106 * Accepts any positive number from 0 to 18,446,744,073,709,551,615 107 * and the returns an even number of hex strings up to 16 characters 108 * (from 0x0 to 0xFFFFFFFFFFFFFF). 109 * 110 * Authors : David 'SpottedTiger' L. Davis 111 * Created : 04.May.05 112 * 113 * Example: 114 * --------- 115 * string sx; 116 * 117 * sx = ultox(0); //0x0 118 * assert( sx == "00"c ); 119 * 120 * sx = ultox(255); //0xFF 121 * assert( sx == "FF"c ); 122 * sx = ultox(171); //0xAB 123 * assert( sx == "AB"c ); 124 * sx = ultox(43981); //0xABCD 125 * assert( sx == "ABCD"c ); 126 * sx = ultox(169004288); //0xA12CD00 127 * assert( sx == "0A12CD00"c ); 128 * sx = ultox(0xA12CD00); //169004288 129 * assert( sx == "0A12CD00"c ); 130 * 131 * sx = ultox(ulong.max); //0xFFFFFFFFFFFFFFFF 132 * assert( sx == "FFFFFFFFFFFFFFFF"c ); 133 * --------- 134 */ 135 string ultox(in ulong ul) 136 { 137 char[16] sx; 138 char c1, c2; 139 union u { ulong ul; char[8] c; } 140 int i = 0, j = 0, k = 0; 141 bool z = true; 142 u U; 143 144 U.ul = ul; 145 146 for (i = 7; i >= 0; i--) 147 { 148 c1 = U.c[i] >> 4; 149 c1 = cast(char)(c1 > 9 ? c1 + 55 : c1 + 48); 150 c2 = U.c[i] & 0x0F; 151 c2 = cast(char)(c2 > 9 ? c2 + 55 : c2 + 48); 152 153 if (z && c1 == '0' && c2 == '0') 154 continue; 155 156 z = false; 157 sx[j++] = c1; 158 sx[j++] = c2; 159 } 160 161 if (j > 0) 162 //Copying a fixed array into a dynamic array, must COW. 163 return sx[0..j].dup; 164 else 165 return "00"c; 166 } 167 168 unittest 169 { 170 string sx; 171 172 sx = ultox(0); //0x0 173 assert( sx == "00"c ); 174 175 sx = ultox(255); //0xFF 176 assert( sx == "FF"c ); 177 sx = ultox(171); //0xAB 178 assert( sx == "AB"c ); 179 sx = ultox(43981); //0xABCD 180 assert( sx == "ABCD"c ); 181 sx = ultox(169004288); //0xA12CD00 182 assert( sx == "0A12CD00"c ); 183 sx = ultox(0xA12CD00); //169004288 184 assert( sx == "0A12CD00"c ); 185 186 sx = ultox(ulong.max); //0xFFFFFFFFFFFFFFFF 187 assert( sx == "FFFFFFFFFFFFFFFF"c ); 188 } 189 190 /// Checks if string contains hex number 191 /** 192 * Authors : David 'SpottedTiger' L. Davis 193 * Created : 04.May.05 194 * 195 * Example: 196 * ----------- 197 * assert( isHex("00"c) ); 198 * assert( isHex("FF"c) ); 199 * assert( isHex("Ffae0"c) ); 200 * assert( isHex("AB"c) ); 201 * assert( isHex("abdef"c) ); 202 * assert( isHex("ABCD"c) ); 203 * assert( isHex("0A12CD00"c) ); 204 * assert( isHex("FFFFFFFFFFFFFFFF"c) ); 205 * 206 * assert( isHex("00ER"c) == false ); 207 * assert( !isHex("0xW"c) ); 208 * ----------- 209 */ 210 bool isHex(string sx) 211 { 212 char c; 213 214 for (int i = 0; i < sx.length; i++) 215 { 216 c = sx[i]; 217 218 if ((c >= '0' && c <= '9') || 219 (c >= 'A' && c <= 'F') || 220 (c >= 'a' && c <= 'f')) 221 continue; 222 else 223 return false; 224 } 225 226 return true; 227 } 228 229 unittest 230 { 231 assert( isHex("00"c) ); 232 assert( isHex("FF"c) ); 233 assert( isHex("Ffae0"c) ); 234 assert( isHex("AB"c) ); 235 assert( isHex("abdef"c) ); 236 assert( isHex("ABCD"c) ); 237 assert( isHex("0A12CD00"c) ); 238 assert( isHex("FFFFFFFFFFFFFFFF"c) ); 239 240 assert( isHex("00ER"c) == false ); 241 assert( !isHex("0xW"c) ); 242 }