in poi-scratchpad/src/main/java/org/apache/poi/hdgf/chunks/Chunk.java [138:261]
void processCommands() {
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<Command> commandList = new ArrayList<>();
for(CommandDefinition cdef : commandDefinitions) {
int type = cdef.getType();
int offset = cdef.getOffset();
// Handle virtual commands
if(type == 10) {
name = cdef.getName();
continue;
} else if(type == 18) {
continue;
}
// Build the appropriate command for the type
Command command;
if(type == 11 || type == 21) {
command = new BlockOffsetCommand(cdef);
} else {
command = new Command(cdef);
}
// Bizarrely, 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 28: case 29:
// Offset is from start of chunk (case 18 has been taken care of above)
break;
default:
// Offset is from start of header!
if(offset >= 19) {
offset -= 19;
}
}
// Check we seem to have enough data
if(offset >= contents.length) {
LOG.atWarn().log("Command offset {} past end of data at {}", box(offset),box(contents.length));
continue;
}
try {
// Process
switch(type) {
// Types 0->7 = a flag at bit 0->7
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
command.value = ((contents[offset] >>> type) & 1) == 1;
break;
case 8:
command.value = contents[offset];
break;
case 9:
command.value = 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
// Ensure we have enough data
if(contents.length < 8) {
command.value = "";
break;
}
// Find the end point
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;
command.value = new String(contents, startsAt, strLen, header.getChunkCharset());
break;
case 25:
command.value = LittleEndian.getShort(contents, offset);
break;
case 26:
command.value = 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:
LOG.atInfo().log("Command of type {} not processed!", box(type));
}
}
catch (Exception e) {
LOG.atError().withThrowable(e).log("Unexpected error processing command, ignoring and continuing. Command: {}", command);
}
// Add to the array
commandList.add(command);
}
// Save the commands we liked the look of
this.commands = commandList.toArray(
new Command[0]);
// Now build up the blocks, if we had a command that tells
// us where a block is
}