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:
Josh Micich 2008-08-30 04:34:01 +00:00
parent 55a6277bf2
commit 077c07f988
2 changed files with 44 additions and 55 deletions

View File

@ -43,58 +43,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public abstract class Ptg implements Cloneable { public abstract class Ptg implements Cloneable {
public static final Ptg[] EMPTY_PTG_ARRAY = { }; 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. * 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); Ptg retval = createClassifiedPtg(id, in);
if (id > 0x60) { if (id >= 0x60) {
retval.setClass(CLASS_ARRAY); retval.setClass(CLASS_ARRAY);
} else if (id > 0x40) { } else if (id >= 0x40) {
retval.setClass(CLASS_VALUE); retval.setClass(CLASS_VALUE);
} else { } else {
retval.setClass(CLASS_REF); retval.setClass(CLASS_REF);
} }
return retval; return retval;
} }
private static Ptg createClassifiedPtg(byte id, RecordInputStream in) { private static Ptg createClassifiedPtg(byte id, RecordInputStream in) {
@ -397,6 +345,22 @@ public abstract class Ptg implements Cloneable {
return ptgClass; 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(); public abstract byte getDefaultOperandClass();
/** /**

View File

@ -20,6 +20,7 @@ package org.apache.poi.hssf.record.formula;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.hssf.HSSFTestDataSamples; 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.TestcaseRecordInputStream;
import org.apache.poi.hssf.record.UnicodeString; import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; 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); 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());
}
} }