patchDelta function
Implementation
Uint8List patchDelta(Uint8List base, Uint8List delta) {
var copyLength = 0;
var rvOffset = 0;
var header = DeltaHeader.decode(delta);
var offset = header.offset;
// assert the size of the base buffer
if (header.baseBufferSize != base.length) {
throw Exception('Invalid base buffer length in header');
}
// pre allocate buffer to hold the results
var rv = Uint8List(header.targetBufferSize);
// start patching
while (offset < delta.length) {
var opcode = delta[offset++];
if (_isCopyFromSrc(opcode)) {
// copy instruction (copy bytes from base buffer to target buffer)
var baseOffset = 0;
copyLength = 0;
// the state of the next bits will tell us information we need
// to perform the copy
// first we get the offset in the source buffer where
// the copy will start
if (opcode & 0x01 != 0) baseOffset = delta[offset++];
if (opcode & 0x02 != 0) baseOffset |= delta[offset++] << 8;
if (opcode & 0x04 != 0) baseOffset |= delta[offset++] << 16;
if (opcode & 0x08 != 0) baseOffset |= delta[offset++] << 24;
// now the amount of bytes to copy
if (opcode & 0x10 != 0) copyLength = delta[offset++];
if (opcode & 0x20 != 0) copyLength |= delta[offset++] << 8;
if (opcode & 0x40 != 0) copyLength |= delta[offset++] << 16;
if (copyLength == 0) copyLength = 0x10000;
// copy the data
var replacement = base.getRange(baseOffset, baseOffset + copyLength);
_replaceRange(rv, rvOffset, replacement);
} else if (_isCopyFromDelta(opcode)) {
// insert instruction (copy bytes from delta buffer to target buffer)
// amount to copy is specified by the opcode itself
copyLength = opcode;
assert(offset + copyLength <= delta.length);
assert(rvOffset + copyLength <= rv.length);
var replacement = delta.getRange(offset, offset + copyLength);
_replaceRange(rv, rvOffset, replacement);
offset += copyLength;
} else {
throw Exception('Invalid delta opcode');
}
// advance target position
rvOffset += copyLength;
}
// assert the size of the target buffer
if (rvOffset != rv.length) {
throw Exception('Error patching the base buffer');
}
return rv;
}