refactor SprmOperation, reducing memory consumption for a bit

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1145279 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-07-11 18:38:03 +00:00
parent 0c281fd3f7
commit f24c96d0b7
1 changed files with 139 additions and 120 deletions

View File

@ -24,142 +24,161 @@ import org.apache.poi.util.LittleEndian;
/**
* This class is used to represent a sprm operation from a Word 97/2000/XP
* document.
*
* @author Ryan Ackley
* @version 1.0
*/
public final class SprmOperation
{
final static private BitField OP_BITFIELD = BitFieldFactory.getInstance(0x1ff);
final static private BitField SPECIAL_BITFIELD = BitFieldFactory.getInstance(0x200);
final static private BitField TYPE_BITFIELD = BitFieldFactory.getInstance(0x1c00);
final static private BitField SIZECODE_BITFIELD = BitFieldFactory.getInstance(0xe000);
private static final BitField BITFIELD_OP = BitFieldFactory
.getInstance( 0x1ff );
private static final BitField BITFIELD_SIZECODE = BitFieldFactory
.getInstance( 0xe000 );
private static final BitField BITFIELD_SPECIAL = BitFieldFactory
.getInstance( 0x200 );
private static final BitField BITFIELD_TYPE = BitFieldFactory
.getInstance( 0x1c00 );
final static private short LONG_SPRM_TABLE = (short)0xd608;
final static private short LONG_SPRM_PARAGRAPH = (short)0xc615;
final static private short SPRM_LONG_PARAGRAPH = (short) 0xc615;
final static private short SPRM_LONG_TABLE = (short) 0xd608;
final static public int PAP_TYPE = 1;
final static public int TAP_TYPE = 5;
public static final int TYPE_PAP = 1;
public static final int TYPE_TAP = 5;
private short _value;
private int _type;
private int _operation;
private int _gOffset;
private byte[] _grpprl;
private int _sizeCode;
private int _size;
@Deprecated
final static public int PAP_TYPE = TYPE_PAP;
@Deprecated
final static public int TAP_TYPE = TYPE_TAP;
public SprmOperation(byte[] grpprl, int offset)
{
_grpprl = grpprl;
_value = LittleEndian.getShort(grpprl, offset);
_gOffset = offset + 2;
_operation = OP_BITFIELD.getValue(_value);
_type = TYPE_BITFIELD.getValue(_value);
_sizeCode = SIZECODE_BITFIELD.getValue(_value);
_size = initSize(_value);
}
public static int getOperationFromOpcode(short opcode)
{
return OP_BITFIELD.getValue(opcode);
}
public static int getTypeFromOpcode(short opcode)
{
return TYPE_BITFIELD.getValue(opcode);
}
public int getType()
{
return _type;
}
public int getOperation()
{
return _operation;
}
public int getGrpprlOffset()
{
return _gOffset;
}
public int getOperand()
{
switch (_sizeCode)
public static int getOperationFromOpcode( short opcode )
{
case 0:
case 1:
return _grpprl[_gOffset];
case 2:
case 4:
case 5:
return LittleEndian.getShort(_grpprl, _gOffset);
case 3:
return LittleEndian.getInt(_grpprl, _gOffset);
case 6:
byte operandLength = _grpprl[_gOffset + 1]; //surely shorter than an int...
byte [] codeBytes = new byte[LittleEndian.INT_SIZE]; //initialized to zeros by JVM
for(int i = 0; i < operandLength; i++)
if(_gOffset + i < _grpprl.length)
codeBytes[i] = _grpprl[_gOffset + 1 + i];
return LittleEndian.getInt(codeBytes, 0);
case 7:
byte threeByteInt[] = new byte[4];
threeByteInt[0] = _grpprl[_gOffset];
threeByteInt[1] = _grpprl[_gOffset + 1];
threeByteInt[2] = _grpprl[_gOffset + 2];
threeByteInt[3] = (byte)0;
return LittleEndian.getInt(threeByteInt, 0);
default:
throw new IllegalArgumentException("SPRM contains an invalid size code");
return BITFIELD_OP.getValue( opcode );
}
}
public int getSizeCode()
{
return _sizeCode;
}
public int size()
{
return _size;
}
public byte[] getGrpprl()
{
return _grpprl;
}
private int initSize(short sprm)
{
switch (_sizeCode)
public static int getTypeFromOpcode( short opcode )
{
case 0:
case 1:
return 3;
case 2:
case 4:
case 5:
return 4;
case 3:
return 6;
case 6:
if (sprm == LONG_SPRM_TABLE || sprm == LONG_SPRM_PARAGRAPH)
return BITFIELD_TYPE.getValue( opcode );
}
private int _offset;
private int _gOffset;
private byte[] _grpprl;
private int _size;
private short _value;
public SprmOperation( byte[] grpprl, int offset )
{
_grpprl = grpprl;
_value = LittleEndian.getShort( grpprl, offset );
_offset = offset;
_gOffset = offset + 2;
_size = initSize( _value );
}
public byte[] toByteArray()
{
byte[] result = new byte[size()];
System.arraycopy( _grpprl, _offset, result, 0, size() );
return result;
}
public byte[] getGrpprl()
{
return _grpprl;
}
public int getGrpprlOffset()
{
return _gOffset;
}
public int getOperand()
{
switch ( getSizeCode() )
{
int retVal = (0x0000ffff & LittleEndian.getShort(_grpprl, _gOffset)) + 3;
_gOffset += 2;
return retVal;
case 0:
case 1:
return _grpprl[_gOffset];
case 2:
case 4:
case 5:
return LittleEndian.getShort( _grpprl, _gOffset );
case 3:
return LittleEndian.getInt( _grpprl, _gOffset );
case 6:
// surely shorter than an int...
byte operandLength = _grpprl[_gOffset + 1];
// initialized to zeros by JVM
byte[] codeBytes = new byte[LittleEndian.INT_SIZE];
for ( int i = 0; i < operandLength; i++ )
if ( _gOffset + i < _grpprl.length )
codeBytes[i] = _grpprl[_gOffset + 1 + i];
return LittleEndian.getInt( codeBytes, 0 );
case 7:
byte threeByteInt[] = new byte[4];
threeByteInt[0] = _grpprl[_gOffset];
threeByteInt[1] = _grpprl[_gOffset + 1];
threeByteInt[2] = _grpprl[_gOffset + 2];
threeByteInt[3] = (byte) 0;
return LittleEndian.getInt( threeByteInt, 0 );
default:
throw new IllegalArgumentException(
"SPRM contains an invalid size code" );
}
return (0x000000ff & _grpprl[_gOffset++]) + 3;
case 7:
return 5;
default:
throw new IllegalArgumentException("SPRM contains an invalid size code");
}
}
public int getOperation()
{
return BITFIELD_OP.getValue( _value );
}
public int getSizeCode()
{
return BITFIELD_SIZECODE.getValue( _value );
}
public int getType()
{
return BITFIELD_TYPE.getValue( _value );
}
private int initSize( short sprm )
{
switch ( getSizeCode() )
{
case 0:
case 1:
return 3;
case 2:
case 4:
case 5:
return 4;
case 3:
return 6;
case 6:
int offset = _gOffset;
if ( sprm == SPRM_LONG_TABLE || sprm == SPRM_LONG_PARAGRAPH )
{
int retVal = ( 0x0000ffff & LittleEndian.getShort( _grpprl,
offset ) ) + 3;
_gOffset += 2;
return retVal;
}
return ( 0x000000ff & _grpprl[_gOffset++] ) + 3;
case 7:
return 5;
default:
throw new IllegalArgumentException(
"SPRM contains an invalid size code" );
}
}
public int size()
{
return _size;
}
@Override
public String toString()