Junio C Hamano | d9ea73e | 2006-04-05 02:03:58 -0700 | [diff] [blame] | 1 | #include "cache.h" |
| 2 | #include "xdiff-interface.h" |
| 3 | |
Junio C Hamano | a0fd314 | 2006-04-06 22:29:55 -0700 | [diff] [blame] | 4 | static int parse_num(char **cp_p, int *num_p) |
Junio C Hamano | c1e335a | 2006-04-05 12:22:35 -0700 | [diff] [blame] | 5 | { |
| 6 | char *cp = *cp_p; |
Junio C Hamano | a0fd314 | 2006-04-06 22:29:55 -0700 | [diff] [blame] | 7 | int num = 0; |
Junio C Hamano | c1e335a | 2006-04-05 12:22:35 -0700 | [diff] [blame] | 8 | int read_some; |
| 9 | |
| 10 | while ('0' <= *cp && *cp <= '9') |
| 11 | num = num * 10 + *cp++ - '0'; |
| 12 | if (!(read_some = cp - *cp_p)) |
| 13 | return -1; |
| 14 | *cp_p = cp; |
| 15 | *num_p = num; |
| 16 | return 0; |
| 17 | } |
| 18 | |
| 19 | int parse_hunk_header(char *line, int len, |
Junio C Hamano | a0fd314 | 2006-04-06 22:29:55 -0700 | [diff] [blame] | 20 | int *ob, int *on, |
| 21 | int *nb, int *nn) |
Junio C Hamano | c1e335a | 2006-04-05 12:22:35 -0700 | [diff] [blame] | 22 | { |
| 23 | char *cp; |
| 24 | cp = line + 4; |
| 25 | if (parse_num(&cp, ob)) { |
| 26 | bad_line: |
| 27 | return error("malformed diff output: %s", line); |
| 28 | } |
| 29 | if (*cp == ',') { |
| 30 | cp++; |
| 31 | if (parse_num(&cp, on)) |
| 32 | goto bad_line; |
| 33 | } |
| 34 | else |
| 35 | *on = 1; |
| 36 | if (*cp++ != ' ' || *cp++ != '+') |
| 37 | goto bad_line; |
| 38 | if (parse_num(&cp, nb)) |
| 39 | goto bad_line; |
| 40 | if (*cp == ',') { |
| 41 | cp++; |
| 42 | if (parse_num(&cp, nn)) |
| 43 | goto bad_line; |
| 44 | } |
| 45 | else |
| 46 | *nn = 1; |
| 47 | return -!!memcmp(cp, " @@", 3); |
| 48 | } |
| 49 | |
Junio C Hamano | d9ea73e | 2006-04-05 02:03:58 -0700 | [diff] [blame] | 50 | static void consume_one(void *priv_, char *s, unsigned long size) |
| 51 | { |
| 52 | struct xdiff_emit_state *priv = priv_; |
| 53 | char *ep; |
| 54 | while (size) { |
| 55 | unsigned long this_size; |
| 56 | ep = memchr(s, '\n', size); |
| 57 | this_size = (ep == NULL) ? size : (ep - s + 1); |
| 58 | priv->consume(priv, s, this_size); |
| 59 | size -= this_size; |
| 60 | s += this_size; |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) |
| 65 | { |
| 66 | struct xdiff_emit_state *priv = priv_; |
| 67 | int i; |
| 68 | |
| 69 | for (i = 0; i < nbuf; i++) { |
| 70 | if (mb[i].ptr[mb[i].size-1] != '\n') { |
| 71 | /* Incomplete line */ |
| 72 | priv->remainder = realloc(priv->remainder, |
| 73 | priv->remainder_size + |
| 74 | mb[i].size); |
| 75 | memcpy(priv->remainder + priv->remainder_size, |
| 76 | mb[i].ptr, mb[i].size); |
| 77 | priv->remainder_size += mb[i].size; |
| 78 | continue; |
| 79 | } |
| 80 | |
| 81 | /* we have a complete line */ |
| 82 | if (!priv->remainder) { |
| 83 | consume_one(priv, mb[i].ptr, mb[i].size); |
| 84 | continue; |
| 85 | } |
| 86 | priv->remainder = realloc(priv->remainder, |
| 87 | priv->remainder_size + |
| 88 | mb[i].size); |
| 89 | memcpy(priv->remainder + priv->remainder_size, |
| 90 | mb[i].ptr, mb[i].size); |
| 91 | consume_one(priv, priv->remainder, |
| 92 | priv->remainder_size + mb[i].size); |
| 93 | free(priv->remainder); |
| 94 | priv->remainder = NULL; |
| 95 | priv->remainder_size = 0; |
| 96 | } |
| 97 | if (priv->remainder) { |
| 98 | consume_one(priv, priv->remainder, priv->remainder_size); |
| 99 | free(priv->remainder); |
| 100 | priv->remainder = NULL; |
| 101 | priv->remainder_size = 0; |
| 102 | } |
| 103 | return 0; |
| 104 | } |