front_processing/extern/TUIO_JAVA/src/com/illposed/osc/utility/OSCJavaToByteArrayConverter.java
changeset 0 6fefd4afe506
child 9 0f44b7360c8d
equal deleted inserted replaced
-1:000000000000 0:6fefd4afe506
       
     1 /**
       
     2  * @author cramakrishnan
       
     3  *
       
     4  * Copyright (C) 2003, C. Ramakrishnan / Illposed Software
       
     5  * All rights reserved.
       
     6  * 
       
     7  * See license.txt (or license.rtf) for license information.
       
     8  * 
       
     9  * 
       
    10  * OSCJavaToByteArrayConverter is a helper class that translates
       
    11  * from Java types to the format the OSC spec specifies for those
       
    12  * types.
       
    13  *
       
    14  * This implementation is based on Markus Gaelli and
       
    15  * Iannis Zannos' OSC implementation in Squeak:
       
    16  * http://www.emergent.de/Goodies/
       
    17  */
       
    18 
       
    19 package com.illposed.osc.utility;
       
    20 
       
    21 import java.io.IOException;
       
    22 import java.io.ByteArrayOutputStream;
       
    23 import java.math.BigInteger;
       
    24 import java.util.Enumeration;
       
    25 import java.util.Vector;
       
    26 
       
    27 
       
    28 public class OSCJavaToByteArrayConverter {
       
    29 
       
    30 	protected ByteArrayOutputStream stream = new ByteArrayOutputStream();
       
    31 	private byte[] intBytes = new byte[4];
       
    32 
       
    33 	/*public OSCJavaToByteArrayConverter() {
       
    34 		super();
       
    35 	}*/
       
    36 
       
    37 	/**
       
    38 	 * Creation date: (2/23/2001 2:43:25 AM)
       
    39 	 * @param anArray java.lang.Object[]
       
    40 	 *
       
    41 	 */
       
    42 	public void appendNullCharToAlignStream() {
       
    43 		int mod = stream.size() % 4;
       
    44 		int pad = 4 - mod;
       
    45 		for (int i = 0; i < pad; i++)
       
    46 			stream.write(0);
       
    47 	}
       
    48 
       
    49 	/**
       
    50 	 * Creation date: (2/23/2001 2:21:53 AM)
       
    51 	 * @return byte[]
       
    52 	 */
       
    53 	public byte[] toByteArray() {
       
    54 		return stream.toByteArray();
       
    55 	}
       
    56 
       
    57 	/**
       
    58 	 * Creation date: (2/23/2001 2:14:23 AM)
       
    59 	 * @param bytes byte[]
       
    60 	 */
       
    61 	public void write(byte[] bytes) {
       
    62 		writeBigEndToFourByteBoundry(bytes);
       
    63 	}
       
    64 
       
    65 	/**
       
    66 	 * Creation date: (2/23/2001 2:21:04 AM)
       
    67 	 * @param i int
       
    68 	 */
       
    69 	public void write(int i) {
       
    70 		writeIntegerToByteArray(i);
       
    71 	}
       
    72 
       
    73 	/**
       
    74 	 * Creation date: (2/23/2001 2:03:57 AM)
       
    75 	 * @param f java.lang.Float
       
    76 	 */
       
    77 	public void write(Float f) {
       
    78 		writeIntegerToByteArray(Float.floatToIntBits(f.floatValue()));
       
    79 	}
       
    80 
       
    81 	/**
       
    82 	 * Creation date: (2/23/2001 2:08:36 AM)
       
    83 	 * @param i java.lang.Integer
       
    84 	 */
       
    85 	public void write(Integer i) {
       
    86 		writeIntegerToByteArray(i.intValue());
       
    87 	}
       
    88 
       
    89 	/**
       
    90 	 * Creation date: (2/23/2001 1:57:35 AM)
       
    91 	 * @param str java.lang.String
       
    92 	 */
       
    93 	public void write(String str) {
       
    94 		writeLittleEndToFourByteBoundry(str.getBytes());
       
    95 	}
       
    96 
       
    97 	/**
       
    98 	 * Creation date: (2/23/2001 2:08:36 AM)
       
    99 	 * @param c char
       
   100 	 */
       
   101 	public void write(char c) {
       
   102 		stream.write(c);
       
   103 	}
       
   104 
       
   105 	/**
       
   106 	 * Creation date: (2/23/2001 2:02:54 AM)
       
   107 	 * @param anObject java.lang.Object
       
   108 	 */
       
   109 	public void write(Object anObject) {
       
   110 		// Can't do switch on class
       
   111 		if (null == anObject)
       
   112 			return;
       
   113 		if (anObject instanceof Float) {
       
   114 			write((Float) anObject);
       
   115 			return;
       
   116 		}
       
   117 		if (anObject instanceof String) {
       
   118 			write((String) anObject);
       
   119 			return;
       
   120 		}
       
   121 		if (anObject instanceof Integer) {
       
   122 			write((Integer) anObject);
       
   123 			return;
       
   124 		}
       
   125 	}
       
   126 
       
   127 	/**
       
   128 	 * Creation date: (2/23/2001 2:43:25 AM)
       
   129 	 * @param aClass Class
       
   130 	 */
       
   131 	public void writeType(Class c) {
       
   132 		// A big ol' case statement -- what's polymorphism mean, again?
       
   133 		// I really wish I could extend the base classes!
       
   134 
       
   135 		// use the appropriate flags to tell SuperCollider what kind of 
       
   136 		// thing it is looking at
       
   137 
       
   138 		if (Integer.class.equals(c)) {
       
   139 			stream.write('i');
       
   140 			return;
       
   141 		}
       
   142 		if (java.math.BigInteger.class.equals(c)) {
       
   143 			stream.write('h');
       
   144 			return;
       
   145 		}
       
   146 		if (Float.class.equals(c)) {
       
   147 			stream.write('f');
       
   148 			return;
       
   149 		}
       
   150 		if (Double.class.equals(c)) {
       
   151 			stream.write('d');
       
   152 			return;
       
   153 		}
       
   154 		if (String.class.equals(c)) {
       
   155 			stream.write('s');
       
   156 			return;
       
   157 		}
       
   158 		if (Character.class.equals(c)) {
       
   159 			stream.write('c');
       
   160 			return;
       
   161 		}
       
   162 	}
       
   163 
       
   164 	/**
       
   165 	 * Creation date: (2/23/2001 2:43:25 AM)
       
   166 	 * @param anArray java.lang.Object[]
       
   167 	 */
       
   168 	public void writeTypesArray(Object[] array) {
       
   169 		// A big ol' case statement in a for loop -- what's polymorphism mean, again?
       
   170 		// I really wish I could extend the base classes!
       
   171 
       
   172 		for (int i = 0; i < array.length; i++) {
       
   173 			if (null == array[i])
       
   174 				continue;
       
   175 			// if the array at i is a type of array write a [
       
   176 			// This is used for nested arguments
       
   177 			if (array[i].getClass().isArray()) {
       
   178 				stream.write('[');
       
   179 				// fill the [] with the SuperCollider types corresponding to the object
       
   180 				// (i.e. Object of type String needs -s).
       
   181 				writeTypesArray((Object[]) array[i]);
       
   182 				// close the array
       
   183 				stream.write(']');
       
   184 				continue;
       
   185 			}
       
   186 			// Create a way to deal with Boolean type objects
       
   187 			if (Boolean.TRUE.equals(array[i])) {
       
   188 				stream.write('T');
       
   189 				continue;
       
   190 			}
       
   191 			if (Boolean.FALSE.equals(array[i])) {
       
   192 				stream.write('F');
       
   193 				continue;
       
   194 			}
       
   195 			// go through the array and write the superCollider types as shown in the 
       
   196 			// above method. the Classes derived here are used as the arg to the above method
       
   197 			writeType(array[i].getClass());
       
   198 		}
       
   199 		// align the stream with padded bytes
       
   200 		appendNullCharToAlignStream();
       
   201 	}
       
   202 	
       
   203 	/**
       
   204 	 * Same as writeSuperColliderTypes(Object[]), just that it takes a vector (for jdk1.1
       
   205 	 * compatibility), rather than an array.
       
   206 	 * @param vector  the collection I am to write out types for
       
   207 	 */
       
   208 	public void writeTypes(Vector vector) {
       
   209 		// A big ol' case statement in a for loop -- what's polymorphism mean, again?
       
   210 		// I really wish I could extend the base classes!
       
   211 
       
   212 		Enumeration enm = vector.elements();
       
   213 		Object nextObject;
       
   214 		while (enm.hasMoreElements()) {
       
   215 			nextObject = enm.nextElement();
       
   216 			if (null == nextObject)
       
   217 				continue;
       
   218 			// if the array at i is a type of array write a [
       
   219 			// This is used for nested arguments
       
   220 			if (nextObject.getClass().isArray()) {
       
   221 				stream.write('[');
       
   222 				// fill the [] with the SuperCollider types corresponding to the object
       
   223 				// (e.g., Object of type String needs -s).
       
   224 				writeTypesArray((Object[]) nextObject);
       
   225 				// close the array
       
   226 				stream.write(']');
       
   227 				continue;
       
   228 			}
       
   229 			// Create a way to deal with Boolean type objects
       
   230 			if (Boolean.TRUE.equals(nextObject)) {
       
   231 				stream.write('T');
       
   232 				continue;
       
   233 			}
       
   234 			if (Boolean.FALSE.equals(nextObject)) {
       
   235 				stream.write('F');
       
   236 				continue;
       
   237 			}
       
   238 			// go through the array and write the superCollider types as shown in the 
       
   239 			// above method. the Classes derived here are used as the arg to the above method
       
   240 			writeType(nextObject.getClass());
       
   241 		}
       
   242 		// align the stream with padded bytes
       
   243 		appendNullCharToAlignStream();
       
   244 	}
       
   245 
       
   246 	/**
       
   247 	 * convert an integer to byte array
       
   248 	 *
       
   249 	 * @param value int
       
   250 	 */
       
   251 	private void writeIntegerToByteArray(int value) {
       
   252 		byte[] intBytes = new byte[4];
       
   253 
       
   254 		intBytes[3] = (byte)value; value>>>=8;
       
   255 		intBytes[2] = (byte)value; value>>>=8;
       
   256 		intBytes[1] = (byte)value; value>>>=8;
       
   257 		intBytes[0] = (byte)value;
       
   258 
       
   259 		try {
       
   260 			stream.write(intBytes);
       
   261 		} catch (IOException e) {
       
   262 			throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream");
       
   263 		}
       
   264 	}
       
   265 	
       
   266 	/**
       
   267 	 * Line up the BigEnd of the bytes to a 4 byte boundry
       
   268 	 *
       
   269 	 * @param bytes byte[]
       
   270 	 */
       
   271 	private void writeBigEndToFourByteBoundry(byte[] bytes) {
       
   272 		int mod = bytes.length % 4;
       
   273 		// if the remainder == 0 write the bytes
       
   274 		if (mod == 0) {
       
   275 			try { stream.write(bytes); } catch (IOException e)
       
   276 			{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
       
   277 			return;
       
   278 		}
       
   279 		// pad the bytes to lineup correctly
       
   280 		int pad = 4 - mod;
       
   281 		byte[] newBytes = new byte[pad + bytes.length];
       
   282 		System.arraycopy(bytes,0,newBytes,pad,bytes.length);
       
   283 
       
   284 		try { stream.write(newBytes); } catch (IOException e)
       
   285 		{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
       
   286 	}
       
   287 
       
   288 	/**
       
   289 	 * Line up the LittleEnd of the bytes to a 4 byte boundry
       
   290 	 * 
       
   291 	 * @param bytes byte[]
       
   292 	 */
       
   293 	private void writeLittleEndToFourByteBoundry(byte[] bytes) {
       
   294 		int mod = bytes.length % 4;
       
   295 		// if the remainder == 0 write the bytes
       
   296 		if (mod == 4) {
       
   297 			try { stream.write(bytes); } catch (IOException e)
       
   298 			{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
       
   299 			return;
       
   300 		}
       
   301 		// pad the bytes to lineup correctly
       
   302 		int pad = 4 - mod;
       
   303 		byte[] newBytes = new byte[pad + bytes.length];
       
   304 		System.arraycopy(bytes,0,newBytes,0,bytes.length);
       
   305 
       
   306 		try { stream.write(newBytes); } catch (IOException e)
       
   307 		{ throw new RuntimeException("You're screwed: IOException writing to a ByteArrayOutputStream"); }
       
   308 	}
       
   309 
       
   310 }