/* * Copyright (c) 2009-2012 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'jMonkeyEngine' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jme3.export.binary; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * <code>ByteUtils</code> is a helper class for converting numeric primitives * to and from byte representations. * * @author Joshua Slack */ public class ByteUtils { /** * Takes an InputStream and returns the complete byte content of it * * @param inputStream * The input stream to read from * @return The byte array containing the data from the input stream * @throws java.io.IOException * thrown if there is a problem reading from the input stream * provided */ public static byte[] getByteContent(InputStream inputStream) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream( 16 * 1024); byte[] buffer = new byte[1024]; int byteCount = -1; byte[] data = null; // Read the byte content into the output stream first while ((byteCount = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, byteCount); } // Set data with byte content from stream data = outputStream.toByteArray(); // Release resources outputStream.close(); return data; } // ********** byte <> short METHODS ********** /** * Writes a short out to an OutputStream. * * @param outputStream * The OutputStream the short will be written to * @param value * The short to write * @throws IOException * Thrown if there is a problem writing to the OutputStream */ public static void writeShort(OutputStream outputStream, short value) throws IOException { byte[] byteArray = convertToBytes(value); outputStream.write(byteArray); return; } public static byte[] convertToBytes(short value) { byte[] byteArray = new byte[2]; byteArray[0] = (byte) (value >> 8); byteArray[1] = (byte) value; return byteArray; } /** * Read in a short from an InputStream * * @param inputStream * The InputStream used to read the short * @return A short, which is the next 2 bytes converted from the InputStream * @throws IOException * Thrown if there is a problem reading from the InputStream */ public static short readShort(InputStream inputStream) throws IOException { byte[] byteArray = new byte[2]; // Read in the next 2 bytes inputStream.read(byteArray); short number = convertShortFromBytes(byteArray); return number; } public static short convertShortFromBytes(byte[] byteArray) { return convertShortFromBytes(byteArray, 0); } public static short convertShortFromBytes(byte[] byteArray, int offset) { // Convert it to a short short number = (short) ((byteArray[offset+1] & 0xFF) + ((byteArray[offset+0] & 0xFF) << 8)); return number; } // ********** byte <> int METHODS ********** /** * Writes an integer out to an OutputStream. * * @param outputStream * The OutputStream the integer will be written to * @param integer * The integer to write * @throws IOException * Thrown if there is a problem writing to the OutputStream */ public static void writeInt(OutputStream outputStream, int integer) throws IOException { byte[] byteArray = convertToBytes(integer); outputStream.write(byteArray); return; } public static byte[] convertToBytes(int integer) { byte[] byteArray = new byte[4]; byteArray[0] = (byte) (integer >> 24); byteArray[1] = (byte) (integer >> 16); byteArray[2] = (byte) (integer >> 8); byteArray[3] = (byte) integer; return byteArray; } /** * Read in an integer from an InputStream * * @param inputStream * The InputStream used to read the integer * @return An int, which is the next 4 bytes converted from the InputStream * @throws IOException * Thrown if there is a problem reading from the InputStream */ public static int readInt(InputStream inputStream) throws IOException { byte[] byteArray = new byte[4]; // Read in the next 4 bytes inputStream.read(byteArray); int number = convertIntFromBytes(byteArray); return number; } public static int convertIntFromBytes(byte[] byteArray) { return convertIntFromBytes(byteArray, 0); } public static int convertIntFromBytes(byte[] byteArray, int offset) { // Convert it to an int int number = ((byteArray[offset] & 0xFF) << 24) + ((byteArray[offset+1] & 0xFF) << 16) + ((byteArray[offset+2] & 0xFF) << 8) + (byteArray[offset+3] & 0xFF); return number; } // ********** byte <> long METHODS ********** /** * Writes a long out to an OutputStream. * * @param outputStream * The OutputStream the long will be written to * @param value * The long to write * @throws IOException * Thrown if there is a problem writing to the OutputStream */ public static void writeLong(OutputStream outputStream, long value) throws IOException { byte[] byteArray = convertToBytes(value); outputStream.write(byteArray); return; } public static byte[] convertToBytes(long n) { byte[] bytes = new byte[8]; bytes[7] = (byte) (n); n >>>= 8; bytes[6] = (byte) (n); n >>>= 8; bytes[5] = (byte) (n); n >>>= 8; bytes[4] = (byte) (n); n >>>= 8; bytes[3] = (byte) (n); n >>>= 8; bytes[2] = (byte) (n); n >>>= 8; bytes[1] = (byte) (n); n >>>= 8; bytes[0] = (byte) (n); return bytes; } /** * Read in a long from an InputStream * * @param inputStream * The InputStream used to read the long * @return A long, which is the next 8 bytes converted from the InputStream * @throws IOException * Thrown if there is a problem reading from the InputStream */ public static long readLong(InputStream inputStream) throws IOException { byte[] byteArray = new byte[8]; // Read in the next 8 bytes inputStream.read(byteArray); long number = convertLongFromBytes(byteArray); return number; } public static long convertLongFromBytes(byte[] bytes) { return convertLongFromBytes(bytes, 0); } public static long convertLongFromBytes(byte[] bytes, int offset) { // Convert it to an long return ((((long) bytes[offset+7]) & 0xFF) + ((((long) bytes[offset+6]) & 0xFF) << 8) + ((((long) bytes[offset+5]) & 0xFF) << 16) + ((((long) bytes[offset+4]) & 0xFF) << 24) + ((((long) bytes[offset+3]) & 0xFF) << 32) + ((((long) bytes[offset+2]) & 0xFF) << 40) + ((((long) bytes[offset+1]) & 0xFF) << 48) + ((((long) bytes[offset+0]) & 0xFF) << 56)); } // ********** byte <> double METHODS ********** /** * Writes a double out to an OutputStream. * * @param outputStream * The OutputStream the double will be written to * @param value * The double to write * @throws IOException * Thrown if there is a problem writing to the OutputStream */ public static void writeDouble(OutputStream outputStream, double value) throws IOException { byte[] byteArray = convertToBytes(value); outputStream.write(byteArray); return; } public static byte[] convertToBytes(double n) { long bits = Double.doubleToLongBits(n); return convertToBytes(bits); } /** * Read in a double from an InputStream * * @param inputStream * The InputStream used to read the double * @return A double, which is the next 8 bytes converted from the InputStream * @throws IOException * Thrown if there is a problem reading from the InputStream */ public static double readDouble(InputStream inputStream) throws IOException { byte[] byteArray = new byte[8]; // Read in the next 8 bytes inputStream.read(byteArray); double number = convertDoubleFromBytes(byteArray); return number; } public static double convertDoubleFromBytes(byte[] bytes) { return convertDoubleFromBytes(bytes, 0); } public static double convertDoubleFromBytes(byte[] bytes, int offset) { // Convert it to a double long bits = convertLongFromBytes(bytes, offset); return Double.longBitsToDouble(bits); } // ********** byte <> float METHODS ********** /** * Writes an float out to an OutputStream. * * @param outputStream * The OutputStream the float will be written to * @param fVal * The float to write * @throws IOException * Thrown if there is a problem writing to the OutputStream */ public static void writeFloat(OutputStream outputStream, float fVal) throws IOException { byte[] byteArray = convertToBytes(fVal); outputStream.write(byteArray); return; } public static byte[] convertToBytes(float f) { int temp = Float.floatToIntBits(f); return convertToBytes(temp); } /** * Read in a float from an InputStream * * @param inputStream * The InputStream used to read the float * @return A float, which is the next 4 bytes converted from the InputStream * @throws IOException * Thrown if there is a problem reading from the InputStream */ public static float readFloat(InputStream inputStream) throws IOException { byte[] byteArray = new byte[4]; // Read in the next 4 bytes inputStream.read(byteArray); float number = convertFloatFromBytes(byteArray); return number; } public static float convertFloatFromBytes(byte[] byteArray) { return convertFloatFromBytes(byteArray, 0); } public static float convertFloatFromBytes(byte[] byteArray, int offset) { // Convert it to an int int number = convertIntFromBytes(byteArray, offset); return Float.intBitsToFloat(number); } // ********** byte <> boolean METHODS ********** /** * Writes a boolean out to an OutputStream. * * @param outputStream * The OutputStream the boolean will be written to * @param bVal * The boolean to write * @throws IOException * Thrown if there is a problem writing to the OutputStream */ public static void writeBoolean(OutputStream outputStream, boolean bVal) throws IOException { byte[] byteArray = convertToBytes(bVal); outputStream.write(byteArray); return; } public static byte[] convertToBytes(boolean b) { byte[] rVal = new byte[1]; rVal[0] = b ? (byte)1 : (byte)0; return rVal; } /** * Read in a boolean from an InputStream * * @param inputStream * The InputStream used to read the boolean * @return A boolean, which is the next byte converted from the InputStream (iow, byte != 0) * @throws IOException * Thrown if there is a problem reading from the InputStream */ public static boolean readBoolean(InputStream inputStream) throws IOException { byte[] byteArray = new byte[1]; // Read in the next byte inputStream.read(byteArray); return convertBooleanFromBytes(byteArray); } public static boolean convertBooleanFromBytes(byte[] byteArray) { return convertBooleanFromBytes(byteArray, 0); } public static boolean convertBooleanFromBytes(byte[] byteArray, int offset) { return byteArray[offset] != 0; } /** * Properly reads in data from the given stream until the specified number * of bytes have been read. * * @param store * the byte array to store in. Should have a length > bytes * @param bytes * the number of bytes to read. * @param is * the stream to read from * @return the store array for chaining purposes * @throws IOException * if an error occurs while reading from the stream * @throws ArrayIndexOutOfBoundsException * if bytes greater than the length of the store. */ public static byte[] readData(byte[] store, int bytes, InputStream is) throws IOException { for (int i = 0; i < bytes; i++) { store[i] = (byte)is.read(); } return store; } public static byte[] rightAlignBytes(byte[] bytes, int width) { if (bytes.length != width) { byte[] rVal = new byte[width]; for (int x = width - bytes.length; x < width; x++) { rVal[x] = bytes[x - (width - bytes.length)]; } return rVal; } return bytes; } }