EscherArrayPropertypublic class EscherArrayProperty extends EscherComplexProperty Escher array properties are the most wierd construction ever invented
with all sorts of special cases. I'm hopeful I've got them all. |
Fields Summary |
---|
private static final int | FIXED_SIZEThe size of the header that goes at the
start of the array, before the data | private boolean | sizeIncludesHeaderSizeNormally, the size recorded in the simple data (for the complex
data) includes the size of the header.
There are a few cases when it doesn't though... | private boolean | emptyComplexPartWhen reading a property from data stream remeber if the complex part is empty and set this flag. |
Constructors Summary |
---|
public EscherArrayProperty(short id, byte[] complexData)
super( id, checkComplexData(complexData) );
emptyComplexPart = complexData.length == 0;
| public EscherArrayProperty(short propertyNumber, boolean isBlipId, byte[] complexData)
super( propertyNumber, isBlipId, checkComplexData(complexData) );
|
Methods Summary |
---|
private static byte[] | checkComplexData(byte[] complexData)
if (complexData == null || complexData.length == 0)
complexData = new byte[6];
return complexData;
| public static int | getActualSizeOfElements(short sizeOfElements)Sometimes the element size is stored as a negative number. We
negate it and shift it to get the real value.
if (sizeOfElements < 0)
return (short) ( ( -sizeOfElements ) >> 2 );
else
return sizeOfElements;
| public byte[] | getElement(int index)
int actualSize = getActualSizeOfElements(getSizeOfElements());
byte[] result = new byte[actualSize];
System.arraycopy(complexData, FIXED_SIZE + index * actualSize, result, 0, result.length );
return result;
| public int | getNumberOfElementsInArray()
return LittleEndian.getUShort( complexData, 0 );
| public int | getNumberOfElementsInMemory()
return LittleEndian.getUShort( complexData, 2 );
| public short | getSizeOfElements()
return LittleEndian.getShort( complexData, 4 );
| public int | serializeSimplePart(byte[] data, int pos)Serializes the simple part of this property. ie the first 6 bytes.
Needs special code to handle the case when the size doesn't
include the size of the header block
LittleEndian.putShort(data, pos, getId());
int recordSize = complexData.length;
if(!sizeIncludesHeaderSize) {
recordSize -= 6;
}
LittleEndian.putInt(data, pos + 2, recordSize);
return 6;
| public int | setArrayData(byte[] data, int offset)We have this method because the way in which arrays in escher works
is screwed for seemly arbitary reasons. While most properties are
fairly consistent and have a predictable array size, escher arrays
have special cases.
if (emptyComplexPart){
complexData = new byte[0];
} else {
short numElements = LittleEndian.getShort(data, offset);
short numReserved = LittleEndian.getShort(data, offset + 2);
short sizeOfElements = LittleEndian.getShort(data, offset + 4);
int arraySize = getActualSizeOfElements(sizeOfElements) * numElements;
if (arraySize == complexData.length) {
// The stored data size in the simple block excludes the header size
complexData = new byte[arraySize + 6];
sizeIncludesHeaderSize = false;
}
System.arraycopy(data, offset, complexData, 0, complexData.length );
}
return complexData.length;
| public void | setElement(int index, byte[] element)
int actualSize = getActualSizeOfElements(getSizeOfElements());
System.arraycopy( element, 0, complexData, FIXED_SIZE + index * actualSize, actualSize);
| public void | setNumberOfElementsInArray(int numberOfElements)
int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
if ( expectedArraySize != complexData.length )
{
byte[] newArray = new byte[expectedArraySize];
System.arraycopy( complexData, 0, newArray, 0, complexData.length );
complexData = newArray;
}
LittleEndian.putShort( complexData, 0, (short) numberOfElements );
| public void | setNumberOfElementsInMemory(int numberOfElements)
int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
if ( expectedArraySize != complexData.length )
{
byte[] newArray = new byte[expectedArraySize];
System.arraycopy( complexData, 0, newArray, 0, expectedArraySize );
complexData = newArray;
}
LittleEndian.putShort( complexData, 2, (short) numberOfElements );
| public void | setSizeOfElements(int sizeOfElements)
LittleEndian.putShort( complexData, 4, (short) sizeOfElements );
int expectedArraySize = getNumberOfElementsInArray() * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE;
if ( expectedArraySize != complexData.length )
{
// Keep just the first 6 bytes. The rest is no good to us anyway.
byte[] newArray = new byte[expectedArraySize];
System.arraycopy( complexData, 0, newArray, 0, 6 );
complexData = newArray;
}
| public java.lang.String | toString()
String nl = System.getProperty("line.separator");
StringBuffer results = new StringBuffer();
results.append(" {EscherArrayProperty:" + nl);
results.append(" Num Elements: " + getNumberOfElementsInArray() + nl);
results.append(" Num Elements In Memory: " + getNumberOfElementsInMemory() + nl);
results.append(" Size of elements: " + getSizeOfElements() + nl);
for (int i = 0; i < getNumberOfElementsInArray(); i++)
{
results.append(" Element " + i + ": " + HexDump.toHex(getElement(i)) + nl);
}
results.append("}" + nl);
return "propNum: " + getPropertyNumber()
+ ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() )
+ ", complex: " + isComplex()
+ ", blipId: " + isBlipId()
+ ", data: " + nl + results.toString();
|
|