All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.illposed.osc.utility.OSCJavaToByteArrayConverter Maven / Gradle / Ivy

The newest version!
/**
 * @author cramakrishnan
 *
 * Copyright (C) 2003, C. Ramakrishnan / Illposed Software
 * All rights reserved.
 * 
 * See license.txt (or license.rtf) for license information.
 * 
 * 
 * OSCJavaToByteArrayConverter is a helper class that translates
 * from Java types to the format the OSC spec specifies for those
 * types.
 *
 * This implementation is based on Markus Gaelli and
 * Iannis Zannos' OSC implementation in Squeak:
 * http://www.emergent.de/Goodies/
 */

package com.illposed.osc.utility;

import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.util.Enumeration;
import java.util.Vector;


public class OSCJavaToByteArrayConverter {

	protected ByteArrayOutputStream stream = new ByteArrayOutputStream();
	private byte[] intBytes = new byte[4];

	/*public OSCJavaToByteArrayConverter() {
		super();
	}*/

	/**
	 * Creation date: (2/23/2001 2:43:25 AM)
	 * @param anArray java.lang.Object[]
	 *
	 */
	public void appendNullCharToAlignStream() {
		int mod = stream.size() % 4;
		int pad = 4 - mod;
		for (int i = 0; i < pad; i++)
			stream.write(0);
	}

	/**
	 * Creation date: (2/23/2001 2:21:53 AM)
	 * @return byte[]
	 */
	public byte[] toByteArray() {
		return stream.toByteArray();
	}

	/**
	 * Creation date: (2/23/2001 2:14:23 AM)
	 * @param bytes byte[]
	 */
	public void write(byte[] bytes) {
		writeBigEndToFourByteBoundry(bytes);
	}

	/**
	 * Creation date: (2/23/2001 2:21:04 AM)
	 * @param i int
	 */
	public void write(int i) {
		writeIntegerToByteArray(i);
	}

	/**
	 * Creation date: (2/23/2001 2:03:57 AM)
	 * @param f java.lang.Float
	 */
	public void write(Float f) {
		writeIntegerToByteArray(Float.floatToIntBits(f.floatValue()));
	}

	/**
	 * Creation date: (2/23/2001 2:08:36 AM)
	 * @param i java.lang.Integer
	 */
	public void write(Integer i) {
		writeIntegerToByteArray(i.intValue());
	}

	/**
	 * Creation date: (2/23/2001 1:57:35 AM)
	 * @param str java.lang.String
	 */
	public void write(String str) {
		writeLittleEndToFourByteBoundry(str.getBytes());
	}

	/**
	 * Creation date: (2/23/2001 2:08:36 AM)
	 * @param c char
	 */
	public void write(char c) {
		stream.write(c);
	}

	/**
	 * Creation date: (2/23/2001 2:02:54 AM)
	 * @param anObject java.lang.Object
	 */
	public void write(Object anObject) {
		// Can't do switch on class
		if (null == anObject)
			return;
		if (anObject instanceof Float) {
			write((Float) anObject);
			return;
		}
		if (anObject instanceof String) {
			write((String) anObject);
			return;
		}
		if (anObject instanceof Integer) {
			write((Integer) anObject);
			return;
		}
	}

	/**
	 * Creation date: (2/23/2001 2:43:25 AM)
	 * @param aClass Class
	 */
	public void writeType(Class c) {
		// A big ol' case statement -- what's polymorphism mean, again?
		// I really wish I could extend the base classes!

		// use the appropriate flags to tell SuperCollider what kind of 
		// thing it is looking at

		if (Integer.class.equals(c)) {
			stream.write('i');
			return;
		}
		if (java.math.BigInteger.class.equals(c)) {
			stream.write('h');
			return;
		}
		if (Float.class.equals(c)) {
			stream.write('f');
			return;
		}
		if (Double.class.equals(c)) {
			stream.write('d');
			return;
		}
		if (String.class.equals(c)) {
			stream.write('s');
			return;
		}
		if (Character.class.equals(c)) {
			stream.write('c');
			return;
		}
	}

	/**
	 * Creation date: (2/23/2001 2:43:25 AM)
	 * @param anArray java.lang.Object[]
	 */
	public void writeTypesArray(Object[] array) {
		// A big ol' case statement in a for loop -- what's polymorphism mean, again?
		// I really wish I could extend the base classes!

		for (int i = 0; i < array.length; i++) {
			if (null == array[i])
				continue;
			// if the array at i is a type of array write a [
			// This is used for nested arguments
			if (array[i].getClass().isArray()) {
				stream.write('[');
				// fill the [] with the SuperCollider types corresponding to the object
				// (i.e. Object of type String needs -s).
				writeTypesArray((Object[]) array[i]);
				// close the array
				stream.write(']');
				continue;
			}
			// Create a way to deal with Boolean type objects
			if (Boolean.TRUE.equals(array[i])) {
				stream.write('T');
				continue;
			}
			if (Boolean.FALSE.equals(array[i])) {
				stream.write('F');
				continue;
			}
			// go through the array and write the superCollider types as shown in the 
			// above method. the Classes derived here are used as the arg to the above method
			writeType(array[i].getClass());
		}
		// align the stream with padded bytes
		appendNullCharToAlignStream();
	}
	
	/**
	 * Same as writeSuperColliderTypes(Object[]), just that it takes a vector (for jdk1.1
	 * compatibility), rather than an array.
	 * @param vector  the collection I am to write out types for
	 */
	public void writeTypes(Vector vector) {
		// A big ol' case statement in a for loop -- what's polymorphism mean, again?
		// I really wish I could extend the base classes!

		Enumeration enm = vector.elements();
		Object nextObject;
		while (enm.hasMoreElements()) {
			nextObject = enm.nextElement();
			if (null == nextObject)
				continue;
			// if the array at i is a type of array write a [
			// This is used for nested arguments
			if (nextObject.getClass().isArray()) {
				stream.write('[');
				// fill the [] with the SuperCollider types corresponding to the object
				// (e.g., Object of type String needs -s).
				writeTypesArray((Object[]) nextObject);
				// close the array
				stream.write(']');
				continue;
			}
			// Create a way to deal with Boolean type objects
			if (Boolean.TRUE.equals(nextObject)) {
				stream.write('T');
				continue;
			}
			if (Boolean.FALSE.equals(nextObject)) {
				stream.write('F');
				continue;
			}
			// go through the array and write the superCollider types as shown in the 
			// above method. the Classes derived here are used as the arg to the above method
			writeType(nextObject.getClass());
		}
		// align the stream with padded bytes
		appendNullCharToAlignStream();
	}

	/**
	 * convert an integer to byte array
	 *
	 * @param value int
	 */
	private void writeIntegerToByteArray(int value) {
		byte[] intBytes = new byte[4];

		intBytes[3] = (byte)value; value>>>=8;
		intBytes[2] = (byte)value; value>>>=8;
		intBytes[1] = (byte)value; value>>>=8;
		intBytes[0] = (byte)value;

		try {
			stream.write(intBytes);
		} catch (IOException e) {
			throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream");
		}
	}
	
	/**
	 * Line up the BigEnd of the bytes to a 4 byte boundry
	 *
	 * @param bytes byte[]
	 */
	private void writeBigEndToFourByteBoundry(byte[] bytes) {
		int mod = bytes.length % 4;
		// if the remainder == 0 write the bytes
		if (mod == 0) {
			try { stream.write(bytes); } catch (IOException e)
			{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
			return;
		}
		// pad the bytes to lineup correctly
		int pad = 4 - mod;
		byte[] newBytes = new byte[pad + bytes.length];
		System.arraycopy(bytes,0,newBytes,pad,bytes.length);

		try { stream.write(newBytes); } catch (IOException e)
		{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
	}

	/**
	 * Line up the LittleEnd of the bytes to a 4 byte boundry
	 * 
	 * @param bytes byte[]
	 */
	private void writeLittleEndToFourByteBoundry(byte[] bytes) {
		int mod = bytes.length % 4;
		// if the remainder == 0 write the bytes
		if (mod == 4) {
			try { stream.write(bytes); } catch (IOException e)
			{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
			return;
		}
		// pad the bytes to lineup correctly
		int pad = 4 - mod;
		byte[] newBytes = new byte[pad + bytes.length];
		System.arraycopy(bytes,0,newBytes,0,bytes.length);

		try { stream.write(newBytes); } catch (IOException e)
		{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy