Chunkpublic class Chunk extends Object Base of all chunks, which hold data, flags etc |
Fields Summary |
---|
private byte[] | contentsThe contents of the chunk, excluding the header,
trailer and separator | private ChunkHeader | header | private ChunkTrailer | trailerMay be null | private ChunkSeparator | separatorMay be null | protected org.apache.poi.hdgf.chunks.ChunkFactory.CommandDefinition[] | commandDefinitionsThe possible different commands we can hold | private Command[] | commandsThe command+value pairs we hold | private String | nameThe name of the chunk, as found from the commandDefinitions | private POILogger | loggerFor logging warnings about the structure of the file |
Constructors Summary |
---|
public Chunk(ChunkHeader header, ChunkTrailer trailer, ChunkSeparator separator, byte[] contents)
this.header = header;
this.trailer = trailer;
this.separator = separator;
this.contents = contents;
|
Methods Summary |
---|
public byte[] | _getContents()
return contents;
| public org.apache.poi.hdgf.chunks.ChunkFactory.CommandDefinition[] | getCommandDefinitions()Gets the command definitions, which define and describe much
of the data held by the chunk.
return commandDefinitions;
| public org.apache.poi.hdgf.chunks.Chunk$Command[] | getCommands()
return commands;
| public org.apache.poi.hdgf.chunks.ChunkHeader | getHeader()
return header;
| public java.lang.String | getName()Get the name of the chunk, as found from the CommandDefinitions
return name;
| public int | getOnDiskSize()Returns the size of the chunk, including any
headers, trailers and separators.
int size = header.getSizeInBytes() + contents.length;
if(trailer != null) {
size += trailer.trailerData.length;
}
if(separator != null) {
size += separator.separatorData.length;
}
return size;
| public org.apache.poi.hdgf.chunks.ChunkSeparator | getSeparator()Gets the separator between this chunk and the next, if it exists
return separator;
| public org.apache.poi.hdgf.chunks.ChunkTrailer | getTrailer()Gets the trailer for this chunk, if it exists
return trailer;
| protected void | processCommands()Uses our CommandDefinitions to process the commands
our chunk type has, and figure out the
values for them.
if(commandDefinitions == null) {
throw new IllegalStateException("You must supply the command definitions before calling processCommands!");
}
// Loop over the definitions, building the commands
// and getting their values
ArrayList commands = new ArrayList();
for(int i=0; i<commandDefinitions.length; i++) {
int type = commandDefinitions[i].getType();
int offset = commandDefinitions[i].getOffset();
// Handle virtual commands
if(type == 10) {
name = commandDefinitions[i].getName();
continue;
} else if(type == 18) {
continue;
}
// Build the appropriate command for the type
Command command;
if(type == 11 || type == 21) {
command = new BlockOffsetCommand(commandDefinitions[i]);
} else {
command = new Command(commandDefinitions[i]);
}
// Bizarely, many of the offsets are from the start of the
// header, not from the start of the chunk body
switch(type) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
case 11: case 21:
case 12: case 16: case 17: case 18: case 28: case 29:
// Offset is from start of chunk
break;
default:
// Offset is from start of header!
if(offset >= 19) {
offset -= 19;
}
}
// Check we seem to have enough data
if(offset >= contents.length) {
logger.log(POILogger.WARN,
"Command offset " + offset + " past end of data at " + contents.length
);
continue;
}
// Process
switch(type) {
// Types 0->7 = a flat at bit 0->7
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
int val = contents[offset] & (1<<type);
command.value = new Boolean( (val > 0) );
break;
case 8:
command.value = new Byte( contents[offset] );
break;
case 9:
command.value = new Double(
LittleEndian.getDouble(contents, offset)
);
break;
case 12:
// A Little Endian String
// Starts 8 bytes into the data segment
// Ends at end of data, or 00 00
int startsAt = 8;
int endsAt = startsAt;
for(int j=startsAt; j<contents.length-1 && endsAt == startsAt; j++) {
if(contents[j] == 0 && contents[j+1] == 0) {
endsAt = j;
}
}
if(endsAt == startsAt) {
endsAt = contents.length;
}
int strLen = (endsAt-startsAt) / 2;
command.value = StringUtil.getFromUnicodeLE(contents, startsAt, strLen);
break;
case 25:
command.value = new Short(
LittleEndian.getShort(contents, offset)
);
break;
case 26:
command.value = new Integer(
LittleEndian.getInt(contents, offset)
);
break;
// Types 11 and 21 hold the offset to the blocks
case 11: case 21:
if(offset < contents.length - 3) {
int bOffset = (int)LittleEndian.getUInt(contents, offset);
BlockOffsetCommand bcmd = (BlockOffsetCommand)command;
bcmd.setOffset(bOffset);
}
break;
default:
logger.log(POILogger.INFO,
"Command of type " + type + " not processed!");
}
// Add to the array
commands.add(command);
}
// Save the commands we liked the look of
this.commands = (Command[])commands.toArray(
new Command[commands.size()] );
// Now build up the blocks, if we had a command that tells
// us where a block is
|
|