Path: blob/main/contrib/libdiff/lib/diff_internal.h
35083 views
/* Generic infrastructure to implement various diff algorithms. */1/*2* Copyright (c) 2020 Neels Hofmeyr <[email protected]>3*4* Permission to use, copy, modify, and distribute this software for any5* purpose with or without fee is hereby granted, provided that the above6* copyright notice and this permission notice appear in all copies.7*8* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15*/1617#ifndef MAX18#define MAX(A,B) ((A)>(B)?(A):(B))19#endif20#ifndef MIN21#define MIN(A,B) ((A)<(B)?(A):(B))22#endif2324static inline bool25diff_range_empty(const struct diff_range *r)26{27return r->start == r->end;28}2930static inline bool31diff_ranges_touch(const struct diff_range *a, const struct diff_range *b)32{33return (a->end >= b->start) && (a->start <= b->end);34}3536static inline void37diff_ranges_merge(struct diff_range *a, const struct diff_range *b)38{39*a = (struct diff_range){40.start = MIN(a->start, b->start),41.end = MAX(a->end, b->end),42};43}4445static inline int46diff_range_len(const struct diff_range *r)47{48if (!r)49return 0;50return r->end - r->start;51}5253/* Indicate whether two given diff atoms match. */54int55diff_atom_same(bool *same,56const struct diff_atom *left,57const struct diff_atom *right);5859/* A diff chunk represents a set of atoms on the left and/or a set of atoms on60* the right.61*62* If solved == false:63* The diff algorithm has divided the source file, and this is a chunk that the64* inner_algo should run on next.65* The lines on the left should be diffed against the lines on the right.66* (If there are no left lines or no right lines, it implies solved == true,67* because there is nothing to diff.)68*69* If solved == true:70* If there are only left atoms, it is a chunk removing atoms from the left ("a71* minus chunk").72* If there are only right atoms, it is a chunk adding atoms from the right ("a73* plus chunk").74* If there are both left and right lines, it is a chunk of equal content on75* both sides, and left_count == right_count:76*77* - foo }78* - bar }-- diff_chunk{ left_start = &left.atoms.head[0], left_count = 3,79* - baz } right_start = NULL, right_count = 0 }80* moo }81* goo }-- diff_chunk{ left_start = &left.atoms.head[3], left_count = 3,82* zoo } right_start = &right.atoms.head[0], right_count = 3 }83* +loo }84* +roo }-- diff_chunk{ left_start = NULL, left_count = 0,85* +too } right_start = &right.atoms.head[3], right_count = 3 }86*87*/88struct diff_chunk {89bool solved;90struct diff_atom *left_start;91unsigned int left_count;92struct diff_atom *right_start;93unsigned int right_count;94};9596#define DIFF_RESULT_ALLOC_BLOCKSIZE 1289798struct diff_chunk_context;99100bool101diff_chunk_context_empty(const struct diff_chunk_context *cc);102103bool104diff_chunk_contexts_touch(const struct diff_chunk_context *cc,105const struct diff_chunk_context *other);106107void108diff_chunk_contexts_merge(struct diff_chunk_context *cc,109const struct diff_chunk_context *other);110111struct diff_state {112/* The final result passed to the original diff caller. */113struct diff_result *result;114115/* The root diff_data is in result->left,right, these are (possibly)116* subsections of the root data. */117struct diff_data left;118struct diff_data right;119120unsigned int recursion_depth_left;121122/* Remaining chunks from one diff algorithm pass, if any solved == false123* chunks came up. */124diff_chunk_arraylist_t temp_result;125126/* State buffer used by Myers algorithm. */127int *kd_buf;128size_t kd_buf_size; /* in units of sizeof(int), not bytes */129};130131struct diff_chunk *diff_state_add_chunk(struct diff_state *state, bool solved,132struct diff_atom *left_start,133unsigned int left_count,134struct diff_atom *right_start,135unsigned int right_count);136137struct diff_output_info;138139int diff_output_lines(struct diff_output_info *output_info, FILE *dest,140const char *prefix, struct diff_atom *start_atom,141unsigned int count);142143int diff_output_trailing_newline_msg(struct diff_output_info *outinfo,144FILE *dest,145const struct diff_chunk *c);146#define DIFF_FUNCTION_CONTEXT_SIZE 55147int diff_output_match_function_prototype(char *prototype, size_t prototype_size,148int *last_prototype_idx,149const struct diff_result *result,150int chunk_start_line);151152struct diff_output_info *diff_output_info_alloc(void);153154void155diff_data_init_subsection(struct diff_data *d, struct diff_data *parent,156struct diff_atom *from_atom, unsigned int atoms_count);157158159