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

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

The newest version!
/* $Id: OSCByteArrayToJavaConverter.java,v 1.1.1.1 2006/11/13 14:47:22 modin Exp $
 * Created on 28.10.2003
 */
package com.illposed.osc.utility;

import java.math.BigInteger;
import java.util.Date;

import com.illposed.osc.*;

/**
 * @author cramakrishnan
 *
 * Copyright (C) 2003, C. Ramakrishnan / Auracle
 * All rights reserved.
 * 
 * See license.txt (or license.rtf) for license information.
 */
public class OSCByteArrayToJavaConverter {

	byte[] bytes;
	int bytesLength;
	int streamPosition;

	private byte[] intBytes   = new byte[4];
	private byte[] floatBytes = new byte[4];

	private	byte[] secondBytes = new byte[8];
	private	byte[] picosecBytes = new byte[8];

	/**
	 * Helper object for converting from a byte array to Java objects
	 */
	/*public OSCByteArrayToJavaConverter() {
		super();
	}*/

	public OSCPacket convert(byte[] byteArray, int bytesLength) {
		bytes = byteArray;
		this.bytesLength = bytesLength;
		streamPosition = 0;
		if (isBundle())
			return convertBundle();
		else
			return convertMessage();
	}

	private boolean isBundle() {
		// only need the first 7 to check if it is a bundle
		String bytesAsString = new String(bytes, 0, 7);
		return bytesAsString.startsWith("#bundle");
	}                               
                               
	private OSCBundle convertBundle() {
		// skip the "#bundle " stuff
		streamPosition = 8;
		Date timestamp = readTimeTag();
		OSCBundle bundle = new OSCBundle(timestamp);
		OSCByteArrayToJavaConverter myConverter = new OSCByteArrayToJavaConverter();
		while (streamPosition < bytesLength) {
			// recursively read through the stream and convert packets you find
			int packetLength = ((Integer) readInteger()).intValue();
			byte[] packetBytes = new byte[packetLength];
			//streamPosition++;
			System.arraycopy(bytes,streamPosition,packetBytes,0,packetLength);
			streamPosition+=packetLength;
			//for (int i = 0; i < packetLength; i++)
			//	packetBytes[i] = bytes[streamPosition++];
			OSCPacket packet = myConverter.convert(packetBytes, packetLength);
			bundle.addPacket(packet);
		}
		return bundle;
	}

	private OSCMessage convertMessage() {
		OSCMessage message = new OSCMessage();
		message.setAddress(readString());
		char[] types = readTypes();
		if (null == types) {
			// we are done
			return message;
		}
		moveToFourByteBoundry();
		for (int i = 0; i < types.length; i++) {
			if ('[' == types[i]) {
				// we're looking at an array -- read it in
				message.addArgument(readArray(types, i));
				// then increment i to the end of the array
				while (']' != types[i])
					i++;
			} else
				message.addArgument(readArgument(types[i]));
		}
		return message;
	}

	private String readString() {
		int strLen = lengthOfCurrentString();
		char[] stringChars = new char[strLen];
		//System.arraycopy(bytes,streamPosition,stringChars,0,strLen);
		//streamPosition+=strLen;
		for (int i = 0; i < strLen; i++)
			stringChars[i] = (char) bytes[streamPosition++];
		moveToFourByteBoundry();
		return new String(stringChars);
	}

	/**
	 * @return a char array with the types of the arguments
	 */
	private char[] readTypes() {
		// the next byte should be a ","
		if (bytes[streamPosition] != 0x2C)
			return null;
		streamPosition++;
		// find out how long the list of types is
		int typesLen = lengthOfCurrentString();
		if (0 == typesLen) {
			return null;
		}
		// read in the types
		char[] typesChars = new char[typesLen];
		for (int i = 0; i < typesLen; i++) {
			typesChars[i] = (char) bytes[streamPosition++];
		}
		return typesChars;
	}

	/**
	 * @param c type of argument
	 * @return a Java representation of the argument
	 */
	private Object readArgument(char c) {
		switch (c) {
			case 'i' :
				return readInteger();
			case 'h' :
				return readBigInteger();
			case 'f' :
				return readFloat();
			case 'd' :
				return readDouble();
			case 's' :
				return readString();
			case 'c' :
				return readChar();
			case 'T' :
				return Boolean.TRUE;
			case 'F' :
				return Boolean.FALSE;
		}

		return null;
	}

	/**
	 * @return a Character
	 */
	private Object readChar() {
		return new Character((char) bytes[streamPosition++]);
	}

	/**
	 * @return a Double
	 */
	private Object readDouble() {
		return readFloat();
	}

	/**
	 * @return a Float
	 */
	private Object readFloat() {
		//byte[] floatBytes = new byte[4];
		floatBytes[0] = bytes[streamPosition++];
		floatBytes[1] = bytes[streamPosition++];
		floatBytes[2] = bytes[streamPosition++];
		floatBytes[3] = bytes[streamPosition++];

		int floatBits = 
			((floatBytes[3] & 0xFF) ) +
			((floatBytes[2] & 0xFF) << 8) +
			((floatBytes[1] & 0xFF) << 16) +
			((floatBytes[0] & 0xFF) << 24);
		
		return new Float(Float.intBitsToFloat(floatBits));
	}

	/**
	 * @return a BigInteger
	 */
	private Object readBigInteger() {
		//byte[] intBytes = new byte[4];
		intBytes[0] = bytes[streamPosition++];
		intBytes[1] = bytes[streamPosition++];
		intBytes[2] = bytes[streamPosition++];
		intBytes[3] = bytes[streamPosition++];

		int intBits = 
			((intBytes[3] & 0xFF) ) +
			((intBytes[2] & 0xFF) << 8) +
			((intBytes[1] & 0xFF) << 16) +
			((intBytes[0] & 0xFF) << 24);
		
		return new Integer(intBits);
	}

	/**
	 * @return an Integer
	 */
	private Object readInteger() {
		//byte[] intBytes = new byte[4];
		intBytes[0] = bytes[streamPosition++];
		intBytes[1] = bytes[streamPosition++];
		intBytes[2] = bytes[streamPosition++];
		intBytes[3] = bytes[streamPosition++];

		int intBits = 
			((intBytes[3] & 0xFF) ) +
			((intBytes[2] & 0xFF) << 8) +
			((intBytes[1] & 0xFF) << 16) +
			((intBytes[0] & 0xFF) << 24);
		
		return new Integer(intBits);
	}
	
	/**
	 * @return a Date
	 */
	private Date readTimeTag() {
		//byte[] secondBytes = new byte[8];
		//byte[] picosecBytes = new byte[8];
		/*for (int i = 4; i < 8; i++)
			secondBytes[i] = bytes[streamPosition++];
		for (int i = 4; i < 8; i++)
			picosecBytes[i] = bytes[streamPosition++];*/
		System.arraycopy(bytes,streamPosition,secondBytes,4,4);
		streamPosition+=4;
		System.arraycopy(bytes,streamPosition,picosecBytes,4,4);
		streamPosition+=4;
		
		BigInteger secsSince1900 = new BigInteger(secondBytes);
		long secsSince1970 =  secsSince1900.longValue() - OSCBundle.SECONDS_FROM_1900_to_1970.longValue();
		if (secsSince1970 < 0) secsSince1970 = 0; // no point maintaining times in the distant past
		BigInteger picosecs = new BigInteger(picosecBytes);
		long millisecs = (secsSince1970 * 1000) + (picosecs.longValue() / 1000);
		return new Date(millisecs);
	}

	/**
	 * @param types
	 * @param i
	 * @return an Array
	 */
	private Object[] readArray(char[] types, int i) {
		int arrayLen = 0;
		while (types[i + arrayLen] != ']')
			arrayLen++;
		Object[] array = new Object[arrayLen];
		for (int j = 0; i < arrayLen; j++) {
			array[j] = readArgument(types[i + j]);
		}
		return array;
	}

	private int lengthOfCurrentString() {
		int i = 0;
		while (bytes[streamPosition + i] != 0)
			i++;
		return i;
	}

	private void moveToFourByteBoundry() {
		// If i'm already at a 4 byte boundry, I need to move to the next one
		int mod = streamPosition % 4;
		streamPosition += (4 - mod);
	}

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy