/**
* Copyright 2009 DFKI GmbH.
* All Rights Reserved. Use is subject to license terms.
*
* This file is part of MARY TTS.
*
* MARY TTS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package marytts.util.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
/**
* @author marc
*
*/
public class StreamUtils {
public static double[] readDoubleArray(DataInput stream, int len) throws IOException {
byte[] raw = new byte[len * Double.SIZE / 8];
stream.readFully(raw);
DataInputStream in = new DataInputStream(new ByteArrayInputStream(raw));
double[] data = new double[len];
for (int i = 0; i < len; i++) {
data[i] = in.readDouble();
}
return data;
}
public static void writeDoubleArray(DataOutput stream, double[] data) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos);
for (int i = 0; i < data.length; i++) {
out.writeDouble(data[i]);
}
out.close();
byte[] raw = baos.toByteArray();
assert raw.length == data.length * Double.SIZE / 8;
stream.write(raw);
}
/**
* Reads from the bytebuffer <code>bb</code> a representation of a Unicode character string encoded in <a
* href="DataInput.html#modified-utf-8">modified UTF-8</a> format; this string of characters is then returned as a
* <code>String</code>. The details of the modified UTF-8 representation are exactly the same as for the <code>readUTF</code>
* method of <code>DataInput</code>.
*
* @param bb
* a byte buffer.
* @return a Unicode string.
* @exception BufferUnderflowException
* if the input stream reaches the end before all the bytes.
* @exception UTFDataFormatException
* if the bytes do not represent a valid modified UTF-8 encoding of a Unicode string.
* @see java.io.DataInputStream#readUnsignedShort()
*/
public static String readUTF(ByteBuffer bb) throws BufferUnderflowException, UTFDataFormatException {
int utflen = readUnsignedShort(bb);
byte[] bytearr = new byte[utflen];
char[] chararr = new char[utflen];
int c, char2, char3;
int count = 0;
int chararr_count = 0;
bb.get(bytearr);
while (count < utflen) {
c = (int) bytearr[count] & 0xff;
if (c > 127)
break;
count++;
chararr[chararr_count++] = (char) c;
}
while (count < utflen) {
c = (int) bytearr[count] & 0xff;
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
/* 0xxxxxxx */
count++;
chararr[chararr_count++] = (char) c;
break;
case 12:
case 13:
/* 110x xxxx 10xx xxxx */
count += 2;
if (count > utflen)
throw new UTFDataFormatException("malformed input: partial character at end");
char2 = (int) bytearr[count - 1];
if ((char2 & 0xC0) != 0x80)
throw new UTFDataFormatException("malformed input around byte " + count);
chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
count += 3;
if (count > utflen)
throw new UTFDataFormatException("malformed input: partial character at end");
char2 = (int) bytearr[count - 2];
char3 = (int) bytearr[count - 1];
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
throw new UTFDataFormatException("malformed input around byte " + (count - 1));
chararr[chararr_count++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
break;
default:
/* 10xx xxxx, 1111 xxxx */
throw new UTFDataFormatException("malformed input around byte " + count);
}
}
// The number of chars produced may be less than utflen
return new String(chararr, 0, chararr_count);
}
/**
* See the general contract of the <code>readUnsignedShort</code> method of <code>DataInput</code>.
* <p>
* Bytes for this operation are read from the given byte buffer
*
* @param bb
* bb
* @return the next two bytes of this input stream, interpreted as an unsigned 16-bit integer.
* @exception BufferUnderflowException
* if this input stream reaches the end before reading two bytes.
* @see java.io.FilterInputStream#in
*/
public static int readUnsignedShort(ByteBuffer bb) throws BufferUnderflowException {
int ch1 = bb.get() & 0xFF; // convert byte to unsigned byte
int ch2 = bb.get() & 0xFF; // convert byte to unsigned byte
return (ch1 << 8) + (ch2 << 0);
}
}