mirror of https://github.com/apache/poi.git
Fixed decoding of operand class for ArrayPtg
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@690461 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
55a6277bf2
commit
077c07f988
|
@ -43,58 +43,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|||
public abstract class Ptg implements Cloneable {
|
||||
public static final Ptg[] EMPTY_PTG_ARRAY = { };
|
||||
|
||||
/* convert infix order ptg list to rpn order ptg list
|
||||
* @return List ptgs in RPN order
|
||||
* @param infixPtgs List of ptgs in infix order
|
||||
*/
|
||||
|
||||
/* DO NOT REMOVE
|
||||
*we keep this method in case we wish to change the way we parse
|
||||
*It needs a getPrecedence in OperationsPtg
|
||||
|
||||
public static List ptgsToRpn(List infixPtgs) {
|
||||
java.util.Stack operands = new java.util.Stack();
|
||||
java.util.List retval = new java.util.Stack();
|
||||
|
||||
java.util.ListIterator i = infixPtgs.listIterator();
|
||||
Object p;
|
||||
OperationPtg o ;
|
||||
boolean weHaveABracket = false;
|
||||
while (i.hasNext()) {
|
||||
p=i.next();
|
||||
if (p instanceof OperationPtg) {
|
||||
if (p instanceof ParenthesisPtg) {
|
||||
if (!weHaveABracket) {
|
||||
operands.push(p);
|
||||
weHaveABracket = true;
|
||||
} else {
|
||||
o = (OperationPtg) operands.pop();
|
||||
while (!(o instanceof ParenthesisPtg)) {
|
||||
retval.add(o);
|
||||
}
|
||||
weHaveABracket = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
operands.push(p);
|
||||
}
|
||||
} else {
|
||||
retval.add(p);
|
||||
}
|
||||
}
|
||||
while (!operands.isEmpty()) {
|
||||
if (operands.peek() instanceof ParenthesisPtg ){
|
||||
//throw some error
|
||||
} else {
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reads <tt>size</tt> bytes of the input stream, to create an array of <tt>Ptg</tt>s.
|
||||
|
@ -145,15 +93,15 @@ public abstract class Ptg implements Cloneable {
|
|||
|
||||
Ptg retval = createClassifiedPtg(id, in);
|
||||
|
||||
if (id > 0x60) {
|
||||
if (id >= 0x60) {
|
||||
retval.setClass(CLASS_ARRAY);
|
||||
} else if (id > 0x40) {
|
||||
} else if (id >= 0x40) {
|
||||
retval.setClass(CLASS_VALUE);
|
||||
} else {
|
||||
retval.setClass(CLASS_REF);
|
||||
}
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
private static Ptg createClassifiedPtg(byte id, RecordInputStream in) {
|
||||
|
@ -397,6 +345,22 @@ public abstract class Ptg implements Cloneable {
|
|||
return ptgClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug / diagnostic method to get this token's 'operand class' type.
|
||||
* @return 'R' for 'reference', 'V' for 'value', 'A' for 'array' and '.' for base tokens
|
||||
*/
|
||||
public final char getRVAType() {
|
||||
if (isBaseToken()) {
|
||||
return '.';
|
||||
}
|
||||
switch (ptgClass) {
|
||||
case Ptg.CLASS_REF: return 'R';
|
||||
case Ptg.CLASS_VALUE: return 'V';
|
||||
case Ptg.CLASS_ARRAY: return 'A';
|
||||
}
|
||||
throw new RuntimeException("Unknown operand class (" + ptgClass + ")");
|
||||
}
|
||||
|
||||
public abstract byte getDefaultOperandClass();
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.poi.hssf.record.formula;
|
|||
import java.util.Arrays;
|
||||
|
||||
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.record.UnicodeString;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
@ -128,4 +129,28 @@ public final class TestArrayPtg extends TestCase {
|
|||
}
|
||||
assertEquals("{TRUE,\"ABCD\";\"E\",0.0;FALSE,\"FG\"}", actualFormula);
|
||||
}
|
||||
|
||||
/**
|
||||
* worth checking since AttrPtg.sid=0x20 and Ptg.CLASS_* = (0x00, 0x20, and 0x40)
|
||||
*/
|
||||
public void testOperandClassDecoding() {
|
||||
confirmOperandClassDecoding(Ptg.CLASS_REF);
|
||||
confirmOperandClassDecoding(Ptg.CLASS_VALUE);
|
||||
confirmOperandClassDecoding(Ptg.CLASS_ARRAY);
|
||||
}
|
||||
|
||||
private static void confirmOperandClassDecoding(byte operandClass) {
|
||||
byte[] fullData = new byte[ENCODED_PTG_DATA.length + ENCODED_CONSTANT_DATA.length];
|
||||
System.arraycopy(ENCODED_PTG_DATA, 0, fullData, 0, ENCODED_PTG_DATA.length);
|
||||
System.arraycopy(ENCODED_CONSTANT_DATA, 0, fullData, ENCODED_PTG_DATA.length, ENCODED_CONSTANT_DATA.length);
|
||||
|
||||
// Force encoded operand class for tArray
|
||||
fullData[0] = (byte) (ArrayPtg.sid + operandClass);
|
||||
|
||||
RecordInputStream in = new TestcaseRecordInputStream(ArrayPtg.sid, fullData);
|
||||
|
||||
Ptg[] ptgs = Ptg.readTokens(ENCODED_PTG_DATA.length, in);
|
||||
ArrayPtg aPtg = (ArrayPtg) ptgs[0];
|
||||
assertEquals(operandClass, aPtg.getPtgClass());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue