Refactor child pointer logic to the factory
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1766492 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3f1965ea27
commit
6816899106
@ -45,6 +45,10 @@ public abstract class Pointer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract int getSizeInBytes();
|
public abstract int getSizeInBytes();
|
||||||
|
public abstract int getNumPointersOffset(byte[] data);
|
||||||
|
public abstract int getNumPointers(int offset, byte[] data);
|
||||||
|
public abstract int getPostNumPointersSkip();
|
||||||
|
|
||||||
public abstract boolean destinationHasStrings();
|
public abstract boolean destinationHasStrings();
|
||||||
public abstract boolean destinationHasPointers();
|
public abstract boolean destinationHasPointers();
|
||||||
public abstract boolean destinationHasChunks();
|
public abstract boolean destinationHasChunks();
|
||||||
|
@ -31,6 +31,9 @@ public final class PointerFactory {
|
|||||||
}
|
}
|
||||||
public int getVersion() { return version; }
|
public int getVersion() { return version; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a single Pointer from the data at the given offset
|
||||||
|
*/
|
||||||
public Pointer createPointer(byte[] data, int offset) {
|
public Pointer createPointer(byte[] data, int offset) {
|
||||||
Pointer p;
|
Pointer p;
|
||||||
if(version >= 6) {
|
if(version >= 6) {
|
||||||
@ -57,39 +60,25 @@ public final class PointerFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In a {@link PointerContainingStream}, where would the
|
* Parsers the {@link PointerContainingStream} contents and
|
||||||
* number of child pointers be stored for this kind of Pointer?
|
* creates all the child Pointers for it
|
||||||
*/
|
*/
|
||||||
public int identifyNumPointersOffset(Pointer pointer, byte[] data) {
|
public Pointer[] createContainerPointers(Pointer parent, byte[] data) {
|
||||||
if (pointer instanceof PointerV6) {
|
// Where in the stream does the "number of pointers" offset live?
|
||||||
// V6 stores it as the first value in the stream
|
int numPointersOffset = parent.getNumPointersOffset(data);
|
||||||
return (int)LittleEndian.getUInt(data, 0);
|
// How many do we have?
|
||||||
} else if (pointer instanceof PointerV5) {
|
int numPointers = parent.getNumPointers(numPointersOffset, data);
|
||||||
// V5 uses fixed offsets
|
// How much to skip for the num pointers + any extra data?
|
||||||
switch (pointer.type) {
|
int skip = parent.getPostNumPointersSkip();
|
||||||
case 0x1d:
|
|
||||||
case 0x4e:
|
// Create
|
||||||
return 0x24-6;
|
int pos = numPointersOffset + skip;
|
||||||
case 0x1e:
|
Pointer[] childPointers = new Pointer[numPointers];
|
||||||
return 0x3c-6;
|
for(int i=0; i<numPointers; i++) {
|
||||||
case 0x14:
|
childPointers[i] = this.createPointer(data, pos);
|
||||||
return 0x88-6;
|
pos += childPointers[i].getSizeInBytes();
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return childPointers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.hdgf.pointers;
|
package org.apache.poi.hdgf.pointers;
|
||||||
|
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Pointer from v5
|
* A Pointer from v5
|
||||||
*/
|
*/
|
||||||
@ -43,4 +45,33 @@ public final class PointerV5 extends Pointer {
|
|||||||
* With v6 pointers, the on-disk size is 16 bytes
|
* With v6 pointers, the on-disk size is 16 bytes
|
||||||
*/
|
*/
|
||||||
public int getSizeInBytes() { return 16; }
|
public int getSizeInBytes() { return 16; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depends on the type only, not stored
|
||||||
|
*/
|
||||||
|
public int getNumPointersOffset(byte[] data) {
|
||||||
|
switch (type) {
|
||||||
|
case 0x1d:
|
||||||
|
case 0x4e:
|
||||||
|
return 0x24-6;
|
||||||
|
case 0x1e:
|
||||||
|
return 0x3c-6;
|
||||||
|
case 0x14:
|
||||||
|
return 0x88-6;
|
||||||
|
}
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 16 bit int at the given offset
|
||||||
|
*/
|
||||||
|
public int getNumPointers(int offset, byte[] data) {
|
||||||
|
// V5 stores it as a 16 bit number at the offset
|
||||||
|
return LittleEndian.getShort(data, offset);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Just the 2 bytes of the number of pointers
|
||||||
|
*/
|
||||||
|
public int getPostNumPointersSkip() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.hdgf.pointers;
|
package org.apache.poi.hdgf.pointers;
|
||||||
|
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Pointer from v6+
|
* A Pointer from v6+
|
||||||
*/
|
*/
|
||||||
@ -42,4 +44,34 @@ public final class PointerV6 extends Pointer {
|
|||||||
* With v6 pointers, the on-disk size is 18 bytes
|
* With v6 pointers, the on-disk size is 18 bytes
|
||||||
*/
|
*/
|
||||||
public int getSizeInBytes() { return 18; }
|
public int getSizeInBytes() { return 18; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stored within the data
|
||||||
|
*/
|
||||||
|
public int getNumPointersOffset(byte[] data) {
|
||||||
|
return getNumPointersOffsetV6(data);
|
||||||
|
}
|
||||||
|
public static int getNumPointersOffsetV6(byte[] data) {
|
||||||
|
// V6 stores it as the first value in the stream
|
||||||
|
return (int)LittleEndian.getUInt(data, 0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 32 bit int at the given offset
|
||||||
|
*/
|
||||||
|
public int getNumPointers(int offset, byte[] data) {
|
||||||
|
return getNumPointersV6(offset, data);
|
||||||
|
}
|
||||||
|
public static int getNumPointersV6(int offset, byte[] data) {
|
||||||
|
// V6 stores it a 32 bit number at the offset
|
||||||
|
return (int)LittleEndian.getUInt(data, offset);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 4 bytes of the number, and 4 more unknown bytes
|
||||||
|
*/
|
||||||
|
public int getPostNumPointersSkip() {
|
||||||
|
return getPostNumPointersSkipV6();
|
||||||
|
}
|
||||||
|
public static int getPostNumPointersSkipV6() {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ package org.apache.poi.hdgf.streams;
|
|||||||
import org.apache.poi.hdgf.chunks.ChunkFactory;
|
import org.apache.poi.hdgf.chunks.ChunkFactory;
|
||||||
import org.apache.poi.hdgf.pointers.Pointer;
|
import org.apache.poi.hdgf.pointers.Pointer;
|
||||||
import org.apache.poi.hdgf.pointers.PointerFactory;
|
import org.apache.poi.hdgf.pointers.PointerFactory;
|
||||||
import org.apache.poi.hdgf.pointers.PointerV6;
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stream that holds pointers, possibly in addition to some
|
* A stream that holds pointers, possibly in addition to some
|
||||||
@ -33,42 +31,14 @@ public class PointerContainingStream extends Stream { // TODO - instantiable sup
|
|||||||
|
|
||||||
private ChunkFactory chunkFactory;
|
private ChunkFactory chunkFactory;
|
||||||
private PointerFactory pointerFactory;
|
private PointerFactory pointerFactory;
|
||||||
private int numPointersLocalOffset;
|
|
||||||
|
|
||||||
protected PointerContainingStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) {
|
protected PointerContainingStream(Pointer pointer, StreamStore store, ChunkFactory chunkFactory, PointerFactory pointerFactory) {
|
||||||
super(pointer, store);
|
super(pointer, store);
|
||||||
this.chunkFactory = chunkFactory;
|
this.chunkFactory = chunkFactory;
|
||||||
this.pointerFactory = pointerFactory;
|
this.pointerFactory = pointerFactory;
|
||||||
|
|
||||||
// Find the offset to the number of child pointers we have
|
|
||||||
numPointersLocalOffset = pointerFactory.identifyNumPointersOffset(
|
|
||||||
pointer, store.getContents()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate the objects for the pointers we contain
|
|
||||||
int numPointers = pointerFactory.identifyNumPointers(
|
|
||||||
pointer, numPointersLocalOffset, store.getContents()
|
|
||||||
);
|
|
||||||
childPointers = new Pointer[numPointers];
|
|
||||||
|
|
||||||
// Prepare to read the children
|
// Have the child pointers identified and created
|
||||||
int pos = numPointersLocalOffset;
|
childPointers = pointerFactory.createContainerPointers(pointer, store.getContents());
|
||||||
|
|
||||||
// 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++) {
|
|
||||||
childPointers[i] = pointerFactory.createPointer(
|
|
||||||
store.getContents(), pos
|
|
||||||
);
|
|
||||||
pos += childPointers[i].getSizeInBytes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package org.apache.poi.hdgf.streams;
|
package org.apache.poi.hdgf.streams;
|
||||||
|
|
||||||
import org.apache.poi.hdgf.pointers.Pointer;
|
import org.apache.poi.hdgf.pointers.Pointer;
|
||||||
|
import static org.apache.poi.hdgf.pointers.PointerV6.*;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
@ -41,7 +42,20 @@ public abstract class StreamTest extends TestCase {
|
|||||||
public boolean destinationHasPointers() { return hasPointers; }
|
public boolean destinationHasPointers() { return hasPointers; }
|
||||||
@Override
|
@Override
|
||||||
public boolean destinationHasStrings() { return false; }
|
public boolean destinationHasStrings() { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSizeInBytes() { return -1; }
|
public int getSizeInBytes() { return -1; }
|
||||||
|
@Override
|
||||||
|
public int getNumPointersOffset(byte[] data) {
|
||||||
|
return getNumPointersOffsetV6(data);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getNumPointers(int offset, byte[] data) {
|
||||||
|
return getNumPointersV6(offset, data);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getPostNumPointersSkip() {
|
||||||
|
return getPostNumPointersSkipV6();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user