Hash :
fe621944
Author :
Date :
2020-11-10T22:54:37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
/*
* Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#include <unistd.h>
#define print(args...) fprintf(stderr, ##args)
#define debug print
#define debug_dump dump
#define debug_dump_atom dump_atom
#define debug_dump_atoms dump_atoms
static inline void
print_atom_byte(unsigned char c) {
if (c == '\r')
print("\\r");
else if (c == '\n')
print("\\n");
else if ((c < 32 || c >= 127) && (c != '\t'))
print("\\x%02x", c);
else
print("%c", c);
}
static inline void
dump_atom(const struct diff_data *left, const struct diff_data *right,
const struct diff_atom *atom)
{
if (!atom) {
print("NULL atom\n");
return;
}
if (left)
print(" %3u '", diff_atom_root_idx(left, atom));
if (atom->at == NULL) {
off_t remain = atom->len;
if (fseek(atom->root->f, atom->pos, SEEK_SET) == -1)
abort(); /* cannot return error */
while (remain > 0) {
char buf[16];
size_t r;
int i;
r = fread(buf, 1, MIN(remain, sizeof(buf)),
atom->root->f);
if (r == -1)
abort(); /* cannot return error */
if (r == 0)
break;
remain -= r;
for (i = 0; i < r; i++)
print_atom_byte(buf[i]);
}
} else {
const char *s;
for (s = atom->at; s < (const char*)(atom->at + atom->len); s++)
print_atom_byte(*s);
}
print("'\n");
}
static inline void
dump_atoms(const struct diff_data *d, struct diff_atom *atom,
unsigned int count)
{
if (count > 42) {
dump_atoms(d, atom, 20);
print("[%u lines skipped]\n", count - 20 - 20);
dump_atoms(d, atom + count - 20, 20);
return;
} else {
struct diff_atom *i;
foreach_diff_atom(i, atom, count) {
dump_atom(d, NULL, i);
}
}
}
static inline void
dump(struct diff_data *d)
{
dump_atoms(d, d->atoms.head, d->atoms.len);
}
/* kd is a quadratic space myers matrix from the original Myers algorithm.
* kd_forward and kd_backward are linear slices of a myers matrix from the Myers
* Divide algorithm.
*/
static inline void
dump_myers_graph(const struct diff_data *l, const struct diff_data *r,
int *kd, int *kd_forward, int kd_forward_d,
int *kd_backward, int kd_backward_d)
{
#define COLOR_YELLOW "\033[1;33m"
#define COLOR_GREEN "\033[1;32m"
#define COLOR_BLUE "\033[1;34m"
#define COLOR_RED "\033[1;31m"
#define COLOR_END "\033[0;m"
int x;
int y;
print(" ");
for (x = 0; x <= l->atoms.len; x++)
print("%2d", x % 100);
print("\n");
for (y = 0; y <= r->atoms.len; y++) {
print("%3d ", y);
for (x = 0; x <= l->atoms.len; x++) {
/* print d advancements from kd, if any. */
char label = 'o';
char *color = NULL;
if (kd) {
int max = l->atoms.len + r->atoms.len;
size_t kd_len = max + 1 + max;
int *kd_pos = kd;
int di;
#define xk_to_y(X, K) ((X) - (K))
for (di = 0; di < max; di++) {
int ki;
for (ki = di; ki >= -di; ki -= 2) {
if (x != kd_pos[ki]
|| y != xk_to_y(x, ki))
continue;
label = '0' + (di % 10);
color = COLOR_YELLOW;
break;
}
if (label != 'o')
break;
kd_pos += kd_len;
}
}
if (kd_forward && kd_forward_d >= 0) {
#define xc_to_y(X, C, DELTA) ((X) - (C) + (DELTA))
int ki;
for (ki = kd_forward_d;
ki >= -kd_forward_d;
ki -= 2) {
if (x != kd_forward[ki])
continue;
if (y != xk_to_y(x, ki))
continue;
label = 'F';
color = COLOR_GREEN;
break;
}
}
if (kd_backward && kd_backward_d >= 0) {
int delta = (int)r->atoms.len
- (int)l->atoms.len;
int ki;
for (ki = kd_backward_d;
ki >= -kd_backward_d;
ki -= 2) {
if (x != kd_backward[ki])
continue;
if (y != xc_to_y(x, ki, delta))
continue;
if (label == 'o') {
label = 'B';
color = COLOR_BLUE;
} else {
label = 'X';
color = COLOR_RED;
}
break;
}
}
if (color)
print("%s", color);
print("%c", label);
if (color)
print("%s", COLOR_END);
if (x < l->atoms.len)
print("-");
}
print("\n");
if (y == r->atoms.len)
break;
print(" ");
for (x = 0; x < l->atoms.len; x++) {
bool same;
diff_atom_same(&same, &l->atoms.head[x],
&r->atoms.head[y]);
if (same)
print("|\\");
else
print("| ");
}
print("|\n");
}
}
static inline void
debug_dump_myers_graph(const struct diff_data *l, const struct diff_data *r,
int *kd, int *kd_forward, int kd_forward_d,
int *kd_backward, int kd_backward_d)
{
if (l->atoms.len > 99 || r->atoms.len > 99)
return;
dump_myers_graph(l, r, kd, kd_forward, kd_forward_d,
kd_backward, kd_backward_d);
}
#else
#define debug(args...)
#define debug_dump(args...)
#define debug_dump_atom(args...)
#define debug_dump_atoms(args...)
#define debug_dump_myers_graph(args...)
#endif