Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2005 Junio C Hamano |
| 3 | * The delta-parsing part is almost straight copy of patch-delta.c |
| 4 | * which is (C) 2005 Nicolas Pitre <nico@cam.org>. |
| 5 | */ |
| 6 | #include <stdlib.h> |
| 7 | #include <string.h> |
| 8 | #include <limits.h> |
Nicolas Pitre | dcde55b | 2005-06-29 02:49:56 -0400 | [diff] [blame] | 9 | #include "delta.h" |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 10 | #include "count-delta.h" |
| 11 | |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 12 | /* |
| 13 | * NOTE. We do not _interpret_ delta fully. As an approximation, we |
| 14 | * just count the number of bytes that are copied from the source, and |
Junio C Hamano | 355e76a | 2005-06-03 01:36:03 -0700 | [diff] [blame] | 15 | * the number of literal data bytes that are inserted. |
| 16 | * |
| 17 | * Number of bytes that are _not_ copied from the source is deletion, |
| 18 | * and number of inserted literal bytes are addition, so sum of them |
| 19 | * is the extent of damage. xdelta can express an edit that copies |
| 20 | * data inside of the destination which originally came from the |
| 21 | * source. We do not count that in the following routine, so we are |
| 22 | * undercounting the source material that remains in the final output |
| 23 | * that way. |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 24 | */ |
Junio C Hamano | 355e76a | 2005-06-03 01:36:03 -0700 | [diff] [blame] | 25 | int count_delta(void *delta_buf, unsigned long delta_size, |
| 26 | unsigned long *src_copied, unsigned long *literal_added) |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 27 | { |
| 28 | unsigned long copied_from_source, added_literal; |
| 29 | const unsigned char *data, *top; |
| 30 | unsigned char cmd; |
| 31 | unsigned long src_size, dst_size, out; |
| 32 | |
Nicolas Pitre | dcde55b | 2005-06-29 02:49:56 -0400 | [diff] [blame] | 33 | if (delta_size < DELTA_SIZE_MIN) |
Junio C Hamano | 355e76a | 2005-06-03 01:36:03 -0700 | [diff] [blame] | 34 | return -1; |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 35 | |
| 36 | data = delta_buf; |
| 37 | top = delta_buf + delta_size; |
| 38 | |
Nicolas Pitre | dcde55b | 2005-06-29 02:49:56 -0400 | [diff] [blame] | 39 | src_size = get_delta_hdr_size(&data); |
| 40 | dst_size = get_delta_hdr_size(&data); |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 41 | |
| 42 | added_literal = copied_from_source = out = 0; |
| 43 | while (data < top) { |
| 44 | cmd = *data++; |
| 45 | if (cmd & 0x80) { |
| 46 | unsigned long cp_off = 0, cp_size = 0; |
| 47 | if (cmd & 0x01) cp_off = *data++; |
| 48 | if (cmd & 0x02) cp_off |= (*data++ << 8); |
| 49 | if (cmd & 0x04) cp_off |= (*data++ << 16); |
| 50 | if (cmd & 0x08) cp_off |= (*data++ << 24); |
| 51 | if (cmd & 0x10) cp_size = *data++; |
| 52 | if (cmd & 0x20) cp_size |= (*data++ << 8); |
| 53 | if (cp_size == 0) cp_size = 0x10000; |
| 54 | |
| 55 | if (cmd & 0x40) |
| 56 | /* copy from dst */ |
| 57 | ; |
| 58 | else |
| 59 | copied_from_source += cp_size; |
| 60 | out += cp_size; |
| 61 | } else { |
| 62 | /* write literal into dst */ |
| 63 | added_literal += cmd; |
| 64 | out += cmd; |
| 65 | data += cmd; |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | /* sanity check */ |
| 70 | if (data != top || out != dst_size) |
Junio C Hamano | 355e76a | 2005-06-03 01:36:03 -0700 | [diff] [blame] | 71 | return -1; |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 72 | |
| 73 | /* delete size is what was _not_ copied from source. |
| 74 | * edit size is that and literal additions. |
| 75 | */ |
Junio C Hamano | 355e76a | 2005-06-03 01:36:03 -0700 | [diff] [blame] | 76 | *src_copied = copied_from_source; |
| 77 | *literal_added = added_literal; |
| 78 | return 0; |
Junio C Hamano | 8597697 | 2005-05-24 12:09:32 -0700 | [diff] [blame] | 79 | } |