42564 - fixed ArrayPtg to use ConstantValueParser. Fixed a few other ArrayPtg encoding issues.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@653668 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-05-06 02:02:41 +00:00
parent 31ccbe6fc9
commit 8264540df1
10 changed files with 279 additions and 272 deletions

View File

@ -37,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.1-beta2" date="2008-05-??"> <release version="3.1-beta2" date="2008-05-??">
<action dev="POI-DEVELOPERS" type="fix">42564 - fixed ArrayPtg to use ConstantValueParser. Fixed a few other ArrayPtg encoding issues.</action>
<action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action> <action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action>
<action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action> <action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action>
<action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action> <action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action>

View File

@ -34,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.1-beta2" date="2008-05-??"> <release version="3.1-beta2" date="2008-05-??">
<action dev="POI-DEVELOPERS" type="fix">42564 - fixed ArrayPtg to use ConstantValueParser. Fixed a few other ArrayPtg encoding issues.</action>
<action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action> <action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action>
<action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action> <action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action>
<action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action> <action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action>

View File

@ -24,9 +24,8 @@ import org.apache.poi.util.LittleEndian;
/** /**
* To support Constant Values (2.5.7) as required by the CRN record. * To support Constant Values (2.5.7) as required by the CRN record.
* This class should probably also be used for two dimensional arrays which are encoded by * This class is also used for two dimensional arrays which are encoded by
* EXTERNALNAME (5.39) records and Array tokens.<p/> * EXTERNALNAME (5.39) records and Array tokens.<p/>
* TODO - code in ArrayPtg should be merged with this code. It currently supports only 2 of the constant types
* *
* @author Josh Micich * @author Josh Micich
*/ */

View File

@ -47,6 +47,12 @@ public class ErrorConstant {
public int getErrorCode() { public int getErrorCode() {
return _errorCode; return _errorCode;
} }
public String getText() {
if(HSSFErrorConstants.isValidCode(_errorCode)) {
return HSSFErrorConstants.getText(_errorCode);
}
return "unknown error code (" + _errorCode + ")";
}
public static ErrorConstant valueOf(int errorCode) { public static ErrorConstant valueOf(int errorCode) {
switch (errorCode) { switch (errorCode) {
@ -61,4 +67,11 @@ public class ErrorConstant {
System.err.println("Warning - unexpected error code (" + errorCode + ")"); System.err.println("Warning - unexpected error code (" + errorCode + ")");
return new ErrorConstant(errorCode); return new ErrorConstant(errorCode);
} }
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(getText());
sb.append("]");
return sb.toString();
}
} }

View File

@ -17,22 +17,17 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.StringUtil;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.UnicodeString; import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.record.constant.ConstantValueParser;
import org.apache.poi.hssf.record.constant.ErrorConstant;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.LittleEndian;
/** /**
* ArrayPtg - handles arrays * ArrayPtg - handles arrays
* *
* The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only * The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
* includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows. * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
* It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
* held after this. So Ptg.createParsedExpression keeps track of the number of * held after this. So Ptg.createParsedExpression keeps track of the number of
@ -40,22 +35,16 @@ import org.apache.poi.hssf.record.UnicodeString;
* *
* @author Jason Height (jheight at chariot dot net dot au) * @author Jason Height (jheight at chariot dot net dot au)
*/ */
public class ArrayPtg extends Ptg {
public static final byte sid = 0x20;
public class ArrayPtg extends Ptg private static final int RESERVED_FIELD_LEN = 7;
{ // TODO - fix up field visibility and subclasses
public final static byte sid = 0x20; protected byte[] field_1_reserved;
protected byte field_1_reserved; // data from these fields comes after the Ptg data of all tokens in current formula
protected byte field_2_reserved;
protected byte field_3_reserved;
protected byte field_4_reserved;
protected byte field_5_reserved;
protected byte field_6_reserved;
protected byte field_7_reserved;
protected short token_1_columns; protected short token_1_columns;
protected short token_2_rows; protected short token_2_rows;
protected Object[][] token_3_arrayValues; protected Object[] token_3_arrayValues;
protected ArrayPtg() { protected ArrayPtg() {
//Required for clone methods //Required for clone methods
@ -63,13 +52,11 @@ public class ArrayPtg extends Ptg
public ArrayPtg(RecordInputStream in) public ArrayPtg(RecordInputStream in)
{ {
field_1_reserved = in.readByte(); field_1_reserved = new byte[RESERVED_FIELD_LEN];
field_2_reserved = in.readByte(); // TODO - add readFully method to RecordInputStream
field_3_reserved = in.readByte(); for(int i=0; i< RESERVED_FIELD_LEN; i++) {
field_4_reserved = in.readByte(); field_1_reserved[i] = in.readByte();
field_5_reserved = in.readByte(); }
field_6_reserved = in.readByte();
field_7_reserved = in.readByte();
} }
/** /**
@ -78,29 +65,19 @@ public class ArrayPtg extends Ptg
* See page 304-305 of Excel97-2007BinaryFileFormat(xls)Specification.pdf * See page 304-305 of Excel97-2007BinaryFileFormat(xls)Specification.pdf
*/ */
public void readTokenValues(RecordInputStream in) { public void readTokenValues(RecordInputStream in) {
token_1_columns = (short)(0x00ff & in.readByte()); short nColumns = in.readUByte();
token_2_rows = in.readShort(); short nRows = in.readShort();
//The token_1_columns and token_2_rows do not follow the documentation. //The token_1_columns and token_2_rows do not follow the documentation.
//The number of physical rows and columns is actually +1 of these values. //The number of physical rows and columns is actually +1 of these values.
//Which is not explicitly documented. //Which is not explicitly documented.
token_1_columns++; nColumns++;
token_2_rows++; nRows++;
token_3_arrayValues = new Object[token_1_columns][token_2_rows]; token_1_columns = nColumns;
token_2_rows = nRows;
for (int x=0;x<token_1_columns;x++) { int totalCount = nRows * nColumns;
for (int y=0;y<token_2_rows;y++) { token_3_arrayValues = ConstantValueParser.parse(in, totalCount);
byte grbit = in.readByte();
if (grbit == 0x01) {
token_3_arrayValues[x][y] = new Double(in.readDouble());
} else if (grbit == 0x02) {
//Ignore the doco, it is actually a unicode string with all the
//trimmings ie 16 bit size, option byte etc
token_3_arrayValues[x][y] = in.readUnicodeString();
} else throw new RecordFormatException("Unknown grbit '"+grbit+"' at " + x + "," + y + " with " + in.remaining() + " bytes left");
}
}
} }
public String toString() public String toString()
@ -111,70 +88,44 @@ public class ArrayPtg extends Ptg
buffer.append("rows = ").append(getRowCount()).append("\n"); buffer.append("rows = ").append(getRowCount()).append("\n");
for (int x=0;x<getColumnCount();x++) { for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) { for (int y=0;y<getRowCount();y++) {
Object o = token_3_arrayValues[x][y]; Object o = token_3_arrayValues[getValueIndex(x, y)];
buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n"); buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n");
} }
} }
return buffer.toString(); return buffer.toString();
} }
public void writeBytes(byte [] array, int offset) /* package */ int getValueIndex(int colIx, int rowIx) {
{ if(colIx < 0 || colIx >= token_1_columns) {
array[offset++] = (byte) (sid + ptgClass); throw new IllegalArgumentException("Specified colIx (" + colIx
array[offset++] = field_1_reserved; + ") is outside the allowed range (0.." + (token_1_columns-1) + ")");
array[offset++] = field_2_reserved;
array[offset++] = field_3_reserved;
array[offset++] = field_4_reserved;
array[offset++] = field_5_reserved;
array[offset++] = field_6_reserved;
array[offset++] = field_7_reserved;
} }
public int writeTokenValueBytes(byte [] array, int offset) { if(rowIx < 0 || rowIx >= token_2_rows) {
int pos = 0; throw new IllegalArgumentException("Specified rowIx (" + rowIx
array[pos + offset] = (byte)(token_1_columns-1); + ") is outside the allowed range (0.." + (token_2_rows-1) + ")");
pos++;
LittleEndian.putShort(array, pos+offset, (short)(token_2_rows-1));
pos += 2;
for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) {
Object o = token_3_arrayValues[x][y];
if (o instanceof Double) {
array[pos+offset] = 0x01;
pos++;
LittleEndian.putDouble(array, pos+offset, ((Double)o).doubleValue());
pos+=8;
} else if (o instanceof UnicodeString) {
array[pos+offset] = 0x02;
pos++;
UnicodeString s = (UnicodeString)o;
//JMH TBD Handle string continuation. Id do it now but its 4am.
UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
s.serialize(stats, pos + offset, array);
pos += stats.recordSize;
} else throw new RuntimeException("Coding error");
} }
} return rowIx * token_1_columns + colIx;
return pos;
} }
public void setRowCount(short row) public void writeBytes(byte[] data, int offset) {
{
token_2_rows = row; LittleEndian.putByte(data, offset + 0, sid + ptgClass);
System.arraycopy(field_1_reserved, 0, data, offset+1, RESERVED_FIELD_LEN);
} }
public short getRowCount() public int writeTokenValueBytes(byte[] data, int offset) {
{
LittleEndian.putByte(data, offset + 0, token_1_columns-1);
LittleEndian.putShort(data, offset + 1, (short)(token_2_rows-1));
ConstantValueParser.encode(data, offset + 3, token_3_arrayValues);
return 3 + ConstantValueParser.getEncodedSize(token_3_arrayValues);
}
public short getRowCount() {
return token_2_rows; return token_2_rows;
} }
public void setColumnCount(short col) public short getColumnCount() {
{
token_1_columns = (byte)col;
}
public short getColumnCount()
{
return token_1_columns; return token_1_columns;
} }
@ -182,19 +133,7 @@ public class ArrayPtg extends Ptg
public int getSize() public int getSize()
{ {
int size = 1+7+1+2; int size = 1+7+1+2;
for (int x=0;x<getColumnCount();x++) { size += ConstantValueParser.getEncodedSize(token_3_arrayValues);
for (int y=0;y<getRowCount();y++) {
Object o = token_3_arrayValues[x][y];
if (o instanceof UnicodeString) {
size++;
UnicodeString.UnicodeRecordStats rs = new UnicodeString.UnicodeRecordStats();
((UnicodeString)o).getRecordSize(rs);
size += rs.recordSize;
} else if (o instanceof Double) {
size += 9;
}
}
}
return size; return size;
} }
@ -203,45 +142,52 @@ public class ArrayPtg extends Ptg
StringBuffer b = new StringBuffer(); StringBuffer b = new StringBuffer();
b.append("{"); b.append("{");
for (int x=0;x<getColumnCount();x++) { for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) { if (x > 0) {
Object o = token_3_arrayValues[x][y]; b.append(";");
if (o instanceof String) {
b.append((String)o);
} else if (o instanceof Double) {
b.append(((Double)o).doubleValue());
} }
if (y != getRowCount()) for (int y=0;y<getRowCount();y++) {
if (y > 0) {
b.append(","); b.append(",");
} }
if (x != getColumnCount()) Object o = token_3_arrayValues[getValueIndex(x, y)];
b.append(";"); b.append(getConstantText(o));
}
} }
b.append("}"); b.append("}");
return b.toString(); return b.toString();
} }
private static String getConstantText(Object o) {
if (o == null) {
return ""; // TODO - how is 'empty value' represented in formulas?
}
if (o instanceof UnicodeString) {
return "\"" + ((UnicodeString)o).getString() + "\"";
}
if (o instanceof Double) {
return ((Double)o).toString();
}
if (o instanceof Boolean) {
((Boolean)o).toString();
}
if (o instanceof ErrorConstant) {
return ((ErrorConstant)o).getText();
}
throw new IllegalArgumentException("Unexpected constant class (" + o.getClass().getName() + ")");
}
public byte getDefaultOperandClass() { public byte getDefaultOperandClass() {
return Ptg.CLASS_ARRAY; return Ptg.CLASS_ARRAY;
} }
public Object clone() { public Object clone() {
ArrayPtg ptg = new ArrayPtg(); ArrayPtg ptg = new ArrayPtg();
ptg.field_1_reserved = field_1_reserved; ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
ptg.field_2_reserved = field_2_reserved;
ptg.field_3_reserved = field_3_reserved;
ptg.field_4_reserved = field_4_reserved;
ptg.field_5_reserved = field_5_reserved;
ptg.field_6_reserved = field_6_reserved;
ptg.field_7_reserved = field_7_reserved;
ptg.token_1_columns = token_1_columns; ptg.token_1_columns = token_1_columns;
ptg.token_2_rows = token_2_rows; ptg.token_2_rows = token_2_rows;
ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()]; ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) {
ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
}
}
ptg.setClass(ptgClass); ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -17,56 +17,31 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.StringUtil;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.UnicodeString;
/** /**
* ArrayPtgA - handles arrays * ArrayPtgA - handles arrays
* *
* @author Jason Height (jheight at chariot dot net dot au) * @author Jason Height (jheight at chariot dot net dot au)
*/ */
public final class ArrayPtgA extends ArrayPtg {
public class ArrayPtgA extends ArrayPtg
{
public final static byte sid = 0x60; public final static byte sid = 0x60;
protected ArrayPtgA() { private ArrayPtgA() {
super();
//Required for clone methods //Required for clone methods
} }
public ArrayPtgA(RecordInputStream in) public ArrayPtgA(RecordInputStream in) {
{
super(in); super(in);
} }
public Object clone() { public Object clone() {
ArrayPtgA ptg = new ArrayPtgA(); ArrayPtgA ptg = new ArrayPtgA();
ptg.field_1_reserved = field_1_reserved; ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
ptg.field_2_reserved = field_2_reserved;
ptg.field_3_reserved = field_3_reserved;
ptg.field_4_reserved = field_4_reserved;
ptg.field_5_reserved = field_5_reserved;
ptg.field_6_reserved = field_6_reserved;
ptg.field_7_reserved = field_7_reserved;
ptg.token_1_columns = token_1_columns; ptg.token_1_columns = token_1_columns;
ptg.token_2_rows = token_2_rows; ptg.token_2_rows = token_2_rows;
ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()]; ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) {
ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
}
}
ptg.setClass(ptgClass); ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -17,22 +17,12 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.StringUtil;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.UnicodeString;
/** /**
* ArrayPtg - handles arrays * ArrayPtg - handles arrays
* *
* The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only * The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
* includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows. * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
* It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
* held after this. So Ptg.createParsedExpression keeps track of the number of * held after this. So Ptg.createParsedExpression keeps track of the number of
@ -40,38 +30,24 @@ import org.apache.poi.hssf.record.UnicodeString;
* *
* @author Jason Height (jheight at chariot dot net dot au) * @author Jason Height (jheight at chariot dot net dot au)
*/ */
public final class ArrayPtgV extends ArrayPtg {
public class ArrayPtgV extends ArrayPtg
{
public final static byte sid = 0x40; public final static byte sid = 0x40;
protected ArrayPtgV() { private ArrayPtgV() {
//Required for clone methods //Required for clone methods
} }
public ArrayPtgV(RecordInputStream in) public ArrayPtgV(RecordInputStream in) {
{
super(in); super(in);
} }
public Object clone() { public Object clone() {
ArrayPtgV ptg = new ArrayPtgV(); ArrayPtgV ptg = new ArrayPtgV();
ptg.field_1_reserved = field_1_reserved; ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
ptg.field_2_reserved = field_2_reserved;
ptg.field_3_reserved = field_3_reserved;
ptg.field_4_reserved = field_4_reserved;
ptg.field_5_reserved = field_5_reserved;
ptg.field_6_reserved = field_6_reserved;
ptg.field_7_reserved = field_7_reserved;
ptg.token_1_columns = token_1_columns; ptg.token_1_columns = token_1_columns;
ptg.token_2_rows = token_2_rows; ptg.token_2_rows = token_2_rows;
ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()]; ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
for (int x=0;x<getColumnCount();x++) {
for (int y=0;y<getRowCount();y++) {
ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
}
}
ptg.setClass(ptgClass); ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -40,6 +40,7 @@ public final class AllFormulaTests {
result.addTestSuite(TestArea3DPtg.class); result.addTestSuite(TestArea3DPtg.class);
result.addTestSuite(TestAreaErrPtg.class); result.addTestSuite(TestAreaErrPtg.class);
result.addTestSuite(TestAreaPtg.class); result.addTestSuite(TestAreaPtg.class);
result.addTestSuite(TestArrayPtg.class);
result.addTestSuite(TestErrPtg.class); result.addTestSuite(TestErrPtg.class);
result.addTestSuite(TestExternalFunctionFormulas.class); result.addTestSuite(TestExternalFunctionFormulas.class);
result.addTestSuite(TestFuncPtg.class); result.addTestSuite(TestFuncPtg.class);

View File

@ -0,0 +1,95 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import java.util.Arrays;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.record.UnicodeString;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests for <tt>ArrayPtg</tt>
*
* @author Josh Micich
*/
public final class TestArrayPtg extends TestCase {
private static final byte[] ENCODED_PTG_DATA = {
0x40, 0x00,
0x08, 0x00,
0, 0, 0, 0, 0, 0, 0, 0,
};
private static final byte[] ENCODED_CONSTANT_DATA = {
2, // 3 columns
1, 0, // 2 rows
4, 1, 0, 0, 0, 0, 0, 0, 0, // TRUE
2, 4, 0, 0, 65, 66, 67, 68, // "ABCD"
2, 1, 0, 0, 69, // "E"
1, 0, 0, 0, 0, 0, 0, 0, 0, // 0
4, 0, 0, 0, 0, 0, 0, 0, 0, // FALSE
2, 2, 0, 0, 70, 71, // "FG"
};
/**
* Lots of problems with ArrayPtg's encoding of
*/
public void testReadWriteTokenValueBytes() {
ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA));
ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
assertEquals(3, ptg.getColumnCount());
assertEquals(2, ptg.getRowCount());
Object[] values = ptg.token_3_arrayValues;
assertEquals(6, values.length);
assertEquals(Boolean.TRUE, values[0]);
assertEquals(new UnicodeString("ABCD"), values[1]);
assertEquals(new Double(0), values[3]);
assertEquals(Boolean.FALSE, values[4]);
assertEquals(new UnicodeString("FG"), values[5]);
byte[] outBuf = new byte[ENCODED_CONSTANT_DATA.length];
ptg.writeTokenValueBytes(outBuf, 0);
if(outBuf[0] == 4) {
throw new AssertionFailedError("Identified bug 42564b");
}
assertTrue(Arrays.equals(ENCODED_CONSTANT_DATA, outBuf));
}
/**
* make sure constant elements are stored row by row
*/
public void testElementOrdering() {
ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA));
ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
assertEquals(3, ptg.getColumnCount());
assertEquals(2, ptg.getRowCount());
assertEquals(0, ptg.getValueIndex(0, 0));
assertEquals(1, ptg.getValueIndex(1, 0));
assertEquals(2, ptg.getValueIndex(2, 0));
assertEquals(3, ptg.getValueIndex(0, 1));
assertEquals(4, ptg.getValueIndex(1, 1));
assertEquals(5, ptg.getValueIndex(2, 1));
}
}

View File

@ -732,7 +732,7 @@ public final class TestBugs extends TestCase {
* with the NameRecord, once you get past the BOFRecord * with the NameRecord, once you get past the BOFRecord
* issue. * issue.
*/ */
public void DISABLEDtest42564Alt() { public void test42564Alt() {
HSSFWorkbook wb = openSample("42564-2.xls"); HSSFWorkbook wb = openSample("42564-2.xls");
writeOutAndReadBack(wb); writeOutAndReadBack(wb);
} }