/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.codec;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import org.cryptacular.EncodingException;
/**
* Stateless hexadecimal byte-to-character encoder.
*
* @author Middleware Services
*/
public class HexEncoder implements Encoder
{
/** Hex character encoding table. */
private static final char[] ENCODING_TABLE = new char[16];
/**
* Initializes the encoding character table.
*/
static {
final String charset = "0123456789abcdef";
for (int i = 0; i < charset.length(); i++) {
ENCODING_TABLE[i] = charset.charAt(i);
}
}
/** Flag indicating whether to delimit every two characters with ':' as in key fingerprints, etc. */
private final boolean delimit;
/** Creates a new instance that does not delimit bytes in the output hex string. */
public HexEncoder()
{
this(false);
}
/**
* Creates a new instance with optional delimiting of bytes in the output hex string.
*
* @param delimitBytes True to delimit every two characters (i.e. every byte) with ':' character.
*/
public HexEncoder(final boolean delimitBytes)
{
delimit = delimitBytes;
}
@Override
public void encode(final ByteBuffer input, final CharBuffer output) throws EncodingException
{
byte current;
while (input.hasRemaining()) {
current = input.get();
output.put(ENCODING_TABLE[(current & 0xf0) >> 4]);
output.put(ENCODING_TABLE[current & 0x0f]);
if (delimit && input.hasRemaining()) {
output.put(':');
}
}
}
@Override
public void finalize(final CharBuffer output) throws EncodingException {}
@Override
public int outputSize(final int inputSize)
{
int size = inputSize * 2;
if (delimit) {
size += inputSize - 1;
}
return size;
}
}