* blocks elsewhere in the file
*/
public abstract class Pointer {
- protected int type;
- protected int address;
- protected int offset;
- protected int length;
- protected short format;
+ protected int type;
+ protected int address;
+ protected int offset;
+ protected int length;
+ protected short format;
- public int getAddress() {
- return address;
- }
- public short getFormat() {
- return format;
- }
- public int getLength() {
- return length;
- }
- public int getOffset() {
- return offset;
- }
- public int getType() {
- return type;
- }
+ public int getAddress() {
+ return address;
+ }
+ public short getFormat() {
+ return format;
+ }
+ public int getLength() {
+ return length;
+ }
+ public int getOffset() {
+ return offset;
+ }
+ public int getType() {
+ return type;
+ }
- 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 destinationHasPointers();
- public abstract boolean destinationHasChunks();
- public abstract boolean destinationCompressed();
+ 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 destinationHasPointers();
+ public abstract boolean destinationHasChunks();
+ public abstract boolean destinationCompressed();
}
* of the file
*/
public final class PointerFactory {
- private int version;
- public PointerFactory(int version) {
- this.version = version;
- }
- public int getVersion() { return version; }
+ private int version;
+ public PointerFactory(int version) {
+ this.version = version;
+ }
+ public int getVersion() { return version; }
- /**
- * Creates a single Pointer from the data at the given offset
- */
- public Pointer createPointer(byte[] data, int offset) {
- Pointer p;
- if(version >= 6) {
- p = new PointerV6();
- p.type = LittleEndian.getInt(data, offset+0);
- p.address = (int)LittleEndian.getUInt(data, offset+4);
- p.offset = (int)LittleEndian.getUInt(data, offset+8);
- p.length = (int)LittleEndian.getUInt(data, offset+12);
- p.format = LittleEndian.getShort(data, offset+16);
+ /**
+ * Creates a single Pointer from the data at the given offset
+ */
+ public Pointer createPointer(byte[] data, int offset) {
+ Pointer p;
+ if(version >= 6) {
+ p = new PointerV6();
+ p.type = LittleEndian.getInt(data, offset+0);
+ p.address = (int)LittleEndian.getUInt(data, offset+4);
+ p.offset = (int)LittleEndian.getUInt(data, offset+8);
+ p.length = (int)LittleEndian.getUInt(data, offset+12);
+ p.format = LittleEndian.getShort(data, offset+16);
- return p;
- } else if(version == 5) {
+ return p;
+ } else if(version == 5) {
p = new PointerV5();
p.type = LittleEndian.getShort(data, offset+0);
p.format = LittleEndian.getShort(data, offset+2);
p.length = (int)LittleEndian.getUInt(data, offset+12);
return p;
- } else {
- throw new IllegalArgumentException("Visio files with versions below 5 are not supported, yours was " + version);
- }
- }
-
- /**
- * Parsers the {@link PointerContainingStream} contents and
- * creates all the child Pointers for it
- */
- public Pointer[] createContainerPointers(Pointer parent, byte[] data) {
- // Where in the stream does the "number of pointers" offset live?
- int numPointersOffset = parent.getNumPointersOffset(data);
- // How many do we have?
- int numPointers = parent.getNumPointers(numPointersOffset, data);
- // How much to skip for the num pointers + any extra data?
- int skip = parent.getPostNumPointersSkip();
-
- // Create
- int pos = numPointersOffset + skip;
- Pointer[] childPointers = new Pointer[numPointers];
+ } else {
+ throw new IllegalArgumentException("Visio files with versions below 5 are not supported, yours was " + version);
+ }
+ }
+
+ /**
+ * Parsers the {@link PointerContainingStream} contents and
+ * creates all the child Pointers for it
+ */
+ public Pointer[] createContainerPointers(Pointer parent, byte[] data) {
+ // Where in the stream does the "number of pointers" offset live?
+ int numPointersOffset = parent.getNumPointersOffset(data);
+ // How many do we have?
+ int numPointers = parent.getNumPointers(numPointersOffset, data);
+ // How much to skip for the num pointers + any extra data?
+ int skip = parent.getPostNumPointersSkip();
+
+ // Create
+ int pos = numPointersOffset + skip;
+ Pointer[] childPointers = new Pointer[numPointers];
for(int i=0; i<numPointers; i++) {
childPointers[i] = this.createPointer(data, pos);
pos += childPointers[i].getSizeInBytes();
}
-
+
return childPointers;
- }
+ }
}
*/
public final class PointerV5 extends Pointer {
// TODO Are these getters correct?
- public boolean destinationHasStrings() {
- return (0x40 <= format && format < 0x50);
- }
- public boolean destinationHasPointers() {
- if(type == 20) return true;
- if(format == 0x1d || format == 0x1e) return true;
- return (0x50 <= format && format < 0x60);
- }
- public boolean destinationHasChunks() {
- return (0xd0 <= format && format < 0xdf);
- }
+ public boolean destinationHasStrings() {
+ return (0x40 <= format && format < 0x50);
+ }
+ public boolean destinationHasPointers() {
+ if(type == 20) return true;
+ if(format == 0x1d || format == 0x1e) return true;
+ return (0x50 <= format && format < 0x60);
+ }
+ public boolean destinationHasChunks() {
+ return (0xd0 <= format && format < 0xdf);
+ }
- public boolean destinationCompressed() {
- // Apparently, it's the second least significant bit
- return (format & 2) > 0;
- }
+ public boolean destinationCompressed() {
+ // Apparently, it's the second least significant bit
+ return (format & 2) > 0;
+ }
- /**
- * With v6 pointers, the on-disk size is 16 bytes
- */
- public int getSizeInBytes() { return 16; }
-
- /**
- * Depends on the type only, not stored
- */
+ /**
+ * With v6 pointers, the on-disk size is 16 bytes
+ */
+ 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;
+ return 30;
case 0x1e:
- return 0x3c-6;
+ return 54;
case 0x14:
- return 0x88-6;
- }
- return 10;
+ return 130;
+ }
+ return 10;
}
/**
* 16 bit int at the given offset
* A Pointer from v6+
*/
public final class PointerV6 extends Pointer {
- public boolean destinationHasStrings() {
- return (0x40 <= format && format < 0x50);
- }
- public boolean destinationHasPointers() {
- if(type == 20) return true;
- if(format == 0x1d || format == 0x1e) return true;
- return (0x50 <= format && format < 0x60);
- }
- public boolean destinationHasChunks() {
- return (0xd0 <= format && format < 0xdf);
- }
+ public boolean destinationHasStrings() {
+ return (0x40 <= format && format < 0x50);
+ }
+ public boolean destinationHasPointers() {
+ if(type == 20) return true;
+ if(format == 0x1d || format == 0x1e) return true;
+ return (0x50 <= format && format < 0x60);
+ }
+ public boolean destinationHasChunks() {
+ return (0xd0 <= format && format < 0xdf);
+ }
- public boolean destinationCompressed() {
- // Apparently, it's the second least significant bit
- return (format & 2) > 0;
- }
+ public boolean destinationCompressed() {
+ // Apparently, it's the second least significant bit
+ return (format & 2) > 0;
+ }
- /**
- * With v6 pointers, the on-disk size is 18 bytes
- */
- public int getSizeInBytes() { return 18; }
-
- /**
- * Stored within the data
- */
+ /**
+ * With v6 pointers, the on-disk size is 18 bytes
+ */
+ public int getSizeInBytes() { return 18; }
+
+ /**
+ * Stored within the data
+ */
public int getNumPointersOffset(byte[] data) {
return getNumPointersOffsetV6(data);
}
import junit.framework.TestCase;
public abstract class StreamTest extends TestCase {
- public static class TestPointer extends Pointer {
- private final boolean compressed;
- protected boolean hasPointers = false;
- public TestPointer(boolean compressed, int offset, int length, int type, short format) {
- this.compressed = compressed;
- this.offset = offset;
- this.length = length;
- this.type = type;
- this.format = format;
- }
-
- @Override
+ public static class TestPointer extends Pointer {
+ private final boolean compressed;
+ protected boolean hasPointers = false;
+ public TestPointer(boolean compressed, int offset, int length, int type, short format) {
+ this.compressed = compressed;
+ this.offset = offset;
+ this.length = length;
+ this.type = type;
+ this.format = format;
+ }
+
+ @Override
public boolean destinationCompressed() { return compressed; }
- @Override
+ @Override
public boolean destinationHasChunks() { return false; }
- @Override
+ @Override
public boolean destinationHasPointers() { return hasPointers; }
- @Override
+ @Override
public boolean destinationHasStrings() { return false; }
-
- @Override
+
+ @Override
public int getSizeInBytes() { return -1; }
- @Override
+ @Override
public int getNumPointersOffset(byte[] data) {
- return getNumPointersOffsetV6(data);
- }
+ return getNumPointersOffsetV6(data);
+ }
@Override
public int getNumPointers(int offset, byte[] data) {
return getNumPointersV6(offset, data);
public int getPostNumPointersSkip() {
return getPostNumPointersSkipV6();
}
- }
+ }
}