commit - e10a628aa1d46df600ffc7194d35f67416eaefdd
commit + b3fb46867c2efc085c584bd336b9dca9cf26a161
blob - 0dbd866be6ebf41975cc4e1b917e8f2d8b0be150
blob + c70915a7fff65bfdfe065d3836d6114ffa8a3421
--- include/diff/diff_main.h
+++ include/diff/diff_main.h
void diff_data_free(struct diff_data *diff_data);
+int
+diff_atom_cmp(int *cmp,
+ const struct diff_atom *left,
+ const struct diff_atom *right);
+
/* Indicate whether two given diff atoms match. */
-bool diff_atom_same(const struct diff_atom *left,
- const struct diff_atom *right);
+int
+diff_atom_same(bool *same,
+ const struct diff_atom *left,
+ const struct diff_atom *right);
/* The atom's index in the entire file. For atoms divided by lines of text, this
* yields the line number (starting with 0). Also works for diff_data that
blob - 39136bde16a7fb4b736b65a49793d7ae7a196d8e
blob + 67e31955bdbcf8b9120e49f0711927a1c52ebcfe
--- lib/diff_main.c
+++ lib/diff_main.c
#include "debug.h"
-bool
-diff_atom_same(const struct diff_atom *left, const struct diff_atom *right)
+static int
+read_at(int fd, int at_pos, unsigned char *buf, size_t len)
{
+ int r;
+ if (lseek(fd, at_pos, SEEK_SET) == -1)
+ return errno;
+ r = read(fd, buf, len);
+ if (r == -1)
+ return errno;
+ if (r != len)
+ return EIO;
+ return 0;
+}
+
+static int
+buf_cmp(const unsigned char *left, size_t left_len,
+ const unsigned char *right, size_t right_len)
+{
+ int cmp = memcmp(left, right, MIN(left_len, right_len));
+ if (cmp)
+ return cmp;
+ if (left_len == right_len)
+ return 0;
+ return (left_len > right_len) ? 1 : -1;
+}
+
+int
+diff_atom_cmp(int *cmp,
+ const struct diff_atom *left,
+ const struct diff_atom *right)
+{
off_t remain_left, remain_right;
- bool same = true;
- if (left->hash != right->hash || left->len != right->len)
- return false;
+ if (!left->len && !right->len) {
+ *cmp = 0;
+ return 0;
+ }
+ if (!right->len) {
+ *cmp = 1;
+ return 0;
+ }
+ if (!left->len) {
+ *cmp = -1;
+ return 0;
+ }
- if (left->at != NULL && right->at != NULL)
- return (memcmp(left->at, right->at, left->len) == 0);
+ if (left->at != NULL && right->at != NULL) {
+ *cmp = buf_cmp(left->at, left->len, right->at, right->len);
+ return 0;
+ }
remain_left = left->len;
remain_right = right->len;
off_t n_left, n_right;
ssize_t r;
+ if (!remain_right) {
+ *cmp = 1;
+ return 0;
+ }
+ if (!remain_left) {
+ *cmp = -1;
+ return 0;
+ }
+
n_left = MIN(chunksz, remain_left);
n_right = MIN(chunksz, remain_right);
if (left->at == NULL) {
- if (lseek(left->d->root->fd,
- left->pos + (left->len - remain_left),
- SEEK_SET) == -1)
- abort(); /* XXX cannot return error */
- r = read(left->d->root->fd, buf_left, n_left);
- if (r == -1)
- abort(); /* XXX cannot return error */
- if (r != n_left)
- abort(); /* XXX cannot return error */
+ r = read_at(left->d->root->fd,
+ left->pos + (left->len - remain_left),
+ buf_left, n_left);
+ if (r) {
+ *cmp = 0;
+ return r;
+ }
p_left = buf_left;
} else {
p_left = left->at + (left->len - remain_left);
}
if (right->at == NULL) {
- if (lseek(right->d->root->fd,
- right->pos + (right->len - remain_right),
- SEEK_SET) == -1)
- abort(); /* XXX cannot return error */
- r = read(right->d->root->fd, buf_right, n_right);
- if (r == -1)
- abort(); /* XXX cannot return error */
- if (r != n_right)
- abort(); /* XXX cannot return error */
+ r = read_at(right->d->root->fd,
+ right->pos + (right->len - remain_right),
+ buf_right, n_right);
+ if (r) {
+ *cmp = 0;
+ return r;
+ }
p_right = buf_right;
} else {
p_right = right->at + (right->len - remain_right);
- n_right = MIN(chunksz, remain_right);
}
-
- if (n_left == 0) {
- if (n_right != 0)
- same = false;
- break;
- } else if (n_right == 0) {
- if (n_left != 0)
- same = false;
- break;
- } else if (n_left == n_right) {
- if (memcmp(p_left, p_right, n_left) != 0) {
- same = false;
- break;
- }
- } else {
- same = false;
- break;
+
+ r = buf_cmp(p_left, n_left, p_right, n_right);
+ if (r) {
+ *cmp = r;
+ return 0;
}
remain_left -= n_left;
remain_right -= n_right;
}
- return same;
+ *cmp = 0;
+ return 0;
+}
+
+int
+diff_atom_same(bool *same,
+ const struct diff_atom *left,
+ const struct diff_atom *right)
+{
+ int cmp;
+ int r = diff_atom_cmp(&cmp, left, right);
+ if (r) {
+ *same = true;
+ return r;
+ }
+ *same = (cmp == 0);
+ return 0;
}
/* Even if a left or right side is empty, diff output may need to know the
/* Add a chunk of equal lines, if any */
unsigned int equal_atoms = 0;
while (equal_atoms < state->left.atoms.len
- && equal_atoms < state->right.atoms.len
- && diff_atom_same(&state->left.atoms.head[equal_atoms],
- &state->right.atoms.head[equal_atoms]))
+ && equal_atoms < state->right.atoms.len) {
+ int r;
+ bool same;
+ r = diff_atom_same(&same, &state->left.atoms.head[equal_atoms],
+ &state->right.atoms.head[equal_atoms]);
+ if (r)
+ return r;
+ if (!same)
+ break;
equal_atoms++;
+ }
if (equal_atoms) {
if (!diff_state_add_chunk(state, true,
&state->left.atoms.head[0],
blob - 5a91ceba82cb3d83ec084178d1e08b56cb150395
blob + c164f2277b98e6aadeed4c94b4479e596473d531
--- lib/diff_myers.c
+++ lib/diff_myers.c
int x_before_slide = x;
/* Slide down any snake that we might find here. */
- while (x < left->atoms.len && xk_to_y(x, k) < right->atoms.len
- && diff_atom_same(&left->atoms.head[x],
- &right->atoms.head[xk_to_y(x, k)]))
- x++;
+ while (x < left->atoms.len && xk_to_y(x, k) < right->atoms.len) {
+ bool same;
+ int r = diff_atom_same(&same,
+ &left->atoms.head[x],
+ &right->atoms.head[
+ xk_to_y(x, k)]);
+ if (r) {
+ abort(); // TODO: error handling
+ }
+ if (!same)
+ break;
+ x++;
+ }
kd_forward[k] = x;
if (x_before_slide != x) {
debug(" down %d similar lines\n", x - x_before_slide);
&right->atoms.head[xc_to_y(x, c, delta)-1]);
}
int x_before_slide = x;
- while (x > 0 && xc_to_y(x, c, delta) > 0
- && diff_atom_same(&left->atoms.head[x-1],
- &right->atoms.head[xc_to_y(x, c,
- delta)-1]))
+ while (x > 0 && xc_to_y(x, c, delta) > 0) {
+ bool same;
+ int r = diff_atom_same(&same,
+ &left->atoms.head[x-1],
+ &right->atoms.head[
+ xc_to_y(x, c, delta)-1]);
+ if (r) {
+ abort(); // TODO: error handling
+ }
+ if (!same)
+ break;
x--;
+ }
kd_backward[c] = x;
if (x_before_slide != x) {
debug(" up %d similar lines\n", x_before_slide - x);
/* Slide down any snake that we might find here. */
while (x < left->atoms.len
- && xk_to_y(x, k) < right->atoms.len
- && diff_atom_same(&left->atoms.head[x],
- &right->atoms.head[xk_to_y(x, k)]))
- x++;
+ && xk_to_y(x, k) < right->atoms.len) {
+ bool same;
+ int r = diff_atom_same(&same,
+ &left->atoms.head[x],
+ &right->atoms.head[
+ xk_to_y(x, k)]);
+ if (r)
+ return r;
+ if (!same)
+ break;
+ x++;
+ }
kd_column[k] = x;
if (DEBUG) {
blob - 280be3f6230fb2de2e3b77a26030d2c313f5f696
blob + 79fe3c4b8682eaf5665b62bb3c1e6d8ebb7bc745
--- lib/diff_patience.c
+++ lib/diff_patience.c
continue;
diff_data_foreach_atom_from(i + 1, j, d) {
- if (diff_atom_same(i, j)) {
- if (i->patience.unique_here) {
- i->patience.unique_here = false;
- i->patience.unique_in_both = false;
- count--;
- }
- j->patience.unique_here = false;
- j->patience.unique_in_both = false;
+ bool same;
+ int r = diff_atom_same(&same, i, j);
+ if (r)
+ abort(); // TODO: error handling
+ if (!same)
+ continue;
+ if (i->patience.unique_here) {
+ i->patience.unique_here = false;
+ i->patience.unique_in_both = false;
count--;
}
+ j->patience.unique_here = false;
+ j->patience.unique_in_both = false;
+ count--;
}
}
if (unique_count)
struct diff_atom *j;
int found_in_b = 0;
diff_data_foreach_atom(j, right) {
- if (!diff_atom_same(i, j))
+ bool same;
+ int r = diff_atom_same(&same, i, j);
+ if (r)
+ abort(); // TODO: error handling
+ if (!same)
continue;
if (!j->patience.unique_here) {
found_in_b = 2; /* or more */
struct diff_atom *j;
bool found_in_a = false;
diff_data_foreach_atom(j, left) {
+ bool same;
+ int r;
if (!j->patience.unique_in_both)
continue;
- if (!diff_atom_same(i, j))
+ r = diff_atom_same(&same, i, j);
+ if (r)
+ abort(); // TODO: error handling
+ if (!same)
continue;
found_in_a = true;
break;
* iteration, so we will never hit another common-unique line
* above. */
for (identical_l.start = l_idx, identical_r.start = r_idx;
- identical_l.start > l_min
- && identical_r.start > r_min
- && diff_atom_same(
+ identical_l.start > l_min && identical_r.start > r_min;
+ identical_l.start--, identical_r.start--) {
+ bool same;
+ int r = diff_atom_same(&same,
&left->atoms.head[identical_l.start - 1],
&right->atoms.head[identical_r.start - 1]);
- identical_l.start--, identical_r.start--);
+ if (r)
+ abort(); // TODO: error handling
+ if (!same)
+ break;
+ }
/* Swallow downwards */
for (identical_l.end = l_idx + 1, identical_r.end = r_idx + 1;
identical_l.end < left->atoms.len
- && identical_r.end < right->atoms.len
- && diff_atom_same(&left->atoms.head[identical_l.end],
- &right->atoms.head[identical_r.end]);
+ && identical_r.end < right->atoms.len;
identical_l.end++, identical_r.end++,
next_l_idx++) {
struct diff_atom *l_end;
struct diff_atom *r_end;
+ bool same;
+ int r = diff_atom_same(&same,
+ &left->atoms.head[identical_l.end],
+ &right->atoms.head[identical_r.end]);
+ if (r)
+ abort(); // TODO: error handling
+ if (!same)
+ break;
l_end = &left->atoms.head[identical_l.end];
r_end = &right->atoms.head[identical_r.end];
if (!l_end->patience.unique_in_both)