001/* 002 * Copyright 2020 Vonage 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.vonage.client.sms; 017 018import com.vonage.client.VonageUnexpectedException; 019 020import java.io.UnsupportedEncodingException; 021 022 023/** 024 * Static helper methods for working with hex values. 025 * 026 * @author Paul Cook 027 */ 028public class HexUtil { 029 030 private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', }; 031 032 private HexUtil() { 033 // This class may not be instantiated. 034 } 035 036 /** 037 * translate a byte array of raw data into a String with a hex representation of that data 038 * 039 * @param bytes raw binary data 040 * 041 * @return String Hex representation of the raw data 042 */ 043 public static String bytesToHex(byte[] bytes) { 044 return bytesToHex(bytes, null); 045 } 046 047 /** 048 * translate a byte array of raw data into a String with a hex representation of that data. 049 * Each octet will be separated with a specific separator. 050 * 051 * @param bytes raw binary data 052 * @param separator This string will be injected into the output in between each octet in the stream 053 * 054 * @return String Hex representation of the raw data with each octet separated by 'separator' 055 */ 056 public static String bytesToHex(byte[] bytes, String separator) { 057 StringBuilder tmpBuffer = new StringBuilder(); 058 if (bytes != null) { 059 for (byte c : bytes) { 060 int b = c; 061 if (b < 0) 062 b += 256; 063 if (separator != null) 064 tmpBuffer.append(separator); 065 tmpBuffer.append(HEX_CHARS[(b & 0xf0) / 0x10]); // note, this benchmarks faster than using >> 4 066 tmpBuffer.append(HEX_CHARS[b & 0x0f]); 067 } 068 } 069 return tmpBuffer.toString(); 070 } 071 072 /** 073 * Converts a Hex encoded String into a byte vector. 074 * 075 * @param str The String to be encoded. 076 * 077 * @return A byte vector representing the String. 078 */ 079 public static byte[] hexToBytes(String str) { 080 if (str == null) 081 return null; 082 byte[] hexChars; 083 try { 084 hexChars = str.toUpperCase().getBytes("ISO_8859-1"); 085 } catch (UnsupportedEncodingException e) { 086 throw new VonageUnexpectedException("ISO_8859_1 is an unsupported encoding in this JVM"); 087 } 088 int size = hexChars.length; 089 byte[] bytes = new byte[size / 2]; 090 int first; 091 int second; 092 093 int rIndex = 0; 094 // Convert to bytes. 095 for (int i = 0; i+1 <size; i= i + 2) { 096 097 // Convert first 098 first = hexChars[i]; 099 if (first < 58) 100 first = ((first - 48) * 16); // 0 - 9 101 else 102 first = ((first - 55) * 16); // A - F 103 104 // Convert second 105 second = hexChars[i + 1]; 106 if (second < 58) 107 second = second - 48; // 0 - 9 108 else 109 second = second - 55; // A - F 110 111 //Value must be between -128 and 127 112 int total = (first + second); 113 if (total > 127) 114 total = (256 + total); 115 116 bytes[rIndex] = (byte) total; 117 rIndex++; 118 } 119 return bytes; 120 } 121 122}