1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.util.HexBin;
17 import std.conv;
18 /**
19  * format validation This class encodes/decodes hexadecimal data
20  * 
21  */
22 public  class HexBin {
23 
24     private enum int    BASE_LENGTH        = 128;
25     private enum  int    LOOKUP_LENGTH      = 16;
26     private __gshared byte[] HEX_NUMBER_TABLE;
27     private __gshared char[] UPPER_CHARS ;
28     private __gshared char[] LOWER_CHARS ;
29 
30     shared static this() {
31         HEX_NUMBER_TABLE   = new byte[BASE_LENGTH];
32         UPPER_CHARS        = new char[LOOKUP_LENGTH];
33         LOWER_CHARS        = new char[LOOKUP_LENGTH];
34 
35         for (int i = 0; i < BASE_LENGTH; i++) {
36             HEX_NUMBER_TABLE[i] = -1;
37         }
38         for (int i = '9'; i >= '0'; i--) {
39             HEX_NUMBER_TABLE[i] = cast(byte) (i - '0');
40         }
41         for (int i = 'F'; i >= 'A'; i--) {
42             HEX_NUMBER_TABLE[i] = cast(byte) (i - 'A' + 10);
43         }
44         for (int i = 'f'; i >= 'a'; i--) {
45             HEX_NUMBER_TABLE[i] = cast(byte) (i - 'a' + 10);
46         }
47 
48         for (int i = 0; i < 10; i++) {
49             UPPER_CHARS[i] = cast(char) ('0' + i);
50             LOWER_CHARS[i] = cast(char) ('0' + i);
51         }
52         for (int i = 10; i <= 15; i++) {
53             UPPER_CHARS[i] = cast(char) ('A' + i - 10);
54             LOWER_CHARS[i] = cast(char) ('a' + i - 10);
55         }
56     }
57     
58     public static string encode(byte[] bytes) {
59         return encode(bytes, true);
60     }
61 
62     public static string encode(byte[] bytes, bool upperCase) {
63 
64         if (bytes is null) {
65             return null;
66         }
67 
68          char[] chars = upperCase ? UPPER_CHARS : LOWER_CHARS;
69 
70         char[] hex = new char[bytes.length * 2];
71         for (int i = 0; i < bytes.length; i++) {
72             int b = bytes[i] & 0xFF;
73             hex[i * 2] = chars[b >> 4];
74             hex[i * 2 + 1] = chars[b & 0xf];
75         }
76         return to!string(hex);
77     }
78 
79     /**
80      * Decode hex string to a byte array
81      * 
82      * @param encoded encoded string
83      * @return return array of byte to encode
84      */
85     static public byte[] decode(string encoded) {
86         if (encoded is null) {
87             return null;
88         }
89 
90         int lengthData = cast(int)(encoded.length);
91         if (lengthData % 2 != 0) {
92             return null;
93         }
94 
95         char[] binaryData = /* encoded.toCharArray() */ to!(char[])(encoded);
96         int lengthDecode = lengthData / 2;
97         byte[] decodedData = new byte[lengthDecode];
98         byte temp1, temp2;
99         char tempChar;
100         for (int i = 0; i < lengthDecode; i++) {
101             tempChar = binaryData[i * 2];
102             temp1 = (tempChar < BASE_LENGTH) ? HEX_NUMBER_TABLE[tempChar] : -1;
103             if (temp1 == -1) {
104                 return null;
105             }
106             tempChar = binaryData[i * 2 + 1];
107             temp2 = (tempChar < BASE_LENGTH) ? HEX_NUMBER_TABLE[tempChar] : -1;
108             if (temp2 == -1) {
109                 return null;
110             }
111             decodedData[i] = cast(byte) ((temp1 << 4) | temp2);
112         }
113         return decodedData;
114     }
115 }