Merged revisions 711764 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk ........ r711764 | josh | 2008-11-05 19:43:17 -0800 (Wed, 05 Nov 2008) | 1 line Bug 45784 - More fixes to SeriesTextRecord ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@711963 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a828d3edbc
commit
0993370781
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.5-beta4" date="2008-??-??">
|
<release version="3.5-beta4" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">45784 - More fixes to SeriesTextRecord</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">46033 - fixed TableCell to correctly set text type</action>
|
<action dev="POI-DEVELOPERS" type="fix">46033 - fixed TableCell to correctly set text type</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">46122 - fixed Picture.draw to skip rendering if picture data was not found</action>
|
<action dev="POI-DEVELOPERS" type="fix">46122 - fixed Picture.draw to skip rendering if picture data was not found</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">15716 - memory usage optimisation - converted Ptg arrays into Formula objects</action>
|
<action dev="POI-DEVELOPERS" type="fix">15716 - memory usage optimisation - converted Ptg arrays into Formula objects</action>
|
||||||
|
@ -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.5-beta4" date="2008-??-??">
|
<release version="3.5-beta4" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">45784 - More fixes to SeriesTextRecord</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">46033 - fixed TableCell to correctly set text type</action>
|
<action dev="POI-DEVELOPERS" type="fix">46033 - fixed TableCell to correctly set text type</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">46122 - fixed Picture.draw to skip rendering if picture data was not found</action>
|
<action dev="POI-DEVELOPERS" type="fix">46122 - fixed Picture.draw to skip rendering if picture data was not found</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">15716 - memory usage optimisation - converted Ptg arrays into Formula objects</action>
|
<action dev="POI-DEVELOPERS" type="fix">15716 - memory usage optimisation - converted Ptg arrays into Formula objects</action>
|
||||||
|
@ -18,82 +18,79 @@
|
|||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
import org.apache.poi.util.HexDump;
|
import org.apache.poi.util.HexDump;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||||
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
import org.apache.poi.util.StringUtil;
|
import org.apache.poi.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* SERIESTEXT (0x100D)</p>
|
||||||
* Defines a series name</p>
|
* Defines a series name</p>
|
||||||
*
|
*
|
||||||
* @author Andrew C. Oliver (acoliver at apache.org)
|
* @author Andrew C. Oliver (acoliver at apache.org)
|
||||||
*/
|
*/
|
||||||
public final class SeriesTextRecord extends Record {
|
public final class SeriesTextRecord extends Record {
|
||||||
public final static short sid = 0x100d;
|
public final static short sid = 0x100D;
|
||||||
private short field_1_id;
|
|
||||||
private byte field_2_textLength;
|
/** the actual text cannot be longer than 255 characters */
|
||||||
private byte field_3_undocumented;
|
private static final int MAX_LEN = 0xFF;
|
||||||
|
private int field_1_id;
|
||||||
|
private boolean is16bit;
|
||||||
private String field_4_text;
|
private String field_4_text;
|
||||||
|
|
||||||
|
public SeriesTextRecord() {
|
||||||
public SeriesTextRecord()
|
field_4_text = "";
|
||||||
{
|
is16bit = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SeriesTextRecord(RecordInputStream in)
|
public SeriesTextRecord(RecordInputStream in) {
|
||||||
{
|
field_1_id = in.readUShort();
|
||||||
field_1_id = in.readShort();
|
int field_2_textLength = in.readUByte();
|
||||||
field_2_textLength = in.readByte();
|
is16bit = (in.readUByte() & 0x01) != 0;
|
||||||
field_3_undocumented = in.readByte();
|
if (is16bit) {
|
||||||
field_4_text = in.readUnicodeLEString(
|
field_4_text = in.readUnicodeLEString(field_2_textLength);
|
||||||
LittleEndian.ubyteToInt(field_2_textLength));
|
} else {
|
||||||
|
field_4_text = in.readCompressedUnicode(field_2_textLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString()
|
public String toString() {
|
||||||
{
|
StringBuffer sb = new StringBuffer();
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
|
|
||||||
buffer.append("[SERIESTEXT]\n");
|
sb.append("[SERIESTEXT]\n");
|
||||||
buffer.append(" .id = ")
|
sb.append(" .id =").append(HexDump.shortToHex(getId())).append('\n');
|
||||||
.append("0x").append(HexDump.toHex( getId ()))
|
sb.append(" .textLen=").append(field_4_text.length()).append('\n');
|
||||||
.append(" (").append( getId() ).append(" )");
|
sb.append(" .is16bit=").append(is16bit).append('\n');
|
||||||
buffer.append(System.getProperty("line.separator"));
|
sb.append(" .text =").append(" (").append(getText()).append(" )").append('\n');
|
||||||
buffer.append(" .textLength = ")
|
sb.append("[/SERIESTEXT]\n");
|
||||||
.append("0x").append(HexDump.toHex( getTextLength ()))
|
return sb.toString();
|
||||||
.append(" (").append( getTextLength() ).append(" )");
|
|
||||||
buffer.append(System.getProperty("line.separator"));
|
|
||||||
buffer.append(" .undocumented = ")
|
|
||||||
.append("0x").append(HexDump.toHex( getUndocumented ()))
|
|
||||||
.append(" (").append( getUndocumented() ).append(" )");
|
|
||||||
buffer.append(System.getProperty("line.separator"));
|
|
||||||
buffer.append(" .text = ")
|
|
||||||
.append(" (").append( getText() ).append(" )");
|
|
||||||
buffer.append(System.getProperty("line.separator"));
|
|
||||||
|
|
||||||
buffer.append("[/SERIESTEXT]\n");
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int serialize(int offset, byte[] data)
|
public int serialize(int offset, byte[] data) {
|
||||||
{
|
int dataSize = getDataSize();
|
||||||
int pos = 0;
|
int recordSize = 4 + dataSize;
|
||||||
|
LittleEndianOutput out = new LittleEndianByteArrayOutputStream(data, offset, recordSize);
|
||||||
|
out.writeShort(sid);
|
||||||
|
out.writeShort(dataSize);
|
||||||
|
|
||||||
LittleEndian.putShort(data, 0 + offset, sid);
|
out.writeShort(field_1_id);
|
||||||
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
|
out.writeByte(field_4_text.length());
|
||||||
|
if (is16bit) {
|
||||||
LittleEndian.putShort(data, 4 + offset + pos, field_1_id);
|
// Excel (2007) seems to choose 16bit regardless of whether it is needed
|
||||||
data[ 6 + offset + pos ] = field_2_textLength;
|
out.writeByte(0x01);
|
||||||
data[ 7 + offset + pos ] = field_3_undocumented;
|
StringUtil.putUnicodeLE(field_4_text, out);
|
||||||
StringUtil.putUnicodeLE(field_4_text, data, 8 + offset + pos);
|
} else {
|
||||||
|
// Excel can read this OK
|
||||||
return getRecordSize();
|
out.writeByte(0x00);
|
||||||
|
StringUtil.putCompressedUnicode(field_4_text, out);
|
||||||
|
}
|
||||||
|
return recordSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDataSize() {
|
protected int getDataSize() {
|
||||||
return 2 + 1 + 1 + (field_2_textLength *2);
|
return 2 + 1 + 1 + field_4_text.length() * (is16bit ? 2 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getSid()
|
public short getSid() {
|
||||||
{
|
|
||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,92 +98,41 @@ public final class SeriesTextRecord extends Record {
|
|||||||
SeriesTextRecord rec = new SeriesTextRecord();
|
SeriesTextRecord rec = new SeriesTextRecord();
|
||||||
|
|
||||||
rec.field_1_id = field_1_id;
|
rec.field_1_id = field_1_id;
|
||||||
rec.field_2_textLength = field_2_textLength;
|
rec.is16bit = is16bit;
|
||||||
rec.field_3_undocumented = field_3_undocumented;
|
|
||||||
rec.field_4_text = field_4_text;
|
rec.field_4_text = field_4_text;
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the id field for the SeriesText record.
|
* Get the id field for the SeriesText record.
|
||||||
*/
|
*/
|
||||||
public short getId()
|
public int getId() {
|
||||||
{
|
|
||||||
return field_1_id;
|
return field_1_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the id field for the SeriesText record.
|
* Set the id field for the SeriesText record.
|
||||||
*/
|
*/
|
||||||
public void setId(short field_1_id)
|
public void setId(int id) {
|
||||||
{
|
field_1_id = id;
|
||||||
this.field_1_id = field_1_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the text length field for the SeriesText record.
|
|
||||||
*/
|
|
||||||
public int getTextLength()
|
|
||||||
{
|
|
||||||
return LittleEndian.ubyteToInt(field_2_textLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the text length field for the SeriesText record.
|
|
||||||
* Needs to be wrapped.
|
|
||||||
*/
|
|
||||||
public void setTextLength(byte field_2_textLength)
|
|
||||||
{
|
|
||||||
this.field_2_textLength = field_2_textLength;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Set the text length field for the SeriesText record.
|
|
||||||
*/
|
|
||||||
public void setTextLength(int field_2_textLength)
|
|
||||||
{
|
|
||||||
if(field_2_textLength > 255) {
|
|
||||||
throw new IllegalArgumentException("Length must be 0-255");
|
|
||||||
}
|
|
||||||
if(field_2_textLength > 127) {
|
|
||||||
this.field_2_textLength = (byte)
|
|
||||||
(field_2_textLength-256);
|
|
||||||
} else {
|
|
||||||
this.field_2_textLength = (byte)field_2_textLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the undocumented field for the SeriesText record.
|
|
||||||
*/
|
|
||||||
public byte getUndocumented()
|
|
||||||
{
|
|
||||||
return field_3_undocumented;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the undocumented field for the SeriesText record.
|
|
||||||
*/
|
|
||||||
public void setUndocumented(byte field_3_undocumented)
|
|
||||||
{
|
|
||||||
this.field_3_undocumented = field_3_undocumented;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the text field for the SeriesText record.
|
* Get the text field for the SeriesText record.
|
||||||
*/
|
*/
|
||||||
public String getText()
|
public String getText() {
|
||||||
{
|
|
||||||
return field_4_text;
|
return field_4_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the text field for the SeriesText record.
|
* Set the text field for the SeriesText record.
|
||||||
*/
|
*/
|
||||||
public void setText(String field_4_text)
|
public void setText(String text) {
|
||||||
{
|
if (text.length() > MAX_LEN) {
|
||||||
this.field_4_text = field_4_text;
|
throw new IllegalArgumentException("Text is too long ("
|
||||||
|
+ text.length() + ">" + MAX_LEN + ")");
|
||||||
|
}
|
||||||
|
field_4_text = text;
|
||||||
|
is16bit = StringUtil.hasMultibyte(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,46 +17,89 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
import org.apache.poi.util.HexRead;
|
||||||
* Tests the serialization and deserialization of the SeriesTextRecord
|
|
||||||
* class works correctly. Test data taken directly from a real
|
|
||||||
* Excel file.
|
|
||||||
*
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the serialization and deserialization of the SeriesTextRecord class
|
||||||
|
* works correctly. Test data taken directly from a real Excel file.
|
||||||
|
*
|
||||||
|
*
|
||||||
* @author Andrew C. Oliver (acoliver at apache.org)
|
* @author Andrew C. Oliver (acoliver at apache.org)
|
||||||
*/
|
*/
|
||||||
public final class TestSeriesTextRecord extends TestCase {
|
public final class TestSeriesTextRecord extends TestCase {
|
||||||
byte[] data = new byte[] {
|
private static final byte[] SIMPLE_DATA = HexRead
|
||||||
(byte)0x00,(byte)0x00,(byte)0x0C,(byte)0x01,(byte)0x56,(byte)0x00,(byte)0x61,(byte)0x00,(byte)0x6C,(byte)0x00,(byte)0x75,(byte)0x00,(byte)0x65,(byte)0x00,(byte)0x20,(byte)0x00,(byte)0x4E,(byte)0x00,(byte)0x75,(byte)0x00,(byte)0x6D,(byte)0x00,(byte)0x62,(byte)0x00,(byte)0x65,(byte)0x00,(byte)0x72,(byte)0x00
|
.readFromString("00 00 0C 00 56 61 6C 75 65 20 4E 75 6D 62 65 72");
|
||||||
};
|
|
||||||
|
|
||||||
public void testLoad() {
|
public void testLoad() {
|
||||||
SeriesTextRecord record = new SeriesTextRecord(TestcaseRecordInputStream.create(0x100d, data));
|
SeriesTextRecord record = new SeriesTextRecord(TestcaseRecordInputStream.create(0x100d, SIMPLE_DATA));
|
||||||
|
|
||||||
assertEquals( (short)0, record.getId());
|
assertEquals((short) 0, record.getId());
|
||||||
assertEquals( (byte)0x0C, record.getTextLength());
|
assertEquals("Value Number", record.getText());
|
||||||
assertEquals( (byte)0x01, record.getUndocumented());
|
|
||||||
assertEquals( "Value Number", record.getText());
|
|
||||||
|
|
||||||
assertEquals( 32, record.getRecordSize() );
|
assertEquals(SIMPLE_DATA.length + 4, record.getRecordSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testStore()
|
public void testStore() {
|
||||||
{
|
|
||||||
SeriesTextRecord record = new SeriesTextRecord();
|
SeriesTextRecord record = new SeriesTextRecord();
|
||||||
|
|
||||||
record.setId( (short)0 );
|
record.setId(0);
|
||||||
record.setTextLength( (byte)0x0C );
|
record.setText("Value Number");
|
||||||
record.setUndocumented( (byte)0x01 );
|
|
||||||
record.setText( "Value Number" );
|
|
||||||
|
|
||||||
|
byte[] recordBytes = record.serialize();
|
||||||
|
TestcaseRecordInputStream.confirmRecordEncoding(SeriesTextRecord.sid, SIMPLE_DATA,
|
||||||
|
recordBytes);
|
||||||
|
}
|
||||||
|
|
||||||
byte [] recordBytes = record.serialize();
|
public void testReserializeLongTitle() {
|
||||||
assertEquals(recordBytes.length - 4, data.length);
|
// Hex dump from bug 45784 attachment 22560 streamOffset=0x0CD1
|
||||||
for (int i = 0; i < data.length; i++)
|
byte[] data = HexRead.readFromString(
|
||||||
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
|
"00 00, "
|
||||||
|
+ "82 "
|
||||||
|
+ "01 "
|
||||||
|
+ "50 00 6C 00 61 00 73 00 6D 00 61 00 20 00 4C 00 "
|
||||||
|
+ "65 00 76 00 65 00 6C 00 73 00 20 00 6F 00 66 00 "
|
||||||
|
+ "20 00 4C 00 2D 00 30 00 30 00 30 00 31 00 31 00 "
|
||||||
|
+ "31 00 32 00 32 00 32 00 2D 00 33 00 33 00 33 00 "
|
||||||
|
+ "58 00 34 00 34 00 34 00 20 00 69 00 6E 00 20 00 "
|
||||||
|
+ "53 00 44 00 20 00 72 00 61 00 74 00 0A 00 50 00 "
|
||||||
|
+ "4F 00 20 00 33 00 2E 00 30 00 20 00 6D 00 67 00 "
|
||||||
|
+ "2F 00 6B 00 67 00 20 00 28 00 35 00 2E 00 30 00 "
|
||||||
|
+ "20 00 6D 00 4C 00 2F 00 6B 00 67 00 29 00 20 00 "
|
||||||
|
+ "69 00 6E 00 20 00 4D 00 65 00 74 00 68 00 6F 00 "
|
||||||
|
+ "63 00 65 00 6C 00 0A 00 49 00 56 00 20 00 30 00 "
|
||||||
|
+ "2E 00 35 00 20 00 6D 00 67 00 2F 00 6B 00 67 00 "
|
||||||
|
+ "20 00 28 00 31 00 2E 00 30 00 20 00 6D 00 4C 00 "
|
||||||
|
+ "2F 00 6B 00 67 00 29 00 20 00 69 00 6E 00 20 00 "
|
||||||
|
+ "36 00 30 00 25 00 20 00 50 00 45 00 47 00 20 00 "
|
||||||
|
+ "32 00 30 00 30 00 0A 00 46 00 20 00 3D 00 61 00 "
|
||||||
|
+ "62 00 63 00");
|
||||||
|
|
||||||
|
RecordInputStream in = TestcaseRecordInputStream.create(SeriesTextRecord.sid, data);
|
||||||
|
SeriesTextRecord str;
|
||||||
|
try {
|
||||||
|
str = new SeriesTextRecord(in);
|
||||||
|
} catch (RecordFormatException e) {
|
||||||
|
if (e.getCause() instanceof IllegalArgumentException) {
|
||||||
|
// 'would be' error msg changed at svn r703620
|
||||||
|
// "Illegal length - asked for -126 but only 130 left!"
|
||||||
|
// "Bad requested string length (-126)"
|
||||||
|
throw new AssertionFailedError("Identified bug 45784a");
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.getRecordSize() < 0) {
|
||||||
|
throw new AssertionFailedError("Identified bug 45784b");
|
||||||
|
}
|
||||||
|
byte[] ser;
|
||||||
|
try {
|
||||||
|
ser = str.serialize();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
TestcaseRecordInputStream.confirmRecordEncoding(SeriesTextRecord.sid, data, ser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1484,6 +1484,7 @@ public final class TestBugs extends TestCase {
|
|||||||
// This used to break
|
// This used to break
|
||||||
HSSFWorkbook wb = openSample("45784.xls");
|
HSSFWorkbook wb = openSample("45784.xls");
|
||||||
assertEquals(1, wb.getNumberOfSheets());
|
assertEquals(1, wb.getNumberOfSheets());
|
||||||
|
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user