/*
* The University of Wales, Cardiff Triana Project Software License (Based
* on the Apache Software License Version 1.1)
*
* Copyright (c) 2003 University of Wales, Cardiff. All rights reserved.
*
* Redistribution and use of the software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The end-user documentation included with the redistribution, if any,
* must include the following acknowledgment: "This product includes
* software developed by the University of Wales, Cardiff for the Triana
* Project (http://www.trianacode.org)." Alternately, this
* acknowledgment may appear in the software itself, if and wherever
* such third-party acknowledgments normally appear.
*
* 4. The names "Triana" and "University of Wales, Cardiff" must not be
* used to endorse or promote products derived from this software
* without prior written permission. For written permission, please
* contact triana@trianacode.org.
*
* 5. Products derived from this software may not be called "Triana," nor
* may Triana appear in their name, without prior written permission of
* the University of Wales, Cardiff.
*
* 6. This software may not be sold, used or incorporated into any product
* for sale to third parties.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 UNIVERSITY OF WALES, CARDIFF OR ITS 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.
*
* ------------------------------------------------------------------------
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Triana Project. For more information on the
* Triana Project, please see. http://www.trianacode.org.
*
* This license is based on the BSD license as adopted by the Apache
* Foundation and is governed by the laws of England and Wales.
*/
package signalproc.output;
import java.io.IOException;
import java.io.OutputStream;
import org.trianacode.taskgraph.Task;
/**
* Exports data in row/column format to an Binary file
*
* @author Ian Wang
* @version $Revision: 2921 $
*/
public class BinaryExporter extends Export {
public static final String DOUBLE = "Double (8bytes)";
public static final String FLOAT = "Float (4bytes)";
public static final String LONG = "Long (8bytes)";
public static final String INT = "Int (4bytes)";
public static final String SHORT = "Short (2bytes)";
public static final String BYTE = "Byte (1byte)";
private static final int SHORT_BYTES = 2;
private static final int INT_BYTES = 4;
private static final int LONG_BYTES = 8;
private static final int FLOAT_BYTES = 4;
private static final int DOUBLE_BYTES = 8;
private OutputStream outstream;
/**
* the type of data
*/
private String datatype;
/**
* a flag indicating whether byte order is reversed
*/
private boolean reversebytes;
/**
* This function is called when the unit is first created. It should be over-ridden to initialise the tool
* properties (e.g. default number of nodes) and tool parameters.
*/
public void init() {
super.init();
Task task = getTask();
if (!task.isParameterName("reversebytes")) {
task.setParameter("reversebytes", "false");
}
if (!task.isParameterName("datatype")) {
task.setParameter("datatype", DOUBLE);
}
// Initialise GUI builder interface
String guilines = "";
guilines += "File Name $title filename File null *.*\n";
guilines += "Data Type $title datatype Choice [" + DOUBLE + "] [" + FLOAT + "] [" + LONG + "] [" + INT + "] ["
+ SHORT + "] [" + BYTE + "]\n";
guilines += "Export $title export Choice [Columns] [Rows]\n";
guilines += "Number of Columns/Rows $title colrownum TextField 1\n";
guilines += "Reverse byte order $title reversebytes Checkbox false\n";
guilines += "Input from multiple nodes $title multi Checkbox true\n";
guilines += "Append sequence number (file1, file2...) $title seqnum Checkbox false\n";
setGUIBuilderV2Info(guilines);
}
/**
* Called when the unit is reset. Restores the unit's variables to values specified by the parameters.
*/
public void reset() {
super.reset();
datatype = (String) getTask().getParameter("datatype");
reversebytes = new Boolean((String) getTask().getParameter("reversebytes")).booleanValue();
}
/**
* Opens a output stream to wrap the specified output stream
*
* @return the opened output stream
*/
protected boolean openOutputStream(OutputStream outstream) {
this.outstream = outstream;
return true;
}
/**
* Closes and disposes the output stream
*/
protected void closeOutputStream() throws IOException {
outstream.close();
outstream = null;
}
/**
* Write a row to the output stream
*/
protected void writeRow(double[] data) throws IOException {
byte[] bytes;
for (int ccount = 0; ccount < data.length; ccount++) {
bytes = toByteArray(data[ccount]);
for (int bcount = 0; bcount < bytes.length; bcount++) {
outstream.write(bytes[bcount]);
}
}
}
private byte[] toByteArray(double val) {
if (datatype.equals(FLOAT)) {
val = Math.max(Math.min(Float.MAX_VALUE, val), Float.MIN_VALUE);
return toByteArray(Float.floatToIntBits((float) val), FLOAT_BYTES, reversebytes);
} else if (datatype.equals(LONG)) {
val = Math.max(Math.min(Long.MAX_VALUE, val), Long.MIN_VALUE);
return toByteArray((long) val, LONG_BYTES, reversebytes);
} else if (datatype.equals(INT)) {
val = Math.max(Math.min(Integer.MAX_VALUE, val), Integer.MIN_VALUE);
return toByteArray((int) val, INT_BYTES, reversebytes);
} else if (datatype.equals(SHORT)) {
val = Math.max(Math.min(Short.MAX_VALUE, val), Short.MIN_VALUE);
return toByteArray((short) val, SHORT_BYTES, reversebytes);
} else if (datatype.equals(BYTE)) {
val = Math.max(Math.min(Byte.MAX_VALUE, val), Byte.MIN_VALUE);
return toByteArray((byte) val, 1, reversebytes);
} else {
return toByteArray(Double.doubleToLongBits(val), DOUBLE_BYTES, reversebytes);
}
}
private byte[] toByteArray(long val, int bytecount, boolean reverse) {
byte[] bytes = new byte[bytecount];
for (int count = 0; count < bytecount; ++count) {
if (reverse) {
bytes[count] = (byte) (val & 0xFFL);
} else {
bytes[bytecount - count - 1] = (byte) (val & 0xFFL);
}
val = val >> 8;
}
return bytes;
}
/**
* Called a parameters is updated (e.g. by the GUI)
*/
public void parameterUpdate(String paramname, Object value) {
super.parameterUpdate(paramname, value);
if (paramname.equals("datatype")) {
datatype = (String) value;
}
if (paramname.equals("reversebytes")) {
reversebytes = new Boolean((String) value).booleanValue();
}
}
}