Index: courgette/third_party/bsdiff_create.cc |
=================================================================== |
--- courgette/third_party/bsdiff_create.cc (revision 16336) |
+++ courgette/third_party/bsdiff_create.cc (working copy) |
@@ -42,7 +42,7 @@ |
// |
// The code appears to be a rewritten version of the suffix array algorithm |
// presented in "Faster Suffix Sorting" by N. Jesper Larsson and Kunihiko |
-// Sadakane, special-cased for bytes. |
+// Sadakane, special cased for bytes. |
static void |
split(int *I,int *V,int start,int len,int h) |
@@ -191,9 +191,6 @@ |
stream->WriteVarint32(header->slen); |
stream->WriteVarint32(header->scrc32); |
stream->WriteVarint32(header->dlen); |
- stream->WriteVarint32(header->cblen); |
- stream->WriteVarint32(header->difflen); |
- stream->WriteVarint32(header->extralen); |
} |
BSDiffStatus CreateBinaryPatch(SourceStream* old_stream, |
@@ -204,9 +201,19 @@ |
LOG(INFO) << "Start bsdiff"; |
size_t initial_patch_stream_length = patch_stream->Length(); |
+ SinkStreamSet patch_streams; |
+ SinkStream* control_stream_copy_counts = patch_streams.stream(0); |
+ SinkStream* control_stream_extra_counts = patch_streams.stream(1); |
+ SinkStream* control_stream_seeks = patch_streams.stream(2); |
+ SinkStream* diff_skips = patch_streams.stream(3); |
+ SinkStream* diff_bytes = patch_streams.stream(4); |
+ SinkStream* extra_bytes = patch_streams.stream(5); |
+ |
const uint8* old = old_stream->Buffer(); |
const int oldsize = old_stream->Remaining(); |
+ uint32 pending_diff_zeros = 0; |
+ |
scoped_array<int> I(new(std::nothrow) int[oldsize + 1]); |
scoped_array<int> V(new(std::nothrow) int[oldsize + 1]); |
if (I == NULL || V == NULL) |
@@ -221,24 +228,12 @@ |
const uint8* newbuf = new_stream->Buffer(); |
const int newsize = new_stream->Remaining(); |
- // Allocate newsize+1 bytes instead of newsize bytes to ensure that we never |
- // try to malloc(0) and get a NULL pointer. |
- |
- scoped_array<uint8> diff_bytes_array(new(std::nothrow) uint8[newsize + 1]); |
- scoped_array<uint8> extra_bytes_array(new(std::nothrow) uint8[newsize + 1]); |
- if (diff_bytes_array == NULL || extra_bytes_array == NULL) |
- return MEM_ERROR; |
- |
- uint8* diff_bytes = diff_bytes_array.get(); |
- uint8* extra_bytes = extra_bytes_array.get(); |
int control_length = 0; |
int diff_bytes_length = 0; |
int diff_bytes_nonzero = 0; |
int extra_bytes_length = 0; |
int eblen = 0; |
- SinkStream control_stream; |
- |
// The patch format is a sequence of triples <copy,extra,seek> where 'copy' is |
// the number of bytes to copy from the old file (possibly with mistakes), |
// 'extra' is the number of bytes to copy from a stream of fresh bytes, and |
@@ -364,13 +359,18 @@ |
for (int i = 0; i < lenf; i++) { |
uint8 diff_byte = newbuf[lastscan + i] - old[lastpos + i]; |
- diff_bytes[diff_bytes_length + i] = diff_byte; |
- if (diff_byte) |
+ if (diff_byte) { |
++diff_bytes_nonzero; |
+ diff_skips->WriteVarint32(pending_diff_zeros); |
+ pending_diff_zeros = 0; |
+ diff_bytes->Write(&diff_byte, 1); |
+ } else { |
+ ++pending_diff_zeros; |
+ } |
} |
int gap = (scan - lenb) - (lastscan + lenf); |
for (int i = 0; i < gap; i++) |
- extra_bytes[extra_bytes_length + i] = newbuf[lastscan + lenf + i]; |
+ extra_bytes->Write(&newbuf[lastscan + lenf + i], 1); |
diff_bytes_length += lenf; |
extra_bytes_length += gap; |
@@ -379,9 +379,9 @@ |
uint32 extra_count = gap; |
int32 seek_adjustment = ((pos - lenb) - (lastpos + lenf)); |
- control_stream.WriteVarint32(copy_count); |
- control_stream.WriteVarint32(extra_count); |
- control_stream.WriteVarint32Signed(seek_adjustment); |
+ control_stream_copy_counts->WriteVarint32(copy_count); |
+ control_stream_extra_counts->WriteVarint32(extra_count); |
+ control_stream_seeks->WriteVarint32Signed(seek_adjustment); |
++control_length; |
#ifdef DEBUG_bsmedberg |
LOG(INFO) << StringPrintf( |
@@ -395,6 +395,8 @@ |
} |
} |
+ diff_skips->WriteVarint32(pending_diff_zeros); |
+ |
I.reset(); |
MBSPatchHeader header; |
@@ -405,19 +407,16 @@ |
header.slen = oldsize; |
header.scrc32 = CalculateCrc(old, oldsize); |
header.dlen = newsize; |
- header.cblen = control_stream.Length(); |
- header.difflen = diff_bytes_length; |
- header.extralen = extra_bytes_length; |
WriteHeader(patch_stream, &header); |
- patch_stream->Append(&control_stream); |
- patch_stream->Write(diff_bytes, diff_bytes_length); |
- patch_stream->Write(extra_bytes, extra_bytes_length); |
+ size_t diff_skips_length = diff_skips->Length(); |
+ patch_streams.CopyTo(patch_stream); |
LOG(INFO) << "Control tuples: " << control_length |
<< " copy bytes: " << diff_bytes_length |
<< " mistakes: " << diff_bytes_nonzero |
+ << " (skips: " << diff_skips_length << ")" |
<< " extra bytes: " << extra_bytes_length; |
LOG(INFO) << "Uncompressed bsdiff patch size " |