001/**
002 * Copyright (c) 2014 Digi International Inc.,
003 * All rights not expressly granted are reserved.
004 *
005 * This Source Code Form is subject to the terms of the Mozilla Public
006 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
007 * You can obtain one at http://mozilla.org/MPL/2.0/.
008 *
009 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
010 * =======================================================================
011 */
012package com.digi.xbee.api.utils;
013
014/**
015 * Utility class containing methods to work with hexadecimal values and several 
016 * data type conversions.
017 */
018public class HexUtils {
019
020        // Constants.
021        private static final String HEXES = "0123456789ABCDEF";
022        private static final String HEX_HEADER = "0x";
023        
024        /**
025         * Converts the given byte array into an hex string.
026         * 
027         * @param value Byte array to convert to hex string.
028         * 
029         * @return Converted byte array to hex string.
030         * 
031         * @throws NullPointerException if {@code value == null}.
032         * 
033         * @see #hexStringToByteArray(String)
034         */
035        public static String byteArrayToHexString(byte[] value) {
036                if (value == null )
037                        throw new NullPointerException("Value to convert cannot be null");
038                final StringBuilder hex = new StringBuilder(2 * value.length );
039                for (final byte b : value) {
040                        hex.append(HEXES.charAt((b & 0xF0) >> 4))
041                                .append(HEXES.charAt((b & 0x0F)));
042                }
043                return hex.toString();
044        }
045        
046        /**
047         * Converts the given byte into an hex string.
048         * 
049         * @param value Byte to convert to hex string.
050         * 
051         * @return Converted byte to hex string.
052         */
053        public static String byteToHexString(byte value) {
054                final StringBuilder hex = new StringBuilder(2);
055                byte b = value;
056                hex.append(HEXES.charAt((b & 0xF0) >> 4))
057                        .append(HEXES.charAt((b & 0x0F)));
058                return hex.toString();
059        }
060        
061        /**
062         * Converts the given hex string into a byte array.
063         * 
064         * @param value Hex string to convert to byte array.
065         * 
066         * @return Byte array of the given hex string.
067         * 
068         * @throws NullPointerException if {@code value == null}.
069         * 
070         * @see #byteArrayToHexString(byte[])
071         */
072        public static byte[] hexStringToByteArray(String value) {
073                if (value == null)
074                        throw new NullPointerException("Value to convert cannot be null.");
075                
076                value = value.trim();
077                if (value.startsWith(HEX_HEADER))
078                        value = value.substring((HEX_HEADER).length());
079                int len = value.length();
080                if (len % 2 != 0) {
081                        value = "0" + value;
082                        len = value.length();
083                }
084                byte[] data = new byte[len / 2];
085                for (int i = 0; i < len; i += 2) {
086                        data[i / 2] = (byte) ((Character.digit(value.charAt(i), 16) << 4)
087                                        + Character.digit(value.charAt(i+1), 16));
088                }
089                return data;
090        }
091        
092        /**
093         * Checks whether the given parameter is a string or a numeric value.
094         * 
095         * @param parameter Parameter to check.
096         * 
097         * @return {@code true} if the given parameter is a string,
098         *         {@code false} otherwise.
099         * 
100         * @throws NullPointerException if {@code parameter == null}.
101         */
102        public static boolean containsLetters(String parameter) {
103                if (parameter == null)
104                        throw new NullPointerException("Parameter cannot be null.");
105                
106                byte[] byteArray = parameter.getBytes();
107                for (int i = 0; i < byteArray.length; i++){
108                        if (!((byteArray[i] >= '0') && (byteArray[i] <= '9')))
109                                return true;
110                }
111                return false;
112        }
113        
114        /**
115         * Converts the given integer into an hexadecimal string.
116         * 
117         * @param value The integer value to convert to hexadecimal string.
118         * @param minBytes The minimum number of bytes to be represented.
119         * 
120         * @return The integer value as hexadecimal string.
121         */
122        public static String integerToHexString(int value, int minBytes) {
123                byte[] intAsByteArray = ByteUtils.intToByteArray(value);
124                String intAsHexString = "";
125                boolean numberFound = false;
126                for (int i = 0; i < intAsByteArray.length; i++) {
127                        if (intAsByteArray[i] == 0x00 && !numberFound && intAsByteArray.length - i > minBytes)
128                                continue;
129                        intAsHexString += HexUtils.byteArrayToHexString(new byte[] {(byte)(intAsByteArray[i] & 0xFF)});
130                        numberFound = true;
131                }
132                return intAsHexString;
133        }
134        
135        /**
136         * Converts the given hexadecimal string to a pretty format by splitting the 
137         * content byte by byte.
138         * 
139         * @param hexString The hexadecimal string to convert.
140         * 
141         * @return The hexadecimal string with pretty format.
142         * 
143         * @throws NullPointerException if {@code hexString == null}.
144         * 
145         * @see #prettyHexString(byte[])
146         */
147        public static String prettyHexString(String hexString) {
148                if (hexString == null)
149                        throw new NullPointerException("Hexadecimal string cannot be null.");
150                
151                String prettyHexString = "";
152                if (hexString.length() % 2 != 0)
153                        hexString = "0" + hexString;
154                int iterations = hexString.length() / 2;
155                for (int i = 0; i < iterations; i++)
156                        prettyHexString += hexString.substring(2 * i, 2 * i + 2) + " ";
157                return prettyHexString.trim();
158        }
159        
160        /**
161         * Converts the given byte array into an hex string and retrieves it 
162         * in pretty format by splitting the content byte by byte.
163         * 
164         * @param value The byte array to convert to pretty hex string.
165         * 
166         * @return The hexadecimal pretty string.
167         * 
168         * @throws NullPointerException if {@code value == null}.
169         * 
170         * @see #prettyHexString(String)
171         */
172        public static String prettyHexString(byte[] value) {
173                return prettyHexString(byteArrayToHexString(value));
174        }
175}