import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianInputStream;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
}
private static Ptg readRefPtg(byte[] formulaRawBytes) {
- byte[] data = new byte[formulaRawBytes.length + 4];
- LittleEndian.putUShort(data, 0, -5555);
- LittleEndian.putUShort(data, 2, formulaRawBytes.length);
- System.arraycopy(formulaRawBytes, 0, data, 4, formulaRawBytes.length);
- RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
- in.nextRecord();
+ LittleEndianInput in = new LittleEndianInputStream(new ByteArrayInputStream(formulaRawBytes));
byte ptgSid = in.readByte();
switch(ptgSid) {
case AreaPtg.sid: return new AreaPtg(in);
import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.LittleEndianOutputStream;
out.writeShort(_unknownShort13);
}
private static Ptg readRefPtg(byte[] formulaRawBytes) {
- byte[] data = new byte[formulaRawBytes.length + 4];
- LittleEndian.putUShort(data, 0, -5555);
- LittleEndian.putUShort(data, 2, formulaRawBytes.length);
- System.arraycopy(formulaRawBytes, 0, data, 4, formulaRawBytes.length);
- RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
- in.nextRecord();
- byte ptgSid = in.readByte();
+ LittleEndianInput in = new LittleEndianByteArrayInputStream(formulaRawBytes);
+ byte ptgSid = in.readByte();
switch(ptgSid) {
case AreaPtg.sid: return new AreaPtg(in);
case Area3DPtg.sid: return new Area3DPtg(in);
- case RefPtg.sid: return new RefPtg(in);
+ case RefPtg.sid: return new RefPtg(in);
case Ref3DPtg.sid: return new Ref3DPtg(in);
}
return null;
--- /dev/null
+/* ====================================================================
+ 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.util;
+
+/**
+ * Adapts a plain byte array to {@link LittleEndianInput}
+ *
+ *
+ * @author Josh Micich
+ */
+public final class LittleEndianByteArrayInputStream implements LittleEndianInput {
+ private final byte[] _buf;
+ private final int _endIndex;
+ private int _readIndex;
+
+ public LittleEndianByteArrayInputStream(byte[] buf, int startOffset, int maxReadLen) {
+ _buf = buf;
+ _readIndex = startOffset;
+ _endIndex = startOffset + maxReadLen;
+ }
+ public LittleEndianByteArrayInputStream(byte[] buf, int startOffset) {
+ this(buf, startOffset, buf.length - startOffset);
+ }
+ public LittleEndianByteArrayInputStream(byte[] buf) {
+ this(buf, 0, buf.length);
+ }
+
+ private void checkPosition(int i) {
+ if (i > _endIndex - _readIndex) {
+ throw new RuntimeException("Buffer overrun");
+ }
+ }
+
+ public int getReadIndex() {
+ return _readIndex;
+ }
+ public byte readByte() {
+ checkPosition(1);
+ return _buf[_readIndex++];
+ }
+
+ public int readInt() {
+ checkPosition(4);
+ int i = _readIndex;
+
+ int b0 = _buf[i++] & 0xFF;
+ int b1 = _buf[i++] & 0xFF;
+ int b2 = _buf[i++] & 0xFF;
+ int b3 = _buf[i++] & 0xFF;
+ _readIndex = i;
+ return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
+ }
+ public long readLong() {
+ checkPosition(8);
+ int i = _readIndex;
+
+ int b0 = _buf[i++] & 0xFF;
+ int b1 = _buf[i++] & 0xFF;
+ int b2 = _buf[i++] & 0xFF;
+ int b3 = _buf[i++] & 0xFF;
+ int b4 = _buf[i++] & 0xFF;
+ int b5 = _buf[i++] & 0xFF;
+ int b6 = _buf[i++] & 0xFF;
+ int b7 = _buf[i++] & 0xFF;
+ _readIndex = i;
+ return (((long)b7 << 56) +
+ ((long)b6 << 48) +
+ ((long)b5 << 40) +
+ ((long)b4 << 32) +
+ ((long)b3 << 24) +
+ (b2 << 16) +
+ (b1 << 8) +
+ (b0 << 0));
+ }
+ public short readShort() {
+ return (short)readUShort();
+ }
+ public int readUByte() {
+ checkPosition(1);
+ return _buf[_readIndex++] & 0xFF;
+ }
+ public int readUShort() {
+ checkPosition(2);
+ int i = _readIndex;
+
+ int b0 = _buf[i++] & 0xFF;
+ int b1 = _buf[i++] & 0xFF;
+ _readIndex = i;
+ return (b1 << 8) + (b0 << 0);
+ }
+ public void readFully(byte[] buf, int off, int len) {
+ checkPosition(len);
+ System.arraycopy(_buf, _readIndex, _buf, off, len);
+ _readIndex+=len;
+ }
+ public void readFully(byte[] buf) {
+ readFully(buf, 0, buf.length);
+ }
+ public double readDouble() {
+ return Double.longBitsToDouble(readLong());
+ }
+ public String readCompressedUnicode(int nChars) {
+ checkPosition(nChars);
+ char[] buf = new char[nChars];
+ for (int i = 0; i < buf.length; i++) {
+ buf[i] = (char) readUByte();
+ }
+ return new String(buf);
+ }
+ public String readUnicodeLEString(int nChars) {
+ checkPosition(nChars*2);
+ char[] buf = new char[nChars];
+ for (int i = 0; i < buf.length; i++) {
+ buf[i] = (char) readUShort();
+ }
+ return new String(buf);
+ }
+}
};
public void testLoad() {
- CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(TestcaseRecordInputStream.createWithFakeSid(data), data.length);
+ CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(TestcaseRecordInputStream.createLittleEndian(data), data.length);
assertEquals( CommonObjectDataSubRecord.OBJECT_TYPE_LIST_BOX, record.getObjectType());
assertEquals((short) 1, record.getObjectId());
See the License for the specific language governing permissions and\r
limitations under the License.\r
==================================================================== */\r
+\r
package org.apache.poi.hssf.record;\r
\r
-import java.io.ByteArrayInputStream;\r
import java.util.Arrays;\r
\r
+import junit.framework.AssertionFailedError;\r
import junit.framework.TestCase;\r
\r
import org.apache.poi.util.HexRead;\r
public void testStore() {\r
\r
byte[] src = hr(data1);\r
- src = TestcaseRecordInputStream.mergeDataAndSid(EmbeddedObjectRefSubRecord.sid, (short)src.length, src);\r
+// src = TestcaseRecordInputStream.mergeDataAndSid(EmbeddedObjectRefSubRecord.sid, (short)src.length, src);\r
\r
- RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(src));\r
- in.nextRecord();\r
+ RecordInputStream in = TestcaseRecordInputStream.create(EmbeddedObjectRefSubRecord.sid, src);\r
\r
- EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord(in, src.length-4);\r
+ EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord(in, src.length);\r
\r
byte[] ser = record1.serialize();\r
\r
- RecordInputStream in2 = new RecordInputStream(new ByteArrayInputStream(ser));\r
- in2.nextRecord();\r
+ RecordInputStream in2 = TestcaseRecordInputStream.create(ser);\r
EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2, ser.length-4);\r
\r
- assertTrue(Arrays.equals(src, ser));\r
+ confirmData(src, ser);\r
assertEquals(record1.getOLEClassName(), record2.getOLEClassName());\r
\r
byte[] ser2 = record1.serialize();\r
assertTrue(Arrays.equals(ser, ser2));\r
}\r
\r
+ /**\r
+ * @param expectedData does not include sid & size\r
+ * @param actualFullRecordData includes sid & size\r
+ */\r
+ private static void confirmData(byte[] expectedData, byte[] actualFullRecordData) {\r
+ assertEquals(expectedData.length, actualFullRecordData.length-4);\r
+ for (int i = 0; i < expectedData.length; i++) {\r
+ if(expectedData[i] != actualFullRecordData[i+4]) {\r
+ throw new AssertionFailedError("Difference at offset (" + i + ")");\r
+ }\r
+ }\r
+ }\r
+\r
public void testCreate() {\r
\r
EmbeddedObjectRefSubRecord record1 = new EmbeddedObjectRefSubRecord();\r
\r
byte[] ser = record1.serialize();\r
- RecordInputStream in2 = new RecordInputStream(new ByteArrayInputStream(ser));\r
- in2.nextRecord();\r
+ RecordInputStream in2 = TestcaseRecordInputStream.create(ser);\r
EmbeddedObjectRefSubRecord record2 = new EmbeddedObjectRefSubRecord(in2, ser.length-4);\r
\r
assertEquals(record1.getOLEClassName(), record2.getOLEClassName());\r
* taken from ftPictFmla sub-record in attachment 22645 (offset 0x40AB).\r
*/\r
private static final byte[] data45912 = hr(\r
- "09 00 14 00 " +\r
"12 00 0B 00 F8 02 88 04 3B 00 " +\r
"00 00 00 01 00 00 00 01 " +\r
"00 00");\r
\r
public void testCameraTool_bug45912() {\r
byte[] data = data45912;\r
- RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));\r
- in.nextRecord();\r
+ RecordInputStream in = TestcaseRecordInputStream.create(EmbeddedObjectRefSubRecord.sid, data);\r
\r
- EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in, data.length-4);\r
+ EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in, data.length);\r
byte[] ser2 = rec.serialize();\r
- assertTrue(Arrays.equals(data, ser2));\r
-\r
-\r
+ confirmData(data, ser2);\r
}\r
\r
private static byte[] hr(String string) {\r
public void testWithConcat() {
// =CHOOSE(2,A2,A3,A4)
byte[] data = {
- 6, 0, 68, 0,
1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 57,
64, 0, 0, 12, 0, 12, -4, 46, 0,
30, 2, 0, // Int - 2
25, 8, 3, 0, // Attr
66, 4, 100, 0 // CHOOSE
};
- RecordInputStream inp = new RecordInputStream( new ByteArrayInputStream(data));
- inp.nextRecord();
+ RecordInputStream inp = TestcaseRecordInputStream.create(FormatRecord.sid, data);
FormulaRecord fr = new FormulaRecord(inp);
RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data);
HyperlinkRecord link = new HyperlinkRecord(is);
byte[] bytes1 = link.serialize();
- is = new RecordInputStream(new ByteArrayInputStream(bytes1));
- is.nextRecord();
+ is = TestcaseRecordInputStream.create(bytes1);
link = new HyperlinkRecord(is);
byte[] bytes2 = link.serialize();
assertEquals(bytes1.length, bytes2.length);
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg;
+import org.apache.poi.util.LittleEndianInput;
/**
* @author Josh Micich
*/
public void testConvertSharedFormulasOperandClasses_bug45123() {
- RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
+ LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
int encodedLen = in.readUShort();
Ptg[] sharedFormula = Ptg.readTokens(encodedLen, in);
public void testLoad() {
- RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
- in.nextRecord();
+ RecordInputStream in = TestcaseRecordInputStream.create(data);
TextObjectRecord record = new TextObjectRecord(in);
-
assertEquals(TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_CENTERED, record.getHorizontalTextAlignment());
assertEquals(TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_JUSTIFY, record.getVerticalTextAlignment());
assertEquals(true, record.isTextLocked());
\r
public void testRead() {\r
\r
- RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(simpleData));\r
- is.nextRecord();\r
+ RecordInputStream is =TestcaseRecordInputStream.create(simpleData);\r
TextObjectRecord record = new TextObjectRecord(is);\r
\r
assertEquals(TextObjectRecord.sid, record.getSid());\r
assertTrue(Arrays.equals(simpleData, ser));\r
\r
//read again\r
- RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(simpleData));\r
- is.nextRecord();\r
+ RecordInputStream is = TestcaseRecordInputStream.create(simpleData);\r
record = new TextObjectRecord(is);\r
}\r
\r
assertEquals(22, ser.length); // just the TXO record\r
\r
//read again\r
- RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(ser));\r
- is.nextRecord();\r
+ RecordInputStream is = TestcaseRecordInputStream.create(ser);\r
record = new TextObjectRecord(is);\r
assertEquals(0, record.getStr().length());\r
}\r
import junit.framework.Assert;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianInput;
/**
* A Record Input Stream derivative that makes access to byte arrays used in the
/**
* Prepends a mock record identifier to the supplied data and opens a record input stream
*/
- public static RecordInputStream createWithFakeSid(byte[] data) {
- return create(-5555, data);
+ public static LittleEndianInput createLittleEndian(byte[] data) {
+ return new LittleEndianByteArrayInputStream(data);
}
public static RecordInputStream create(int sid, byte[] data) {
import junit.framework.TestCase;
-import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
import org.apache.poi.util.HexRead;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianInput;
/**
*
* @author Josh Micich
}
}
public void testDecode() {
- RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(SAMPLE_ENCODING);
+ LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(SAMPLE_ENCODING);
Object[] values = ConstantValueParser.parse(in, 4);
for (int i = 0; i < values.length; i++) {
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianInput;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
*/
public void testReadWriteTokenValueBytes() {
- ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createWithFakeSid(ENCODED_PTG_DATA));
+ ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createLittleEndian(ENCODED_PTG_DATA));
- ptg.readTokenValues(TestcaseRecordInputStream.createWithFakeSid(ENCODED_CONSTANT_DATA));
+ ptg.readTokenValues(TestcaseRecordInputStream.createLittleEndian(ENCODED_CONSTANT_DATA));
assertEquals(3, ptg.getColumnCount());
assertEquals(2, ptg.getRowCount());
Object[][] values = ptg.getTokenArrayValues();
* Excel stores array elements column by column. This test makes sure POI does the same.
*/
public void testElementOrdering() {
- ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createWithFakeSid(ENCODED_PTG_DATA));
- ptg.readTokenValues(TestcaseRecordInputStream.createWithFakeSid(ENCODED_CONSTANT_DATA));
+ ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createLittleEndian(ENCODED_PTG_DATA));
+ ptg.readTokenValues(TestcaseRecordInputStream.createLittleEndian(ENCODED_CONSTANT_DATA));
assertEquals(3, ptg.getColumnCount());
assertEquals(2, ptg.getRowCount());
}
public void testToFormulaString() {
- ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createWithFakeSid(ENCODED_PTG_DATA));
+ ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createLittleEndian(ENCODED_PTG_DATA));
- ptg.readTokenValues(TestcaseRecordInputStream.createWithFakeSid(ENCODED_CONSTANT_DATA));
+ ptg.readTokenValues(TestcaseRecordInputStream.createLittleEndian(ENCODED_CONSTANT_DATA));
String actualFormula;
try {
// Force encoded operand class for tArray
fullData[0] = (byte) (ArrayPtg.sid + operandClass);
- RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(fullData);
+ LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(fullData);
Ptg[] ptgs = Ptg.readTokens(ENCODED_PTG_DATA.length, in);
assertEquals(1, ptgs.length);
import junit.framework.AssertionFailedError;
-import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.util.HexRead;
+import org.apache.poi.util.LittleEndianInput;
/**
* Tests for {@link AttrPtg}.
*/
public void testReserializeAttrChoose() {
byte[] data = HexRead.readFromString("19, 04, 03, 00, 08, 00, 11, 00, 1A, 00, 23, 00");
- RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(data);
+ LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(data);
Ptg[] ptgs = Ptg.readTokens(data.length, in);
byte[] data2 = new byte[data.length];
try {
0,
};
- FuncPtg ptg = new FuncPtg(TestcaseRecordInputStream.createWithFakeSid(fakeData) );
+ FuncPtg ptg = new FuncPtg(TestcaseRecordInputStream.createLittleEndian(fakeData) );
assertEquals( "Len formula index is not 32(20H)", 0x20, ptg.getFunctionIndex() );
assertEquals( "Number of operands in the len formula", 1, ptg.getNumberOfOperands() );
assertEquals( "Function Name", "LEN", ptg.getName() );
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.util.LittleEndianInput;
/**
* Tests for {@link RefPtg}.
0x2C, 33, 44, 55, 66,
};
public void testReadWrite_tRefN_bug45091() {
- RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(tRefN_data);
+ LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(tRefN_data);
Ptg[] ptgs = Ptg.readTokens(tRefN_data.length, in);
byte[] outData = new byte[5];
Ptg.serializePtgs(ptgs, outData, 0);