Coverage Report - org.apache.commons.codec.binary.Hex
 
Classes in this File Line Coverage Branch Coverage Complexity
Hex
97%
47/48
100%
14/14
1.938
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.codec.binary;
 19  
 
 20  
 import java.nio.charset.Charset;
 21  
 
 22  
 import org.apache.commons.codec.BinaryDecoder;
 23  
 import org.apache.commons.codec.BinaryEncoder;
 24  
 import org.apache.commons.codec.CharEncoding;
 25  
 import org.apache.commons.codec.Charsets;
 26  
 import org.apache.commons.codec.DecoderException;
 27  
 import org.apache.commons.codec.EncoderException;
 28  
 
 29  
 /**
 30  
  * Converts hexadecimal Strings. The charset used for certain operation can be set, the default is set in
 31  
  * {@link #DEFAULT_CHARSET_NAME}
 32  
  *
 33  
  * This class is thread-safe.
 34  
  *
 35  
  * @since 1.1
 36  
  * @version $Id$
 37  
  */
 38  
 public class Hex implements BinaryEncoder, BinaryDecoder {
 39  
 
 40  
     /**
 41  
      * Default charset name is {@link Charsets#UTF_8}
 42  
      *
 43  
      * @since 1.7
 44  
      */
 45  1
     public static final Charset DEFAULT_CHARSET = Charsets.UTF_8;
 46  
 
 47  
     /**
 48  
      * Default charset name is {@link CharEncoding#UTF_8}
 49  
      *
 50  
      * @since 1.4
 51  
      */
 52  
     public static final String DEFAULT_CHARSET_NAME = CharEncoding.UTF_8;
 53  
 
 54  
     /**
 55  
      * Used to build output as Hex
 56  
      */
 57  1
     private static final char[] DIGITS_LOWER =
 58  
         {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
 59  
 
 60  
     /**
 61  
      * Used to build output as Hex
 62  
      */
 63  1
     private static final char[] DIGITS_UPPER =
 64  
         {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
 65  
 
 66  
     /**
 67  
      * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
 68  
      * returned array will be half the length of the passed array, as it takes two characters to represent any given
 69  
      * byte. An exception is thrown if the passed char array has an odd number of elements.
 70  
      *
 71  
      * @param data
 72  
      *            An array of characters containing hexadecimal digits
 73  
      * @return A byte array containing binary data decoded from the supplied char array.
 74  
      * @throws DecoderException
 75  
      *             Thrown if an odd number or illegal of characters is supplied
 76  
      */
 77  
     public static byte[] decodeHex(final char[] data) throws DecoderException {
 78  
 
 79  366
         final int len = data.length;
 80  
 
 81  366
         if ((len & 0x01) != 0) {
 82  5
             throw new DecoderException("Odd number of characters.");
 83  
         }
 84  
 
 85  361
         final byte[] out = new byte[len >> 1];
 86  
 
 87  
         // two characters form the hex value.
 88  194153
         for (int i = 0, j = 0; j < len; i++) {
 89  193794
             int f = toDigit(data[j], j) << 4;
 90  193793
             j++;
 91  193793
             f = f | toDigit(data[j], j);
 92  193792
             j++;
 93  193792
             out[i] = (byte) (f & 0xFF);
 94  
         }
 95  
 
 96  359
         return out;
 97  
     }
 98  
 
 99  
     /**
 100  
      * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
 101  
      * The returned array will be double the length of the passed array, as it takes two characters to represent any
 102  
      * given byte.
 103  
      *
 104  
      * @param data
 105  
      *            a byte[] to convert to Hex characters
 106  
      * @return A char[] containing hexadecimal characters
 107  
      */
 108  
     public static char[] encodeHex(final byte[] data) {
 109  411
         return encodeHex(data, true);
 110  
     }
 111  
 
 112  
     /**
 113  
      * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
 114  
      * The returned array will be double the length of the passed array, as it takes two characters to represent any
 115  
      * given byte.
 116  
      *
 117  
      * @param data
 118  
      *            a byte[] to convert to Hex characters
 119  
      * @param toLowerCase
 120  
      *            {@code true} converts to lowercase, {@code false} to uppercase
 121  
      * @return A char[] containing hexadecimal characters
 122  
      * @since 1.4
 123  
      */
 124  
     public static char[] encodeHex(final byte[] data, final boolean toLowerCase) {
 125  415
         return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
 126  
     }
 127  
 
 128  
     /**
 129  
      * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
 130  
      * The returned array will be double the length of the passed array, as it takes two characters to represent any
 131  
      * given byte.
 132  
      *
 133  
      * @param data
 134  
      *            a byte[] to convert to Hex characters
 135  
      * @param toDigits
 136  
      *            the output alphabet
 137  
      * @return A char[] containing hexadecimal characters
 138  
      * @since 1.4
 139  
      */
 140  
     protected static char[] encodeHex(final byte[] data, final char[] toDigits) {
 141  415
         final int l = data.length;
 142  415
         final char[] out = new char[l << 1];
 143  
         // two characters form the hex value.
 144  195901
         for (int i = 0, j = 0; i < l; i++) {
 145  195486
             out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
 146  195486
             out[j++] = toDigits[0x0F & data[i]];
 147  
         }
 148  415
         return out;
 149  
     }
 150  
 
 151  
     /**
 152  
      * Converts an array of bytes into a String representing the hexadecimal values of each byte in order. The returned
 153  
      * String will be double the length of the passed array, as it takes two characters to represent any given byte.
 154  
      *
 155  
      * @param data
 156  
      *            a byte[] to convert to Hex characters
 157  
      * @return A String containing hexadecimal characters
 158  
      * @since 1.4
 159  
      */
 160  
     public static String encodeHexString(final byte[] data) {
 161  391
         return new String(encodeHex(data));
 162  
     }
 163  
 
 164  
     /**
 165  
      * Converts a hexadecimal character to an integer.
 166  
      *
 167  
      * @param ch
 168  
      *            A character to convert to an integer digit
 169  
      * @param index
 170  
      *            The index of the character in the source
 171  
      * @return An integer
 172  
      * @throws DecoderException
 173  
      *             Thrown if ch is an illegal hex character
 174  
      */
 175  
     protected static int toDigit(final char ch, final int index) throws DecoderException {
 176  387587
         final int digit = Character.digit(ch, 16);
 177  387587
         if (digit == -1) {
 178  2
             throw new DecoderException("Illegal hexadecimal character " + ch + " at index " + index);
 179  
         }
 180  387585
         return digit;
 181  
     }
 182  
 
 183  
     private final Charset charset;
 184  
 
 185  
     /**
 186  
      * Creates a new codec with the default charset name {@link #DEFAULT_CHARSET}
 187  
      */
 188  177
     public Hex() {
 189  
         // use default encoding
 190  177
         this.charset = DEFAULT_CHARSET;
 191  177
     }
 192  
 
 193  
     /**
 194  
      * Creates a new codec with the given Charset.
 195  
      *
 196  
      * @param charset
 197  
      *            the charset.
 198  
      * @since 1.7
 199  
      */
 200  165
     public Hex(final Charset charset) {
 201  165
         this.charset = charset;
 202  165
     }
 203  
 
 204  
     /**
 205  
      * Creates a new codec with the given charset name.
 206  
      *
 207  
      * @param charsetName
 208  
      *            the charset name.
 209  
      * @throws java.nio.charset.UnsupportedCharsetException
 210  
      *             If the named charset is unavailable
 211  
      * @since 1.4
 212  
      * @since 1.7 throws UnsupportedCharsetException if the named charset is unavailable
 213  
      */
 214  
     public Hex(final String charsetName) {
 215  166
         this(Charset.forName(charsetName));
 216  165
     }
 217  
 
 218  
     /**
 219  
      * Converts an array of character bytes representing hexadecimal values into an array of bytes of those same values.
 220  
      * The returned array will be half the length of the passed array, as it takes two characters to represent any given
 221  
      * byte. An exception is thrown if the passed char array has an odd number of elements.
 222  
      *
 223  
      * @param array
 224  
      *            An array of character bytes containing hexadecimal digits
 225  
      * @return A byte array containing binary data decoded from the supplied byte array (representing characters).
 226  
      * @throws DecoderException
 227  
      *             Thrown if an odd number of characters is supplied to this function
 228  
      * @see #decodeHex(char[])
 229  
      */
 230  
     @Override
 231  
     public byte[] decode(final byte[] array) throws DecoderException {
 232  172
         return decodeHex(new String(array, getCharset()).toCharArray());
 233  
     }
 234  
 
 235  
     /**
 236  
      * Converts a String or an array of character bytes representing hexadecimal values into an array of bytes of those
 237  
      * same values. The returned array will be half the length of the passed String or array, as it takes two characters
 238  
      * to represent any given byte. An exception is thrown if the passed char array has an odd number of elements.
 239  
      *
 240  
      * @param object
 241  
      *            A String or, an array of character bytes containing hexadecimal digits
 242  
      * @return A byte array containing binary data decoded from the supplied byte array (representing characters).
 243  
      * @throws DecoderException
 244  
      *             Thrown if an odd number of characters is supplied to this function or the object is not a String or
 245  
      *             char[]
 246  
      * @see #decodeHex(char[])
 247  
      */
 248  
     @Override
 249  
     public Object decode(final Object object) throws DecoderException {
 250  
         try {
 251  180
             final char[] charArray = object instanceof String ? ((String) object).toCharArray() : (char[]) object;
 252  179
             return decodeHex(charArray);
 253  1
         } catch (final ClassCastException e) {
 254  1
             throw new DecoderException(e.getMessage(), e);
 255  
         }
 256  
     }
 257  
 
 258  
     /**
 259  
      * Converts an array of bytes into an array of bytes for the characters representing the hexadecimal values of each
 260  
      * byte in order. The returned array will be double the length of the passed array, as it takes two characters to
 261  
      * represent any given byte.
 262  
      * <p>
 263  
      * The conversion from hexadecimal characters to the returned bytes is performed with the charset named by
 264  
      * {@link #getCharset()}.
 265  
      * </p>
 266  
      *
 267  
      * @param array
 268  
      *            a byte[] to convert to Hex characters
 269  
      * @return A byte[] containing the bytes of the hexadecimal characters
 270  
      * @since 1.7 No longer throws IllegalStateException if the charsetName is invalid.
 271  
      * @see #encodeHex(byte[])
 272  
      */
 273  
     @Override
 274  
     public byte[] encode(final byte[] array) {
 275  171
         return encodeHexString(array).getBytes(this.getCharset());
 276  
     }
 277  
 
 278  
     /**
 279  
      * Converts a String or an array of bytes into an array of characters representing the hexadecimal values of each
 280  
      * byte in order. The returned array will be double the length of the passed String or array, as it takes two
 281  
      * characters to represent any given byte.
 282  
      * <p>
 283  
      * The conversion from hexadecimal characters to bytes to be encoded to performed with the charset named by
 284  
      * {@link #getCharset()}.
 285  
      * </p>
 286  
      *
 287  
      * @param object
 288  
      *            a String, or byte[] to convert to Hex characters
 289  
      * @return A char[] containing hexadecimal characters
 290  
      * @throws EncoderException
 291  
      *             Thrown if the given object is not a String or byte[]
 292  
      * @see #encodeHex(byte[])
 293  
      */
 294  
     @Override
 295  
     public Object encode(final Object object) throws EncoderException {
 296  
         try {
 297  12
             final byte[] byteArray = object instanceof String ?
 298  
                                    ((String) object).getBytes(this.getCharset()) : (byte[]) object;
 299  11
             return encodeHex(byteArray);
 300  1
         } catch (final ClassCastException e) {
 301  1
             throw new EncoderException(e.getMessage(), e);
 302  
         }
 303  
     }
 304  
 
 305  
     /**
 306  
      * Gets the charset.
 307  
      *
 308  
      * @return the charset.
 309  
      * @since 1.7
 310  
      */
 311  
     public Charset getCharset() {
 312  519
         return this.charset;
 313  
     }
 314  
 
 315  
     /**
 316  
      * Gets the charset name.
 317  
      *
 318  
      * @return the charset name.
 319  
      * @since 1.4
 320  
      */
 321  
     public String getCharsetName() {
 322  0
         return this.charset.name();
 323  
     }
 324  
 
 325  
     /**
 326  
      * Returns a string representation of the object, which includes the charset name.
 327  
      *
 328  
      * @return a string representation of the object.
 329  
      */
 330  
     @Override
 331  
     public String toString() {
 332  1
         return super.toString() + "[charsetName=" + this.charset + "]";
 333  
     }
 334  
 }