front_processing/extern/TUIO_JAVA/src/com/illposed/osc/utility/OSCByteArrayToJavaConverter.java
changeset 0 6fefd4afe506
child 9 0f44b7360c8d
equal deleted inserted replaced
-1:000000000000 0:6fefd4afe506
       
     1 /* $Id: OSCByteArrayToJavaConverter.java,v 1.1.1.1 2006/11/13 14:47:22 modin Exp $
       
     2  * Created on 28.10.2003
       
     3  */
       
     4 package com.illposed.osc.utility;
       
     5 
       
     6 import java.math.BigInteger;
       
     7 import java.util.Date;
       
     8 
       
     9 import com.illposed.osc.*;
       
    10 
       
    11 /**
       
    12  * @author cramakrishnan
       
    13  *
       
    14  * Copyright (C) 2003, C. Ramakrishnan / Auracle
       
    15  * All rights reserved.
       
    16  * 
       
    17  * See license.txt (or license.rtf) for license information.
       
    18  */
       
    19 public class OSCByteArrayToJavaConverter {
       
    20 
       
    21 	byte[] bytes;
       
    22 	int bytesLength;
       
    23 	int streamPosition;
       
    24 
       
    25 	private byte[] intBytes   = new byte[4];
       
    26 	private byte[] floatBytes = new byte[4];
       
    27 
       
    28 	private	byte[] secondBytes = new byte[8];
       
    29 	private	byte[] picosecBytes = new byte[8];
       
    30 
       
    31 	/**
       
    32 	 * Helper object for converting from a byte array to Java objects
       
    33 	 */
       
    34 	/*public OSCByteArrayToJavaConverter() {
       
    35 		super();
       
    36 	}*/
       
    37 
       
    38 	public OSCPacket convert(byte[] byteArray, int bytesLength) {
       
    39 		bytes = byteArray;
       
    40 		this.bytesLength = bytesLength;
       
    41 		streamPosition = 0;
       
    42 		if (isBundle())
       
    43 			return convertBundle();
       
    44 		else
       
    45 			return convertMessage();
       
    46 	}
       
    47 
       
    48 	private boolean isBundle() {
       
    49 		// only need the first 7 to check if it is a bundle
       
    50 		String bytesAsString = new String(bytes, 0, 7);
       
    51 		return bytesAsString.startsWith("#bundle");
       
    52 	}                               
       
    53                                
       
    54 	private OSCBundle convertBundle() {
       
    55 		// skip the "#bundle " stuff
       
    56 		streamPosition = 8;
       
    57 		Date timestamp = readTimeTag();
       
    58 		OSCBundle bundle = new OSCBundle(timestamp);
       
    59 		OSCByteArrayToJavaConverter myConverter = new OSCByteArrayToJavaConverter();
       
    60 		while (streamPosition < bytesLength) {
       
    61 			// recursively read through the stream and convert packets you find
       
    62 			int packetLength = ((Integer) readInteger()).intValue();
       
    63 			byte[] packetBytes = new byte[packetLength];
       
    64 			//streamPosition++;
       
    65 			System.arraycopy(bytes,streamPosition,packetBytes,0,packetLength);
       
    66 			streamPosition+=packetLength;
       
    67 			//for (int i = 0; i < packetLength; i++)
       
    68 			//	packetBytes[i] = bytes[streamPosition++];
       
    69 			OSCPacket packet = myConverter.convert(packetBytes, packetLength);
       
    70 			bundle.addPacket(packet);
       
    71 		}
       
    72 		return bundle;
       
    73 	}
       
    74 
       
    75 	private OSCMessage convertMessage() {
       
    76 		OSCMessage message = new OSCMessage();
       
    77 		message.setAddress(readString());
       
    78 		char[] types = readTypes();
       
    79 		if (null == types) {
       
    80 			// we are done
       
    81 			return message;
       
    82 		}
       
    83 		moveToFourByteBoundry();
       
    84 		for (int i = 0; i < types.length; i++) {
       
    85 			if ('[' == types[i]) {
       
    86 				// we're looking at an array -- read it in
       
    87 				message.addArgument(readArray(types, i));
       
    88 				// then increment i to the end of the array
       
    89 				while (']' != types[i])
       
    90 					i++;
       
    91 			} else
       
    92 				message.addArgument(readArgument(types[i]));
       
    93 		}
       
    94 		return message;
       
    95 	}
       
    96 
       
    97 	private String readString() {
       
    98 		int strLen = lengthOfCurrentString();
       
    99 		char[] stringChars = new char[strLen];
       
   100 		//System.arraycopy(bytes,streamPosition,stringChars,0,strLen);
       
   101 		//streamPosition+=strLen;
       
   102 		for (int i = 0; i < strLen; i++)
       
   103 			stringChars[i] = (char) bytes[streamPosition++];
       
   104 		moveToFourByteBoundry();
       
   105 		return new String(stringChars);
       
   106 	}
       
   107 
       
   108 	/**
       
   109 	 * @return a char array with the types of the arguments
       
   110 	 */
       
   111 	private char[] readTypes() {
       
   112 		// the next byte should be a ","
       
   113 		if (bytes[streamPosition] != 0x2C)
       
   114 			return null;
       
   115 		streamPosition++;
       
   116 		// find out how long the list of types is
       
   117 		int typesLen = lengthOfCurrentString();
       
   118 		if (0 == typesLen) {
       
   119 			return null;
       
   120 		}
       
   121 		// read in the types
       
   122 		char[] typesChars = new char[typesLen];
       
   123 		for (int i = 0; i < typesLen; i++) {
       
   124 			typesChars[i] = (char) bytes[streamPosition++];
       
   125 		}
       
   126 		return typesChars;
       
   127 	}
       
   128 
       
   129 	/**
       
   130 	 * @param c type of argument
       
   131 	 * @return a Java representation of the argument
       
   132 	 */
       
   133 	private Object readArgument(char c) {
       
   134 		switch (c) {
       
   135 			case 'i' :
       
   136 				return readInteger();
       
   137 			case 'h' :
       
   138 				return readBigInteger();
       
   139 			case 'f' :
       
   140 				return readFloat();
       
   141 			case 'd' :
       
   142 				return readDouble();
       
   143 			case 's' :
       
   144 				return readString();
       
   145 			case 'c' :
       
   146 				return readChar();
       
   147 			case 'T' :
       
   148 				return Boolean.TRUE;
       
   149 			case 'F' :
       
   150 				return Boolean.FALSE;
       
   151 		}
       
   152 
       
   153 		return null;
       
   154 	}
       
   155 
       
   156 	/**
       
   157 	 * @return a Character
       
   158 	 */
       
   159 	private Object readChar() {
       
   160 		return new Character((char) bytes[streamPosition++]);
       
   161 	}
       
   162 
       
   163 	/**
       
   164 	 * @return a Double
       
   165 	 */
       
   166 	private Object readDouble() {
       
   167 		return readFloat();
       
   168 	}
       
   169 
       
   170 	/**
       
   171 	 * @return a Float
       
   172 	 */
       
   173 	private Object readFloat() {
       
   174 		//byte[] floatBytes = new byte[4];
       
   175 		floatBytes[0] = bytes[streamPosition++];
       
   176 		floatBytes[1] = bytes[streamPosition++];
       
   177 		floatBytes[2] = bytes[streamPosition++];
       
   178 		floatBytes[3] = bytes[streamPosition++];
       
   179 
       
   180 		int floatBits = 
       
   181 			((floatBytes[3] & 0xFF) ) +
       
   182 			((floatBytes[2] & 0xFF) << 8) +
       
   183 			((floatBytes[1] & 0xFF) << 16) +
       
   184 			((floatBytes[0] & 0xFF) << 24);
       
   185 		
       
   186 		return new Float(Float.intBitsToFloat(floatBits));
       
   187 	}
       
   188 
       
   189 	/**
       
   190 	 * @return a BigInteger
       
   191 	 */
       
   192 	private Object readBigInteger() {
       
   193 		//byte[] intBytes = new byte[4];
       
   194 		intBytes[0] = bytes[streamPosition++];
       
   195 		intBytes[1] = bytes[streamPosition++];
       
   196 		intBytes[2] = bytes[streamPosition++];
       
   197 		intBytes[3] = bytes[streamPosition++];
       
   198 
       
   199 		int intBits = 
       
   200 			((intBytes[3] & 0xFF) ) +
       
   201 			((intBytes[2] & 0xFF) << 8) +
       
   202 			((intBytes[1] & 0xFF) << 16) +
       
   203 			((intBytes[0] & 0xFF) << 24);
       
   204 		
       
   205 		return new Integer(intBits);
       
   206 	}
       
   207 
       
   208 	/**
       
   209 	 * @return an Integer
       
   210 	 */
       
   211 	private Object readInteger() {
       
   212 		//byte[] intBytes = new byte[4];
       
   213 		intBytes[0] = bytes[streamPosition++];
       
   214 		intBytes[1] = bytes[streamPosition++];
       
   215 		intBytes[2] = bytes[streamPosition++];
       
   216 		intBytes[3] = bytes[streamPosition++];
       
   217 
       
   218 		int intBits = 
       
   219 			((intBytes[3] & 0xFF) ) +
       
   220 			((intBytes[2] & 0xFF) << 8) +
       
   221 			((intBytes[1] & 0xFF) << 16) +
       
   222 			((intBytes[0] & 0xFF) << 24);
       
   223 		
       
   224 		return new Integer(intBits);
       
   225 	}
       
   226 	
       
   227 	/**
       
   228 	 * @return a Date
       
   229 	 */
       
   230 	private Date readTimeTag() {
       
   231 		//byte[] secondBytes = new byte[8];
       
   232 		//byte[] picosecBytes = new byte[8];
       
   233 		/*for (int i = 4; i < 8; i++)
       
   234 			secondBytes[i] = bytes[streamPosition++];
       
   235 		for (int i = 4; i < 8; i++)
       
   236 			picosecBytes[i] = bytes[streamPosition++];*/
       
   237 		System.arraycopy(bytes,streamPosition,secondBytes,4,4);
       
   238 		streamPosition+=4;
       
   239 		System.arraycopy(bytes,streamPosition,picosecBytes,4,4);
       
   240 		streamPosition+=4;
       
   241 		
       
   242 		BigInteger secsSince1900 = new BigInteger(secondBytes);
       
   243 		long secsSince1970 =  secsSince1900.longValue() - OSCBundle.SECONDS_FROM_1900_to_1970.longValue();
       
   244 		if (secsSince1970 < 0) secsSince1970 = 0; // no point maintaining times in the distant past
       
   245 		BigInteger picosecs = new BigInteger(picosecBytes);
       
   246 		long millisecs = (secsSince1970 * 1000) + (picosecs.longValue() / 1000);
       
   247 		return new Date(millisecs);
       
   248 	}
       
   249 
       
   250 	/**
       
   251 	 * @param types
       
   252 	 * @param i
       
   253 	 * @return an Array
       
   254 	 */
       
   255 	private Object[] readArray(char[] types, int i) {
       
   256 		int arrayLen = 0;
       
   257 		while (types[i + arrayLen] != ']')
       
   258 			arrayLen++;
       
   259 		Object[] array = new Object[arrayLen];
       
   260 		for (int j = 0; i < arrayLen; j++) {
       
   261 			array[j] = readArgument(types[i + j]);
       
   262 		}
       
   263 		return array;
       
   264 	}
       
   265 
       
   266 	private int lengthOfCurrentString() {
       
   267 		int i = 0;
       
   268 		while (bytes[streamPosition + i] != 0)
       
   269 			i++;
       
   270 		return i;
       
   271 	}
       
   272 
       
   273 	private void moveToFourByteBoundry() {
       
   274 		// If i'm already at a 4 byte boundry, I need to move to the next one
       
   275 		int mod = streamPosition % 4;
       
   276 		streamPosition += (4 - mod);
       
   277 	}
       
   278 
       
   279 }
       
   280