package edu.colostate.vchill.socket;
import edu.colostate.vchill.ChillDefines;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* Utility functions for VCHILL's Socket Module
*
* @author Jochen Deyke
* @author Alexander Deyke
* @author jpont
* @version 2010-08-30
*/
public final class SocketUtil {
/**
* @param source the array to read from
* @param offset location in source of the highest byte
* @return the int read
*/
public static long readUnsignedInt(final byte[] source, final int offset) {
requireSourceLength(source, offset, ChillDefines.INT_BYTE_SIZE);
return ((source[offset] & 0xff) << 24) |
((source[offset + 1] & 0xff) << 16) |
((source[offset + 2] & 0xff) << 8) |
((source[offset + 3] & 0xff));
}
/**
* @param source the array to read from
* @param offset location in source of the highest byte
* @return the int read
*/
public static int readInt(final byte[] source, final int offset) {
requireSourceLength(source, offset, ChillDefines.INT_BYTE_SIZE);
return ((source[offset] & 0xff) << 24) |
((source[offset + 1] & 0xff) << 16) |
((source[offset + 2] & 0xff) << 8) |
((source[offset + 3] & 0xff));
}
/**
* @param source the array to read from
* @param offset location in source of the highest byte
* @return the short read
*/
public static short readShort(final byte[] source, final int offset) {
requireSourceLength(source, offset, ChillDefines.SHORT_BYTE_SIZE);
return (short) (((source[offset] & 0xff) << 8) |
((source[offset + 1] & 0xff)));
}
/**
* @param source the array to read from
* @param offset location in source of the highest byte
* @return the float read
*/
public static float readFloat(final byte[] source, final int offset) {
requireSourceLength(source, offset, ChillDefines.FLOAT_BYTE_SIZE);
return Float.intBitsToFloat(readInt(source, offset));
}
/**
* @param data the float to translate
* @param destination the array to write to
* @param offset location where highest byte goes
* @return the number of bytes written
*/
public static int writeFloat(final float data, final byte[] destination, int offset) {
return writeInt(Float.floatToIntBits(data), destination, offset);
}
/**
* @param source the array to read from
* @param offset location in source of the highest byte
* @return the float read
*/
public static String readString(final byte[] source, final int offset, final int length) {
requireSourceLength(source, offset, length);
try {
return new String(source, offset, length, "UTF-8");
} catch (UnsupportedEncodingException uee) {
System.err.println(uee + "\nSwitching to default encoding");
return new String(source, offset, length);
}
}
/**
* @param data the String to translate
* @param length the length (number of bytes) to write
* @param destination the array to write to
* @param offset location where highest byte goes
* @return the number of bytes written
*/
public static int writeString(final String data, final int length, final byte[] destination, int offset) {
requireDestinationLength(destination, offset, length);
byte[] src;
try {
src = data.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
System.err.println(uee + "\nSwitching to default encoding");
src = data.getBytes();
}
for (int i = 0; i < length; ++i) {
destination[offset + i] = i < src.length - 1 ? src[i] : 0;
}
return length;
}
/**
* @param data the int to translate
* @param destination the array to write to
* @param offset location where highest byte goes
* @return the number of bytes written
*/
public static int writeInt(final int data, final byte[] destination, int offset) {
requireDestinationLength(destination, offset, ChillDefines.INT_BYTE_SIZE);
destination[offset++] = (byte) (data >> 24);
destination[offset++] = (byte) (data >> 16);
destination[offset++] = (byte) (data >> 8);
destination[offset] = (byte) (data);
return ChillDefines.INT_BYTE_SIZE;
}
/**
* @param data the short to translate
* @param destination the array to write to
* @param offset location where highest byte goes
* @return the number of bytes written
*/
public static int writeShort(final int data, final byte[] destination, int offset) {
requireDestinationLength(destination, offset, ChillDefines.SHORT_BYTE_SIZE);
destination[offset++] = (byte) (data >> 8);
destination[offset] = (byte) (data);
return ChillDefines.SHORT_BYTE_SIZE;
}
/**
* @param source the byte array to copy from
* @param sOffset offset in the source array (ie first byte copied is source[sOffset]
* @param destination the array to copy into
* @param dOffset offset in the destination array (ie first byte overwritten is destination[dOffset]
* @param length the number of bytes to copy
* @return the number of bytes copied
*/
public static int copyBytes(final byte[] source, final int sOffset,
final byte[] destination, final int dOffset, final int length) {
requireSourceLength(source, sOffset, length);
requireDestinationLength(destination, dOffset, length);
for (int i = 0; i < length; ++i) {
destination[i + dOffset] = source[i + sOffset];
}
return length;
}
/**
* Helper method to check the Contract precondition of read methods
*/
private static void requireSourceLength(final byte[] source, final int offset, final int length) {
if (source.length < offset + length - 1) {
throw new IllegalArgumentException("Not enough data available in source array:\n have " + source.length + " bytes, need " + (offset + length));
}
}
/**
* Helper method to check the Contract precondition of write methods
*/
private static void requireDestinationLength(final byte[] destination, final int offset, final int length) {
if (destination.length < offset + length - 1) {
throw new IllegalArgumentException("Not enough room available in destination array:\n have " + destination.length + " bytes, need " + (offset + length));
}
}
public static long readUnsignedInt(final DataInput in) throws IOException {
return in.readInt();
}
public static void writeUnsignedInt(final long data, final DataOutput out) throws IOException {
out.writeInt((int) data);
}
public static String readString(final DataInput in, final int length) {
try {
byte bytes[] = new byte[length];
in.readFully(bytes);
return new String(bytes, "UTF-8").trim();
} catch (IOException ioe) {
throw new Error(ioe);
}
}
public static void writeString(final String data, final DataOutput out, final int length) {
try {
byte[] bytes = data.getBytes("UTF-8");
assert bytes.length <= length;
out.write(bytes);
if (bytes.length < length) out.write(new byte[length - bytes.length]); //pad
} catch (IOException ioe) {
throw new Error(ioe);
}
}
}