Better bounds checking in RecordInputStream. Removed rarely used methods readShortArray and putShortArray

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@701747 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-10-05 04:43:48 +00:00
parent 4bf266b1c7
commit 9897317e8e
4 changed files with 174 additions and 217 deletions

View File

@ -45,26 +45,26 @@ public class RecordInputStream extends InputStream {
private boolean autoContinue = true;
public RecordInputStream(InputStream in) throws RecordFormatException {
public RecordInputStream(InputStream in) throws RecordFormatException {
this.in = in;
try {
nextSid = LittleEndian.readShort(in);
//Dont increment the pos just yet (technically we are at the start of
//Don't increment the pos just yet (technically we are at the start of
//the record stream until nextRecord is called).
} catch (IOException ex) {
throw new RecordFormatException("Error reading bytes", ex);
}
}
/** This method will read a byte from the current record*/
public int read() {
checkRecordPosition();
/** This method will read a byte from the current record*/
public int read() {
checkRecordPosition(LittleEndian.BYTE_SIZE);
byte result = data[recordOffset];
recordOffset += 1;
pos += 1;
return result;
}
byte result = data[recordOffset];
recordOffset += LittleEndian.BYTE_SIZE;
pos += LittleEndian.BYTE_SIZE;
return result;
}
public short getSid() {
return currentSid;
@ -90,7 +90,6 @@ public class RecordInputStream extends InputStream {
*
* <i>Note: The auto continue flag is reset to true</i>
*/
public void nextRecord() throws RecordFormatException {
if ((currentLength != -1) && (currentLength != recordOffset)) {
System.out.println("WARN. Unread "+remaining()+" bytes of record 0x"+Integer.toHexString(currentSid));
@ -134,104 +133,90 @@ public class RecordInputStream extends InputStream {
return autoContinue;
}
protected void checkRecordPosition() {
if (remaining() <= 0) {
if (isContinueNext() && autoContinue) {
nextRecord();
}
else throw new ArrayIndexOutOfBoundsException();
}
}
private void checkRecordPosition(int requiredByteCount) {
/**
* Reads an 8 bit, signed value
*/
public byte readByte() {
checkRecordPosition();
if (remaining() < requiredByteCount) {
if (isContinueNext() && autoContinue) {
nextRecord();
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
}
byte result = data[recordOffset];
recordOffset += 1;
pos += 1;
return result;
}
/**
* Reads an 8 bit, signed value
*/
public byte readByte() {
checkRecordPosition(LittleEndian.BYTE_SIZE);
/**
* Reads a 16 bit, signed value
*/
public short readShort() {
checkRecordPosition();
byte result = data[recordOffset];
recordOffset += LittleEndian.BYTE_SIZE;
pos += LittleEndian.BYTE_SIZE;
return result;
}
short result = LittleEndian.getShort(data, recordOffset);
recordOffset += LittleEndian.SHORT_SIZE;
pos += LittleEndian.SHORT_SIZE;
return result;
}
/**
* Reads a 16 bit, signed value
*/
public short readShort() {
checkRecordPosition(LittleEndian.SHORT_SIZE);
public int readInt() {
checkRecordPosition();
short result = LittleEndian.getShort(data, recordOffset);
recordOffset += LittleEndian.SHORT_SIZE;
pos += LittleEndian.SHORT_SIZE;
return result;
}
int result = LittleEndian.getInt(data, recordOffset);
recordOffset += LittleEndian.INT_SIZE;
pos += LittleEndian.INT_SIZE;
return result;
}
public int readInt() {
checkRecordPosition(LittleEndian.INT_SIZE);
public long readLong() {
checkRecordPosition();
int result = LittleEndian.getInt(data, recordOffset);
recordOffset += LittleEndian.INT_SIZE;
pos += LittleEndian.INT_SIZE;
return result;
}
long result = LittleEndian.getLong(data, recordOffset);
recordOffset += LittleEndian.LONG_SIZE;
pos += LittleEndian.LONG_SIZE;
return result;
}
public long readLong() {
checkRecordPosition(LittleEndian.LONG_SIZE);
/**
* Reads an 8 bit, unsigned value
*/
public short readUByte() {
short s = readByte();
if(s < 0) {
s += 256;
}
return s;
}
long result = LittleEndian.getLong(data, recordOffset);
recordOffset += LittleEndian.LONG_SIZE;
pos += LittleEndian.LONG_SIZE;
return result;
}
/**
* Reads a 16 bit,un- signed value.
* @return
*/
public int readUShort() {
checkRecordPosition();
/**
* Reads an 8 bit, unsigned value
*/
public short readUByte() {
return (short) (readByte() & 0x00FF);
}
int result = LittleEndian.getUShort(data, recordOffset);
recordOffset += LittleEndian.SHORT_SIZE;
pos += LittleEndian.SHORT_SIZE;
return result;
}
/**
* Reads a 16 bit, unsigned value.
* @return
*/
public int readUShort() {
checkRecordPosition(LittleEndian.SHORT_SIZE);
public double readDouble() {
checkRecordPosition();
long valueLongBits = LittleEndian.getLong(data, recordOffset);
double result = Double.longBitsToDouble(valueLongBits);
if (Double.isNaN(result)) {
throw new RuntimeException("Did not expect to read NaN");
}
recordOffset += LittleEndian.DOUBLE_SIZE;
pos += LittleEndian.DOUBLE_SIZE;
return result;
}
int result = LittleEndian.getUShort(data, recordOffset);
recordOffset += LittleEndian.SHORT_SIZE;
pos += LittleEndian.SHORT_SIZE;
return result;
}
public short[] readShortArray() {
checkRecordPosition();
short[] arr = LittleEndian.getShortArray(data, recordOffset);
final int size = (2 * (arr.length +1));
recordOffset += size;
pos += size;
return arr;
}
public double readDouble() {
checkRecordPosition(LittleEndian.DOUBLE_SIZE);
long valueLongBits = LittleEndian.getLong(data, recordOffset);
double result = Double.longBitsToDouble(valueLongBits);
if (Double.isNaN(result)) {
throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN
}
recordOffset += LittleEndian.DOUBLE_SIZE;
pos += LittleEndian.DOUBLE_SIZE;
return result;
}
/**
* given a byte array of 16-bit unicode characters, compress to 8-bit and

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,65 +15,65 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.util.*;
import org.apache.poi.util.LittleEndian;
/**
* The series list record defines the series displayed as an overlay to the main chart record.
* NOTE: This source is automatically generated please do not modify this file. Either subclass or
* remove the record in src/records/definitions.
*
* The series list record defines the series displayed as an overlay to the main chart record.<br/>
* TODO - does this record (0x1016) really exist. It doesn't seem to be referenced in either the OOO or MS doc
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public class SeriesListRecord
extends Record
{
public final static short sid = 0x1016;
public final class SeriesListRecord extends Record {
public final static short sid = 0x1016;
private short[] field_1_seriesNumbers;
public SeriesListRecord()
{
public SeriesListRecord(short[] seriesNumbers) {
field_1_seriesNumbers = seriesNumbers;
}
public SeriesListRecord(RecordInputStream in)
{
field_1_seriesNumbers = in.readShortArray();
public SeriesListRecord(RecordInputStream in) {
int nItems = in.readUShort();
short[] ss = new short[nItems];
for (int i = 0; i < nItems; i++) {
ss[i] = in.readShort();
}
field_1_seriesNumbers = ss;
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[SERIESLIST]\n");
buffer.append(" .seriesNumbers = ")
.append(" (").append( getSeriesNumbers() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .seriesNumbers= ").append(" (").append( getSeriesNumbers() ).append(" )");
buffer.append("\n");
buffer.append("[/SERIESLIST]\n");
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
int pos = 0;
public int serialize(int offset, byte[] data) {
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
int nItems = field_1_seriesNumbers.length;
int dataSize = 2 + 2 * nItems;
LittleEndian.putShortArray(data, 4 + offset + pos, field_1_seriesNumbers);
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
return getRecordSize();
LittleEndian.putUShort(data, 4 + offset, nItems);
int pos = offset + 6;
for (int i = 0; i < nItems; i++) {
LittleEndian.putUShort(data, pos, field_1_seriesNumbers[i]);
pos += 2;
}
return 4 + dataSize;
}
/**
* Size of record (exluding 4 byte header)
*/
public int getRecordSize()
{
return 4 + field_1_seriesNumbers.length * 2 + 2;
@ -86,34 +85,23 @@ public class SeriesListRecord
}
public Object clone() {
SeriesListRecord rec = new SeriesListRecord();
rec.field_1_seriesNumbers = field_1_seriesNumbers;
return rec;
return new SeriesListRecord((short[]) field_1_seriesNumbers.clone());
}
/**
* Get the series numbers field for the SeriesList record.
*/
public short[] getSeriesNumbers()
{
public short[] getSeriesNumbers() {
return field_1_seriesNumbers;
}
/**
* Set the series numbers field for the SeriesList record.
*/
public void setSeriesNumbers(short[] field_1_seriesNumbers)
{
public void setSeriesNumbers(short[] field_1_seriesNumbers) {
this.field_1_seriesNumbers = field_1_seriesNumbers;
}
} // END OF CLASS
}

View File

@ -250,20 +250,6 @@ public final class LittleEndian implements LittleEndianConsts {
putNumber(data, offset, value, LittleEndianConsts.BYTE_SIZE);
}
/**
* put a array of shorts into a byte array
*
*@param data the byte array
*@param offset a starting offset into the byte array
*@param value the short array
*/
public static void putShortArray(final byte[] data, final int offset, final short[] value) {
putNumber(data, offset, value.length, SHORT_SIZE);
for (int i = 0; i < value.length; i++) {
putNumber(data, offset + 2 + (i * 2), value[i], SHORT_SIZE);
}
}
/**
* put an unsigned short value into a byte array
*

View File

@ -29,7 +29,7 @@ import junit.framework.TestCase;
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class TestSeriesListRecord extends TestCase {
byte[] data = new byte[] {
private static final byte[] data = {
(byte)0x02,(byte)0x00,(byte)0x01,(byte)0x20,(byte)0xff,(byte)0xf0
};
@ -43,10 +43,8 @@ public final class TestSeriesListRecord extends TestCase {
assertEquals( 4 + 6, record.getRecordSize() );
}
public void testStore()
{
SeriesListRecord record = new SeriesListRecord();
record.setSeriesNumbers( new short[] { (short)0x2001, (short)0xf0ff } );
public void testStore() {
SeriesListRecord record = new SeriesListRecord(new short[] { (short)0x2001, (short)0xf0ff } );
byte [] recordBytes = record.serialize();
assertEquals(recordBytes.length - 4, data.length);