| #include "cache.h" |
| #include "xdiff-interface.h" |
| |
| static int parse_num(char **cp_p, int *num_p) |
| { |
| char *cp = *cp_p; |
| int num = 0; |
| int read_some; |
| |
| while ('0' <= *cp && *cp <= '9') |
| num = num * 10 + *cp++ - '0'; |
| if (!(read_some = cp - *cp_p)) |
| return -1; |
| *cp_p = cp; |
| *num_p = num; |
| return 0; |
| } |
| |
| int parse_hunk_header(char *line, int len, |
| int *ob, int *on, |
| int *nb, int *nn) |
| { |
| char *cp; |
| cp = line + 4; |
| if (parse_num(&cp, ob)) { |
| bad_line: |
| return error("malformed diff output: %s", line); |
| } |
| if (*cp == ',') { |
| cp++; |
| if (parse_num(&cp, on)) |
| goto bad_line; |
| } |
| else |
| *on = 1; |
| if (*cp++ != ' ' || *cp++ != '+') |
| goto bad_line; |
| if (parse_num(&cp, nb)) |
| goto bad_line; |
| if (*cp == ',') { |
| cp++; |
| if (parse_num(&cp, nn)) |
| goto bad_line; |
| } |
| else |
| *nn = 1; |
| return -!!memcmp(cp, " @@", 3); |
| } |
| |
| static void consume_one(void *priv_, char *s, unsigned long size) |
| { |
| struct xdiff_emit_state *priv = priv_; |
| char *ep; |
| while (size) { |
| unsigned long this_size; |
| ep = memchr(s, '\n', size); |
| this_size = (ep == NULL) ? size : (ep - s + 1); |
| priv->consume(priv, s, this_size); |
| size -= this_size; |
| s += this_size; |
| } |
| } |
| |
| int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) |
| { |
| struct xdiff_emit_state *priv = priv_; |
| int i; |
| |
| for (i = 0; i < nbuf; i++) { |
| if (mb[i].ptr[mb[i].size-1] != '\n') { |
| /* Incomplete line */ |
| priv->remainder = realloc(priv->remainder, |
| priv->remainder_size + |
| mb[i].size); |
| memcpy(priv->remainder + priv->remainder_size, |
| mb[i].ptr, mb[i].size); |
| priv->remainder_size += mb[i].size; |
| continue; |
| } |
| |
| /* we have a complete line */ |
| if (!priv->remainder) { |
| consume_one(priv, mb[i].ptr, mb[i].size); |
| continue; |
| } |
| priv->remainder = realloc(priv->remainder, |
| priv->remainder_size + |
| mb[i].size); |
| memcpy(priv->remainder + priv->remainder_size, |
| mb[i].ptr, mb[i].size); |
| consume_one(priv, priv->remainder, |
| priv->remainder_size + mb[i].size); |
| free(priv->remainder); |
| priv->remainder = NULL; |
| priv->remainder_size = 0; |
| } |
| if (priv->remainder) { |
| consume_one(priv, priv->remainder, priv->remainder_size); |
| free(priv->remainder); |
| priv->remainder = NULL; |
| priv->remainder_size = 0; |
| } |
| return 0; |
| } |