diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java index 3af4991d4..e16ae178e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -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 size bytes of the input stream, to create an array of Ptgs. @@ -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) { @@ -396,6 +344,22 @@ public abstract class Ptg implements Cloneable { public final byte getPtgClass() { 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(); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java index 2906f5e02..9e5a34004 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java @@ -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()); + } }