com.cloudhopper.commons.util.ByteUtil Maven / Gradle / Ivy
package com.cloudhopper.commons.util;
/*
* #%L
* ch-commons-util
* %%
* Copyright (C) 2012 Cloudhopper by Twitter
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
/**
* Utility class for methods to handle bytes.
*
* @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer)
*/
public class ByteUtil {
/**
* BCD encodes a String into a byte array.
*/
public static byte[] encodeBcd(String data, int num_bytes) {
// allocate buffer
byte buf[] = new byte[num_bytes];
// if length of addr is odd, then add an F onto the end of it
if ((data.length() % 2) != 0) {
data += "F";
}
int index = 0;
for (int i = 0; i < data.length(); i += 2) {
StringBuilder x = new StringBuilder(data.substring(i, i + 2));
x.reverse();
buf[index] = ByteUtil.decodeHex(x.toString(), 2)[0];
index++;
}
return buf;
}
/**
* BCD decodes a byte array into a String. For example, addresses inside
* PDUs for SMS are usually BCD encoded. An address of "13134434272" will
* actually look like this inside the byte[] "31314443722F"
*
* len is the number of bytes
* to read.
*/
public static String decodeBcd(byte[] data, int offset, int len) {
StringBuilder result = new StringBuilder();
// loop through byte array until we get to the end or an F
for (int i = offset; i < (offset + len); i++) {
// get buffer
StringBuilder x = new StringBuilder(encodeHex(data[i]));
// reverse it
x.reverse();
// add it to the data
if (x.charAt(1) == 'F' || x.charAt(1) == 'f') {
result.append(x.substring(0, 1));
} else {
result.append(x.toString());
}
}
return result.toString();
}
/**
* Decodes the string data (in hex) into a byte array.
* @param width The width of the hex encoding (2 or 4)
* @deprecated Please see class HexUtil
*/
@Deprecated
public static byte[] decodeHex(String hexString, int width) {
return HexUtil.toByteArray(hexString);
/**
// the resulting string
StringBuffer result = new StringBuffer();
// just cycle through the whole string two chars at a time
for (int i = 0; i < data.length(); i += width) {
result.append((char) Integer.parseInt(data.substring(i, i + width), 16));
}
// return whats rightfully the user's
try {
return result.toString().getBytes("ISO-8859-1");
} catch (Exception e) {
// should never happen
}
return null;
*/
}
/**
* Encodes a byte into a hex string (hex dump).
* @deprecated Please see class HexUtil
*/
@Deprecated
public static String encodeHex(byte value) {
return HexUtil.toHexString(value);
/**
// the result
StringBuffer result = new StringBuffer();
short val = decodeUnsigned(data);
result.append(padLeading(Integer.toHexString((int) val), 2));
// return encoded text
return result.toString();
*/
}
/**
* Encodes a byte array into a hex string (hex dump).
* @deprecated Please see class HexUtil
*/
@Deprecated
public static String encodeHex(byte[] bytes) {
return HexUtil.toHexString(bytes);
/**
// the result
StringBuffer result = new StringBuffer();
short val = 0;
// encode each byte into a hex dump
for (int i = 0; i < data.length; i++) {
val = decodeUnsigned(data[i]);
result.append(padLeading(Integer.toHexString((int) val), 2));
}
// return encoded text
return result.toString();
*/
}
/**
* Encodes a byte array into a hex string (hex dump).
* @deprecated Please see class HexUtil
*/
@Deprecated
public static String encodeHex(byte[] data, char delimiter) {
// the result
StringBuilder result = new StringBuilder();
short val = 0;
// encode each byte into a hex dump
for (int i = 0; i < data.length; i++) {
val = decodeUnsigned(data[i]);
result.append(padLeading(Integer.toHexString((int) val), 2));
result.append(delimiter);
}
// return encoded text
return result.toString();
}
public static String padLeading(String data, int width) {
// the number of zeros to add
int num = width - data.length();
// check if we're looking at a stupid programmer
if (0 >= num) {
return data;
}
// a temp string
StringBuilder result = new StringBuilder();
// add all the zeros
for (int i = 0; i < num; i++) {
result.append('0');
}
// add the original string
result.append(data);
// return the damn string
return result.toString();
}
/**
* Allow a variable of type byte
to carry lengths or sizes up to 255.
* The integral types are signed in Java, so if there is necessary to store
* an unsigned type into signed of the same size, the value can be stored
* as negative number even if it would be positive in unsigned case.
* For example message length can be 0 to 254 and is carried by 1 octet
* i.e. unsigned 8 bits. We use a byte variable to read the value from octet stream.
* If the length is >127, it is interpreted as negative byte using negative
* complement notation.
* So length 150 would be interpreted as Java byte -106. If we want to know
* the actual value (*length) we need to make a correction to a bigger integral type,
* in case of byte it's short. The correction from (negative) byte to short is
* (short)(256+(short)length)
* This converts the negative byte value representing positive length into positive
* short value.
* @see #encodeUnsigned(short)
*/
public static short decodeUnsigned(byte signed)
{
if (signed >= 0) {
return signed;
} else {
return (short)(256+(short)signed);
}
}
}