| OLD | NEW |
| 1 // Copyright 2003, 2004 Colin Percival | 1 // Copyright 2003, 2004 Colin Percival |
| 2 // All rights reserved | 2 // All rights reserved |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted providing that the following conditions | 5 // modification, are permitted providing that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // 1. Redistributions of source code must retain the above copyright | 7 // 1. Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // 2. Redistributions in binary form must reproduce the above copyright | 9 // 2. Redistributions in binary form must reproduce the above copyright |
| 10 // notice, this list of conditions and the following disclaimer in the | 10 // notice, this list of conditions and the following disclaimer in the |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 #include "base/logging.h" | 58 #include "base/logging.h" |
| 59 #include "base/strings/string_util.h" | 59 #include "base/strings/string_util.h" |
| 60 #include "base/time/time.h" | 60 #include "base/time/time.h" |
| 61 | 61 |
| 62 #include "courgette/crc.h" | 62 #include "courgette/crc.h" |
| 63 #include "courgette/streams.h" | 63 #include "courgette/streams.h" |
| 64 #include "courgette/third_party/bsdiff/bsdiff_search.h" | 64 #include "courgette/third_party/bsdiff/bsdiff_search.h" |
| 65 #include "courgette/third_party/bsdiff/paged_array.h" | 65 #include "courgette/third_party/bsdiff/paged_array.h" |
| 66 #include "courgette/third_party/bsdiff/qsufsort.h" | 66 #include "courgette/third_party/bsdiff/qsufsort.h" |
| 67 | 67 |
| 68 namespace courgette { | 68 namespace { |
| 69 |
| 70 using courgette::CalculateCrc; |
| 71 using courgette::PagedArray; |
| 72 using courgette::SinkStream; |
| 73 using courgette::SinkStreamSet; |
| 74 using courgette::SourceStream; |
| 75 using courgette::SourceStreamSet; |
| 76 |
| 77 } // namespace |
| 78 |
| 79 namespace bsdiff { |
| 69 | 80 |
| 70 static CheckBool WriteHeader(SinkStream* stream, MBSPatchHeader* header) { | 81 static CheckBool WriteHeader(SinkStream* stream, MBSPatchHeader* header) { |
| 71 bool ok = stream->Write(header->tag, sizeof(header->tag)); | 82 bool ok = stream->Write(header->tag, sizeof(header->tag)); |
| 72 ok &= stream->WriteVarint32(header->slen); | 83 ok &= stream->WriteVarint32(header->slen); |
| 73 ok &= stream->WriteVarint32(header->scrc32); | 84 ok &= stream->WriteVarint32(header->scrc32); |
| 74 ok &= stream->WriteVarint32(header->dlen); | 85 ok &= stream->WriteVarint32(header->dlen); |
| 75 return ok; | 86 return ok; |
| 76 } | 87 } |
| 77 | 88 |
| 78 BSDiffStatus CreateBinaryPatch(SourceStream* old_stream, | 89 BSDiffStatus CreateBinaryPatch(SourceStream* old_stream, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 // fffffffffffffff |lenf| = scan forward from |lastscan| | 169 // fffffffffffffff |lenf| = scan forward from |lastscan| |
| 159 // bbbb |lenb| = scan back from new seed |scan|. | 170 // bbbb |lenb| = scan back from new seed |scan|. |
| 160 // ddddddddddddddd Emit diff bytes for the 'copy'. | 171 // ddddddddddddddd Emit diff bytes for the 'copy'. |
| 161 // xx Emit extra bytes. | 172 // xx Emit extra bytes. |
| 162 // ssssssssssss |lastscan = scan - lenb| is new seed. | 173 // ssssssssssss |lastscan = scan - lenb| is new seed. |
| 163 // x Cases (1) and (3) .... | 174 // x Cases (1) and (3) .... |
| 164 | 175 |
| 165 int lastscan = 0, lastpos = 0, lastoffset = 0; | 176 int lastscan = 0, lastpos = 0, lastoffset = 0; |
| 166 | 177 |
| 167 int scan = 0; | 178 int scan = 0; |
| 168 int match_length = 0; | 179 SearchResult match(0, 0); |
| 169 | 180 |
| 170 while (scan < newsize) { | 181 while (scan < newsize) { |
| 171 int pos = 0; | |
| 172 int oldscore = 0; // Count of how many bytes of the current match at |scan| | 182 int oldscore = 0; // Count of how many bytes of the current match at |scan| |
| 173 // extend the match at |lastscan|. | 183 // extend the match at |lastscan|. |
| 184 match.pos = 0; |
| 174 | 185 |
| 175 scan += match_length; | 186 scan += match.size; |
| 176 for (int scsc = scan; scan < newsize; ++scan) { | 187 for (int scsc = scan; scan < newsize; ++scan) { |
| 177 match_length = courgette::search<PagedArray<int>&>( | 188 match = search<PagedArray<int>&>( |
| 178 I, old, oldsize, newbuf + scan, newsize - scan, &pos); | 189 I, old, oldsize, newbuf + scan, newsize - scan); |
| 179 | 190 |
| 180 for (; scsc < scan + match_length; scsc++) | 191 for (; scsc < scan + match.size; scsc++) |
| 181 if ((scsc + lastoffset < oldsize) && | 192 if ((scsc + lastoffset < oldsize) && |
| 182 (old[scsc + lastoffset] == newbuf[scsc])) | 193 (old[scsc + lastoffset] == newbuf[scsc])) |
| 183 oldscore++; | 194 oldscore++; |
| 184 | 195 |
| 185 if ((match_length == oldscore) && (match_length != 0)) | 196 if ((match.size == oldscore) && (match.size != 0)) |
| 186 break; // Good continuing match, case (1) | 197 break; // Good continuing match, case (1) |
| 187 if (match_length > oldscore + 8) | 198 if (match.size > oldscore + 8) |
| 188 break; // New seed match, case (2) | 199 break; // New seed match, case (2) |
| 189 | 200 |
| 190 if ((scan + lastoffset < oldsize) && | 201 if ((scan + lastoffset < oldsize) && |
| 191 (old[scan + lastoffset] == newbuf[scan])) | 202 (old[scan + lastoffset] == newbuf[scan])) |
| 192 oldscore--; | 203 oldscore--; |
| 193 // Case (3) continues in this loop until we fall out of the loop (4). | 204 // Case (3) continues in this loop until we fall out of the loop (4). |
| 194 } | 205 } |
| 195 | 206 |
| 196 if ((match_length != oldscore) || (scan == newsize)) { // Cases (2) and (4) | 207 if ((match.size != oldscore) || (scan == newsize)) { // Cases (2) and (4) |
| 197 // This next chunk of code finds the boundary between the bytes to be | 208 // This next chunk of code finds the boundary between the bytes to be |
| 198 // copied as part of the current triple, and the bytes to be copied as | 209 // copied as part of the current triple, and the bytes to be copied as |
| 199 // part of the next triple. The |lastscan| match is extended forwards as | 210 // part of the next triple. The |lastscan| match is extended forwards as |
| 200 // far as possible provided doing to does not add too many mistakes. The | 211 // far as possible provided doing to does not add too many mistakes. The |
| 201 // |scan| match is extended backwards in a similar way. | 212 // |scan| match is extended backwards in a similar way. |
| 202 | 213 |
| 203 // Extend the current match (if any) backwards. |lenb| is the maximal | 214 // Extend the current match (if any) backwards. |lenb| is the maximal |
| 204 // extension for which less than half the byte positions in the extension | 215 // extension for which less than half the byte positions in the extension |
| 205 // are wrong. | 216 // are wrong. |
| 206 int lenb = 0; | 217 int lenb = 0; |
| 207 if (scan < newsize) { // i.e. not case (4); there is a match to extend. | 218 if (scan < newsize) { // i.e. not case (4); there is a match to extend. |
| 208 int score = 0, Sb = 0; | 219 int score = 0, Sb = 0; |
| 209 for (int i = 1; (scan >= lastscan + i) && (pos >= i); i++) { | 220 for (int i = 1; (scan >= lastscan + i) && (match.pos >= i); i++) { |
| 210 if (old[pos - i] == newbuf[scan - i]) | 221 if (old[match.pos - i] == newbuf[scan - i]) |
| 211 score++; | 222 score++; |
| 212 if (score * 2 - i > Sb * 2 - lenb) { | 223 if (score * 2 - i > Sb * 2 - lenb) { |
| 213 Sb = score; | 224 Sb = score; |
| 214 lenb = i; | 225 lenb = i; |
| 215 } | 226 } |
| 216 } | 227 } |
| 217 } | 228 } |
| 218 | 229 |
| 219 // Extend the lastscan match forward; |lenf| is the maximal extension for | 230 // Extend the lastscan match forward; |lenf| is the maximal extension for |
| 220 // which less than half of the byte positions in entire lastscan match are | 231 // which less than half of the byte positions in entire lastscan match are |
| (...skipping 19 matching lines...) Expand all Loading... |
| 240 // that maximizes the exact matching bytes. | 251 // that maximizes the exact matching bytes. |
| 241 if (lastscan + lenf > scan - lenb) { | 252 if (lastscan + lenf > scan - lenb) { |
| 242 int overlap = (lastscan + lenf) - (scan - lenb); | 253 int overlap = (lastscan + lenf) - (scan - lenb); |
| 243 int score = 0; | 254 int score = 0; |
| 244 int Ss = 0, lens = 0; | 255 int Ss = 0, lens = 0; |
| 245 for (int i = 0; i < overlap; i++) { | 256 for (int i = 0; i < overlap; i++) { |
| 246 if (newbuf[lastscan + lenf - overlap + i] == | 257 if (newbuf[lastscan + lenf - overlap + i] == |
| 247 old[lastpos + lenf - overlap + i]) { | 258 old[lastpos + lenf - overlap + i]) { |
| 248 score++; | 259 score++; |
| 249 } | 260 } |
| 250 if (newbuf[scan - lenb + i] == old[pos - lenb + i]) { | 261 if (newbuf[scan - lenb + i] == old[match.pos - lenb + i]) { |
| 251 score--; | 262 score--; |
| 252 } | 263 } |
| 253 if (score > Ss) { | 264 if (score > Ss) { |
| 254 Ss = score; | 265 Ss = score; |
| 255 lens = i + 1; | 266 lens = i + 1; |
| 256 } | 267 } |
| 257 } | 268 } |
| 258 | 269 |
| 259 lenf += lens - overlap; | 270 lenf += lens - overlap; |
| 260 lenb -= lens; | 271 lenb -= lens; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 277 for (int i = 0; i < gap; i++) { | 288 for (int i = 0; i < gap; i++) { |
| 278 if (!extra_bytes->Write(&newbuf[lastscan + lenf + i], 1)) | 289 if (!extra_bytes->Write(&newbuf[lastscan + lenf + i], 1)) |
| 279 return MEM_ERROR; | 290 return MEM_ERROR; |
| 280 } | 291 } |
| 281 | 292 |
| 282 diff_bytes_length += lenf; | 293 diff_bytes_length += lenf; |
| 283 extra_bytes_length += gap; | 294 extra_bytes_length += gap; |
| 284 | 295 |
| 285 uint32_t copy_count = lenf; | 296 uint32_t copy_count = lenf; |
| 286 uint32_t extra_count = gap; | 297 uint32_t extra_count = gap; |
| 287 int32_t seek_adjustment = ((pos - lenb) - (lastpos + lenf)); | 298 int32_t seek_adjustment = ((match.pos - lenb) - (lastpos + lenf)); |
| 288 | 299 |
| 289 if (!control_stream_copy_counts->WriteVarint32(copy_count) || | 300 if (!control_stream_copy_counts->WriteVarint32(copy_count) || |
| 290 !control_stream_extra_counts->WriteVarint32(extra_count) || | 301 !control_stream_extra_counts->WriteVarint32(extra_count) || |
| 291 !control_stream_seeks->WriteVarint32Signed(seek_adjustment)) { | 302 !control_stream_seeks->WriteVarint32Signed(seek_adjustment)) { |
| 292 return MEM_ERROR; | 303 return MEM_ERROR; |
| 293 } | 304 } |
| 294 | 305 |
| 295 ++control_length; | 306 ++control_length; |
| 296 #ifdef DEBUG_bsmedberg | 307 #ifdef DEBUG_bsmedberg |
| 297 VLOG(1) << StringPrintf( | 308 VLOG(1) << StringPrintf( |
| 298 "Writing a block: copy: %-8u extra: %-8u seek: %+-9d", copy_count, | 309 "Writing a block: copy: %-8u extra: %-8u seek: %+-9d", copy_count, |
| 299 extra_count, seek_adjustment); | 310 extra_count, seek_adjustment); |
| 300 #endif | 311 #endif |
| 301 | 312 |
| 302 lastscan = scan - lenb; // Include the backward extension in seed. | 313 lastscan = scan - lenb; // Include the backward extension in seed. |
| 303 lastpos = pos - lenb; // ditto. | 314 lastpos = match.pos - lenb; // ditto. |
| 304 lastoffset = lastpos - lastscan; | 315 lastoffset = lastpos - lastscan; |
| 305 } | 316 } |
| 306 } | 317 } |
| 307 | 318 |
| 308 if (!diff_skips->WriteVarint32(pending_diff_zeros)) | 319 if (!diff_skips->WriteVarint32(pending_diff_zeros)) |
| 309 return MEM_ERROR; | 320 return MEM_ERROR; |
| 310 | 321 |
| 311 I.clear(); | 322 I.clear(); |
| 312 | 323 |
| 313 MBSPatchHeader header; | 324 MBSPatchHeader header; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 332 << " (skips: " << diff_skips_length << ")" | 343 << " (skips: " << diff_skips_length << ")" |
| 333 << " extra bytes: " << extra_bytes_length | 344 << " extra bytes: " << extra_bytes_length |
| 334 << "\nUncompressed bsdiff patch size " | 345 << "\nUncompressed bsdiff patch size " |
| 335 << patch_stream->Length() - initial_patch_stream_length | 346 << patch_stream->Length() - initial_patch_stream_length |
| 336 << "\nEnd bsdiff " | 347 << "\nEnd bsdiff " |
| 337 << (base::Time::Now() - start_bsdiff_time).InSecondsF(); | 348 << (base::Time::Now() - start_bsdiff_time).InSecondsF(); |
| 338 | 349 |
| 339 return OK; | 350 return OK; |
| 340 } | 351 } |
| 341 | 352 |
| 342 } // namespace courgette | 353 } // namespace bsdiff |
| OLD | NEW |