commit 93f8150ade45bb6185afe5b5ff3110db6403f8b3 from: Neels Hofmeyr date: Sun Oct 11 05:31:05 2020 UTC results: also combine chunks coming from temp_chunks commit - 984ca65b1b715a9fdc86bfff64e90a485d008058 commit + 93f8150ade45bb6185afe5b5ff3110db6403f8b3 blob - 792940d176efeada092e96fee5f42111ef1fb6a7 blob + a563080497cd7254b968b0777b78e9e2a5772e92 --- lib/diff_main.c +++ lib/diff_main.c @@ -207,75 +207,48 @@ diff_atom_same(bool *same, return 0; } -/* Even if a left or right side is empty, diff output may need to know the - * position in that file. - * So left_start or right_start must never be NULL -- pass left_count or - * right_count as zero to indicate staying at that position without consuming - * any lines. */ -struct diff_chunk * -diff_state_add_chunk(struct diff_state *state, bool solved, - struct diff_atom *left_start, unsigned int left_count, - struct diff_atom *right_start, unsigned int right_count) +static struct diff_chunk * +diff_state_add_solved_chunk(struct diff_state *state, + const struct diff_chunk *chunk) { - diff_chunk_arraylist_t *result = NULL; + diff_chunk_arraylist_t *result; struct diff_chunk *new_chunk; - struct diff_chunk chunk = { - .solved = solved, - .left_start = left_start, - .left_count = left_count, - .right_start = right_start, - .right_count = right_count, - }; enum diff_chunk_type last_t; - enum diff_chunk_type prev_last_t; enum diff_chunk_type new_t; - - debug("Add %s chunk:\n", chunk.solved ? "solved" : "UNSOLVED"); - debug("L\n"); - debug_dump_atoms(&state->left, chunk.left_start, chunk.left_count); - debug("R\n"); - debug_dump_atoms(&state->right, chunk.right_start, chunk.right_count); - - if (!solved || state->temp_result.len) { - /* Append to temp_result */ - result = &state->temp_result; - } else if (!state->result->chunks.len) { - /* Append to final result */ - result = &state->result->chunks; - } - if (result) { - ARRAYLIST_ADD(new_chunk, *result); - if (!new_chunk) - return NULL; - *new_chunk = chunk; - goto chunk_added; - } /* Append to solved chunks; make sure that adjacent chunks of same type are combined, and that a minus chunk * never directly follows a plus chunk. */ result = &state->result->chunks; - prev_last_t = result->len > 1 ? - diff_chunk_type(&result->head[result->len - 2]) : CHUNK_EMPTY; last_t = diff_chunk_type(&result->head[result->len - 1]); - new_t = diff_chunk_type(&chunk); + new_t = diff_chunk_type(chunk); + debug("Add %s chunk:\n", chunk->solved ? "solved" : "UNSOLVED"); + debug("L\n"); + debug_dump_atoms(&state->left, chunk->left_start, chunk->left_count); + debug("R\n"); + debug_dump_atoms(&state->right, chunk->right_start, chunk->right_count); + if (new_t == last_t) { new_chunk = &result->head[result->len - 1]; - new_chunk->left_count += chunk.left_count; - new_chunk->right_count += chunk.right_count; + new_chunk->left_count += chunk->left_count; + new_chunk->right_count += chunk->right_count; debug(" - added chunk touches previous one of same type, joined:\n"); debug("L\n"); debug_dump_atoms(&state->left, new_chunk->left_start, new_chunk->left_count); debug("R\n"); debug_dump_atoms(&state->right, new_chunk->right_start, new_chunk->right_count); } else if (last_t == CHUNK_PLUS && new_t == CHUNK_MINUS) { - /* If a minus-chunk follows a plus-chunk, place it above the plus-chunk. + enum diff_chunk_type prev_last_t = + result->len > 1 ? + diff_chunk_type(&result->head[result->len - 2]) + : CHUNK_EMPTY; + /* If a minus-chunk follows a plus-chunk, place it above the plus-chunk-> * Is the one before that also a minus? combine. */ if (prev_last_t == CHUNK_MINUS) { new_chunk = &result->head[result->len - 2]; - new_chunk->left_count += chunk.left_count; - new_chunk->right_count += chunk.right_count; + new_chunk->left_count += chunk->left_count; + new_chunk->right_count += chunk->right_count; debug(" - added minus-chunk follows plus-chunk," " put before that plus-chunk and joined" @@ -288,7 +261,7 @@ diff_state_add_chunk(struct diff_state *state, bool so ARRAYLIST_INSERT(new_chunk, *result, result->len - 1); if (!new_chunk) return NULL; - *new_chunk = chunk; + *new_chunk = *chunk; debug(" - added minus-chunk follows plus-chunk," " put before that plus-chunk\n"); @@ -297,12 +270,49 @@ diff_state_add_chunk(struct diff_state *state, bool so ARRAYLIST_ADD(new_chunk, *result); if (!new_chunk) return NULL; + *new_chunk = *chunk; + } + return new_chunk; +} + +/* Even if a left or right side is empty, diff output may need to know the + * position in that file. + * So left_start or right_start must never be NULL -- pass left_count or + * right_count as zero to indicate staying at that position without consuming + * any lines. */ +struct diff_chunk * +diff_state_add_chunk(struct diff_state *state, bool solved, + struct diff_atom *left_start, unsigned int left_count, + struct diff_atom *right_start, unsigned int right_count) +{ + diff_chunk_arraylist_t *result = NULL; + struct diff_chunk *new_chunk; + struct diff_chunk chunk = { + .solved = solved, + .left_start = left_start, + .left_count = left_count, + .right_start = right_start, + .right_count = right_count, + }; + + if (!solved || state->temp_result.len) { + /* Append to temp_result */ + debug("append to temp_result\n"); + result = &state->temp_result; + } else if (!state->result->chunks.len) { + /* Append to final result */ + debug("first chunk\n"); + result = &state->result->chunks; + } + if (result) { + ARRAYLIST_ADD(new_chunk, *result); + if (!new_chunk) + return NULL; *new_chunk = chunk; - goto chunk_added; + return new_chunk; } -chunk_added: - return new_chunk; + return diff_state_add_solved_chunk(state, &chunk); } void @@ -492,13 +502,7 @@ diff_run_algo(const struct diff_algo_config *algo_conf for (i = 0; i < state->temp_result.len; i++) { struct diff_chunk *c = &state->temp_result.head[i]; if (c->solved) { - struct diff_chunk *final_c; - ARRAYLIST_ADD(final_c, state->result->chunks); - if (!final_c) { - rc = ENOMEM; - goto return_rc; - } - *final_c = *c; + diff_state_add_solved_chunk(state, c); continue; }