Work in progress - v5 pointer containers

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1766487 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2016-10-25 09:15:02 +00:00
parent 747f5e0f40
commit 3f1965ea27
2 changed files with 53 additions and 8 deletions

View File

@ -17,6 +17,7 @@
package org.apache.poi.hdgf.pointers;
import org.apache.poi.hdgf.streams.PointerContainingStream;
import org.apache.poi.util.LittleEndian;
/**
@ -54,4 +55,41 @@ public final class PointerFactory {
throw new IllegalArgumentException("Visio files with versions below 5 are not supported, yours was " + version);
}
}
/**
* In a {@link PointerContainingStream}, where would the
* number of child pointers be stored for this kind of Pointer?
*/
public int identifyNumPointersOffset(Pointer pointer, byte[] data) {
if (pointer instanceof PointerV6) {
// V6 stores it as the first value in the stream
return (int)LittleEndian.getUInt(data, 0);
} else if (pointer instanceof PointerV5) {
// V5 uses fixed offsets
switch (pointer.type) {
case 0x1d:
case 0x4e:
return 0x24-6;
case 0x1e:
return 0x3c-6;
case 0x14:
return 0x88-6;
}
return 10;
} else {
throw new IllegalArgumentException("Unsupported Pointer type " + pointer);
}
}
public int identifyNumPointers(Pointer pointer, int offset, byte[] data) {
if (pointer instanceof PointerV6) {
// V6 stores it a 32 bit number at the offset
return (int)LittleEndian.getUInt(data, offset);
} else if (pointer instanceof PointerV5) {
// V5 stores it as a 16 bit number at the offset
return LittleEndian.getShort(data, offset);
} else {
throw new IllegalArgumentException("Unsupported Pointer type " + pointer);
}
}
}

View File

@ -20,6 +20,7 @@ package org.apache.poi.hdgf.streams;
import org.apache.poi.hdgf.chunks.ChunkFactory;
import org.apache.poi.hdgf.pointers.Pointer;
import org.apache.poi.hdgf.pointers.PointerFactory;
import org.apache.poi.hdgf.pointers.PointerV6;
import org.apache.poi.util.LittleEndian;
/**
@ -40,20 +41,26 @@ public class PointerContainingStream extends Stream { // TODO - instantiable sup
this.pointerFactory = pointerFactory;
// Find the offset to the number of child pointers we have
// This ought to be the first thing stored in us
numPointersLocalOffset = (int)LittleEndian.getUInt(
store.getContents(), 0
numPointersLocalOffset = pointerFactory.identifyNumPointersOffset(
pointer, store.getContents()
);
// Generate the objects for the pointers we contain
int numPointers = (int)LittleEndian.getUInt(
store.getContents(), numPointersLocalOffset
int numPointers = pointerFactory.identifyNumPointers(
pointer, numPointersLocalOffset, store.getContents()
);
childPointers = new Pointer[numPointers];
// Prepare to read the children
int pos = numPointersLocalOffset;
// After the number of pointers is another (unknown)
// 4 byte value
int pos = numPointersLocalOffset + 4 + 4;
// v5 only has another (unknown) 4 byte value
// TODO Should this logic go into PointerFactory?
if (pointer instanceof PointerV6) {
pos += 4 + 4;
} else {
pos += 2;
}
// Now create the pointer objects
for(int i=0; i<numPointers; i++) {