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 |