Rizin
unix-like reverse engineering framework and cli tools
unified_diff.c File Reference
#include <rz_cons.h>

Go to the source code of this file.

Macros

#define Color_RANGE   Color_BBLUE
 
#define Color_INSERT   Color_BGREEN
 
#define Color_DELETE   Color_BRED
 
#define Color_BGINSERT   "\x1b[48;5;22m"
 
#define Color_BGDELETE   "\x1b[48;5;52m"
 
#define FAST_MOD2(x, y)   ((x) & (y - 1))
 
#define FAST_MOD64(x)   FAST_MOD2(x, 64)
 
#define DIFF_COLOR(prefix)   (prefix == '+' ? Color_INSERT : (prefix == '-' ? Color_DELETE : ""))
 
#define DIFF_BGCOLOR(prefix)   (prefix == '+' ? Color_BGINSERT : (prefix == '-' ? Color_BGDELETE : ""))
 

Functions

static ut32 count_newlines (RzDiff *diff, const void *array, st32 beg, st32 end)
 
static void diff_unified_append_ranges (RzList *opcodes, RzStrBuf *sb, bool color)
 
static void diff_unified_json_ranges (RzList *opcodes, PJ *pj)
 
static void diff_unified_append_data (RzDiff *diff, const void *array, st32 beg, st32 end, RzStrBuf *sb, char prefix, bool color)
 
static void diff_unified_lines_hl (RzDiff *diff, RzDiffOp *op, RzStrBuf *sb, char del_prefix, char ins_prefix)
 
static void diff_unified_json_data (RzDiff *diff, const void *array, st32 beg, st32 end, PJ *pj, const char *op)
 
RZ_API RZ_OWN char * rz_diff_unified_text (RZ_NONNULL RzDiff *diff, RZ_NULLABLE const char *from, RZ_NULLABLE const char *to, bool show_time, bool color)
 Produces a diff output with A and B inputs presented immediately adjacent to each other. More...
 
RZ_API RZ_OWN PJrz_diff_unified_json (RZ_NONNULL RzDiff *diff, RZ_NULLABLE const char *from, RZ_NULLABLE const char *to, bool show_time)
 Produces a diff output to convert A in B in a JSON format. More...
 

Macro Definition Documentation

◆ Color_BGDELETE

#define Color_BGDELETE   "\x1b[48;5;52m"

Definition at line 11 of file unified_diff.c.

◆ Color_BGINSERT

#define Color_BGINSERT   "\x1b[48;5;22m"

Definition at line 10 of file unified_diff.c.

◆ Color_DELETE

#define Color_DELETE   Color_BRED

Definition at line 9 of file unified_diff.c.

◆ Color_INSERT

#define Color_INSERT   Color_BGREEN

Definition at line 8 of file unified_diff.c.

◆ Color_RANGE

#define Color_RANGE   Color_BBLUE

Definition at line 7 of file unified_diff.c.

◆ DIFF_BGCOLOR

#define DIFF_BGCOLOR (   prefix)    (prefix == '+' ? Color_BGINSERT : (prefix == '-' ? Color_BGDELETE : ""))

Definition at line 16 of file unified_diff.c.

◆ DIFF_COLOR

#define DIFF_COLOR (   prefix)    (prefix == '+' ? Color_INSERT : (prefix == '-' ? Color_DELETE : ""))

Definition at line 15 of file unified_diff.c.

◆ FAST_MOD2

#define FAST_MOD2 (   x,
 
)    ((x) & (y - 1))

Definition at line 13 of file unified_diff.c.

◆ FAST_MOD64

#define FAST_MOD64 (   x)    FAST_MOD2(x, 64)

Definition at line 14 of file unified_diff.c.

Function Documentation

◆ count_newlines()

static ut32 count_newlines ( RzDiff diff,
const void *  array,
st32  beg,
st32  end 
)
inlinestatic

Definition at line 18 of file unified_diff.c.

18  {
19  RzDiffMethodElemAt elem_at = diff->methods.elem_at;
20  RzDiffMethodStringify stringify = diff->methods.stringify;
21  int len = 0;
22  ut32 count = 0;
23  const char *p;
24  const void *elem;
25  RzStrBuf tmp;
26 
27  for (st32 i = beg; i < end; ++i) {
29  elem = elem_at(array, i);
30  stringify(elem, &tmp);
32  p = rz_strbuf_get(&tmp);
33  if (len > 0 && p[len - 1] == '\n') {
34  count++;
35  }
37  }
38  return count;
39 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint32_t ut32
void * p
Definition: libc.cpp:67
const void *(* RzDiffMethodElemAt)(RZ_BORROW const void *array, ut32 index)
Definition: rz_diff.h:36
void(* RzDiffMethodStringify)(RZ_BORROW const void *elem, RZ_BORROW RzStrBuf *sb)
Definition: rz_diff.h:40
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
#define st32
Definition: rz_types_base.h:12
RzDiffMethodElemAt elem_at
Definition: diff.c:81
RzDiffMethodStringify stringify
Definition: diff.c:85
MethodsInternal methods
Definition: diff.c:95

References count, methods_internal_t::elem_at, test_evm::end, i, len, rz_diff_t::methods, p, rz_strbuf_fini(), rz_strbuf_get(), rz_strbuf_init(), rz_strbuf_length(), st32, methods_internal_t::stringify, and autogen_x86imm::tmp.

Referenced by diff_unified_lines_hl(), and rz_diff_unified_text().

◆ diff_unified_append_data()

static void diff_unified_append_data ( RzDiff diff,
const void *  array,
st32  beg,
st32  end,
RzStrBuf sb,
char  prefix,
bool  color 
)
inlinestatic

Definition at line 70 of file unified_diff.c.

70  {
71  RzDiffMethodElemAt elem_at = diff->methods.elem_at;
72  RzDiffMethodStringify stringify = diff->methods.stringify;
73  int len = 0;
74  ut32 count = 0;
75  const char *p;
76  const void *elem;
77  RzStrBuf tmp;
78  bool newline = false;
79  bool is_bytes = DIFF_IS_BYTES_METHOD(diff->methods);
80 
81  if (beg < 0) {
82  beg = 0;
83  }
84 
85  const char *bcol = color ? DIFF_COLOR(prefix) : "";
86  const char *ecol = color ? (Color_RESET) : "";
87 
88  rz_strbuf_appendf(sb, "%s%c", bcol, prefix);
89  for (st32 i = beg; i < end; ++i) {
90  if (newline || (is_bytes && count > 0 && !FAST_MOD64(count))) {
91  rz_strbuf_appendf(sb, "%s\n%s%c", ecol, bcol, prefix);
92  newline = false;
93  }
95  elem = elem_at(array, i);
96  stringify(elem, &tmp);
98  p = rz_strbuf_get(&tmp);
99  count += len;
100  if (len > 0 && p[len - 1] == '\n') {
101  len--;
102  newline = true;
103  }
106  }
107  rz_strbuf_appendf(sb, "%s\n", ecol);
108 }
static SblHeader sb
Definition: bin_mbn.c:26
#define DIFF_IS_BYTES_METHOD(x)
Definition: bytes_diff.c:6
unsigned short prefix[65536]
Definition: gun.c:163
#define Color_RESET
Definition: rz_cons.h:617
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API bool rz_strbuf_append_n(RzStrBuf *sb, const char *s, size_t l)
Definition: strbuf.c:229
#define FAST_MOD64(x)
Definition: unified_diff.c:14
#define DIFF_COLOR(prefix)
Definition: unified_diff.c:15
static int color
Definition: visual.c:20

References color, Color_RESET, count, DIFF_COLOR, DIFF_IS_BYTES_METHOD, methods_internal_t::elem_at, test_evm::end, FAST_MOD64, i, len, rz_diff_t::methods, p, prefix, rz_strbuf_append_n(), rz_strbuf_appendf(), rz_strbuf_fini(), rz_strbuf_get(), rz_strbuf_init(), rz_strbuf_length(), sb, st32, methods_internal_t::stringify, and autogen_x86imm::tmp.

Referenced by rz_diff_unified_text().

◆ diff_unified_append_ranges()

static void diff_unified_append_ranges ( RzList opcodes,
RzStrBuf sb,
bool  color 
)
inlinestatic

Definition at line 41 of file unified_diff.c.

41  {
42  const char *color_beg = color ? Color_RANGE : "";
43  const char *color_end = color ? Color_RESET : "";
44 
45  RzDiffOp *first = rz_list_first(opcodes);
46  RzDiffOp *last = rz_list_last(opcodes);
47  st32 a_len = last->a_end - first->a_beg;
48  st32 b_len = last->b_end - first->b_beg;
49 
50  rz_strbuf_appendf(sb, "%s@@ -%d,%d +%d,%d @@%s\n", color_beg, first->a_beg + 1, a_len, first->b_beg + 1, b_len, color_end);
51 }
OPCODE_DESC opcodes[]
Definition: avr_esil.c:1270
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
RZ_API RZ_BORROW void * rz_list_last(RZ_NONNULL const RzList *list)
Returns the last element of the list.
Definition: list.c:86
st32 a_end
Definition: rz_diff.h:52
st32 b_end
Definition: rz_diff.h:54
st32 a_beg
Definition: rz_diff.h:51
st32 b_beg
Definition: rz_diff.h:53
#define Color_RANGE
Definition: unified_diff.c:7

References rz_diff_op_t::a_beg, rz_diff_op_t::a_end, rz_diff_op_t::b_beg, rz_diff_op_t::b_end, color, Color_RANGE, Color_RESET, opcodes, rz_list_first(), rz_list_last(), rz_strbuf_appendf(), sb, and st32.

Referenced by rz_diff_unified_text().

◆ diff_unified_json_data()

static void diff_unified_json_data ( RzDiff diff,
const void *  array,
st32  beg,
st32  end,
PJ pj,
const char *  op 
)
inlinestatic

Definition at line 282 of file unified_diff.c.

282  {
283  RzDiffMethodElemAt elem_at = diff->methods.elem_at;
284  RzDiffMethodStringify stringify = diff->methods.stringify;
285  int len = 0;
286  ut32 count = 0;
287  const char *p;
288  const void *elem;
289  RzStrBuf tmp;
290  bool newline = false;
291  bool is_bytes = DIFF_IS_BYTES_METHOD(diff->methods);
292 
293  if (beg < 0) {
294  beg = 0;
295  }
296 
297  pj_o(pj);
298  pj_ks(pj, "op", op);
300  for (st32 i = beg; i < end; ++i) {
301  if (newline || (is_bytes && count > 0 && !FAST_MOD64(count))) {
302  pj_ks(pj, "value", rz_strbuf_get(&tmp));
303  pj_end(pj);
304 
307 
308  pj_o(pj);
309  pj_ks(pj, "op", op);
310  newline = false;
311  }
312  elem = elem_at(array, i);
313  stringify(elem, &tmp);
315  p = rz_strbuf_get(&tmp);
316  count += len;
317  if (len > 0 && p[len - 1] == '\n') {
318  newline = true;
319  }
320  }
321  pj_ks(pj, "value", rz_strbuf_get(&tmp));
322  pj_end(pj);
324 }
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
Definition: dis.c:32

References count, DIFF_IS_BYTES_METHOD, methods_internal_t::elem_at, test_evm::end, FAST_MOD64, i, len, rz_diff_t::methods, p, pj_end(), pj_ks(), pj_o(), rz_strbuf_fini(), rz_strbuf_get(), rz_strbuf_init(), rz_strbuf_length(), st32, methods_internal_t::stringify, and autogen_x86imm::tmp.

Referenced by rz_diff_unified_json().

◆ diff_unified_json_ranges()

static void diff_unified_json_ranges ( RzList opcodes,
PJ pj 
)
inlinestatic

Definition at line 53 of file unified_diff.c.

53  {
54  RzDiffOp *first = rz_list_first(opcodes);
55  RzDiffOp *last = rz_list_last(opcodes);
56  st32 a_len = last->a_end - first->a_beg;
57  st32 b_len = last->b_end - first->b_beg;
58 
59  pj_ka(pj, "from");
60  pj_N(pj, first->a_beg + 1);
61  pj_N(pj, a_len);
62  pj_end(pj);
63 
64  pj_ka(pj, "to");
65  pj_N(pj, first->b_beg + 1);
66  pj_N(pj, b_len);
67  pj_end(pj);
68 }
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_N(PJ *j, st64 n)
Definition: pj.c:260

References rz_diff_op_t::a_beg, rz_diff_op_t::a_end, rz_diff_op_t::b_beg, rz_diff_op_t::b_end, opcodes, pj_end(), pj_ka(), pj_N(), rz_list_first(), rz_list_last(), and st32.

Referenced by rz_diff_unified_json().

◆ diff_unified_lines_hl()

static void diff_unified_lines_hl ( RzDiff diff,
RzDiffOp op,
RzStrBuf sb,
char  del_prefix,
char  ins_prefix 
)
inlinestatic

Definition at line 113 of file unified_diff.c.

113  {
114  RzDiffMethodElemAt elem_at = diff->methods.elem_at;
115  RzDiffMethodStringify stringify = diff->methods.stringify;
116  int len = 0;
117  const char *p;
118  const void *elem;
119  RzStrBuf tmp, tmp2;
120  const char *ecol = Color_RESET;
121  const char *ebgcol = Color_RESET_BG;
122 
123  const void *a_array = diff->a;
124  st32 a_beg = op->a_beg;
125  if (a_beg < 0) {
126  a_beg = 0;
127  }
128  st32 a_end = op->a_end;
129 
130  const void *b_array = diff->b;
131  st32 b_beg = op->b_beg;
132  if (b_beg < 0) {
133  b_beg = 0;
134  }
135  st32 b_end = op->b_end;
136 
137  ut32 num_nl = count_newlines(diff, a_array, a_beg, a_end);
138  // + 1 just in case there's no nl at end
139  ut32 num_bounds = num_nl + 1;
140  st32 *char_bounds = malloc(sizeof(st32) * 2 * num_bounds);
141  if (!char_bounds) {
142  return;
143  }
144  for (ut32 i = 0; i < num_bounds; i++) {
145  char_bounds[i * 2] = char_bounds[i * 2 + 1] = -1;
146  }
147 
148  // Fill char_bounds array
149  ut32 bounds_idx = 0;
150  bool newline = false;
151  st32 i = a_beg;
152  st32 j = b_beg;
153  for (; i < a_end; ++i) {
154  if (newline) {
155  bounds_idx++;
156  newline = false;
157  }
159  elem = elem_at(a_array, i);
160  stringify(elem, &tmp);
162  p = rz_strbuf_get(&tmp);
163  if (len > 0 && p[len - 1] == '\n') {
164  len--;
165  newline = true;
166  }
167 
168  int len_b = 0;
169  const void *elem_b;
170  const char *p_b;
171 
172  for (; j < b_end; ++j) {
173  rz_strbuf_init(&tmp2);
174  elem_b = elem_at(b_array, j);
175  stringify(elem_b, &tmp2);
176  len_b = rz_strbuf_length(&tmp2);
177  p_b = rz_strbuf_get(&tmp2);
178  if (len_b > 0 && p_b[len_b - 1] == '\n') {
179  len_b--;
180  }
181 
182  if (len && len_b && (p[0] == p_b[0] || p[len - 1] == p_b[len_b - 1])) {
183  // Get left bound.
184  st32 left = 0;
185  for (; left < RZ_MIN(len, len_b) && p[left] == p_b[left]; left++)
186  ;
187  char_bounds[bounds_idx * 2] = left;
188  // Get right bound (offset). "- left" chops off
189  // the left portion that has already matched.
190  st32 right = 0;
191  for (; right < RZ_MIN(len, len_b) - left && p[len - 1 - right] == p_b[len_b - 1 - right];
192  right++)
193  ;
194  char_bounds[bounds_idx * 2 + 1] = right;
195  }
196 
197  rz_strbuf_fini(&tmp2);
198  ++j;
199  break;
200  }
202  }
203 
204  // Show deleted lines
205  char prefix = del_prefix;
206  const char *bcol = DIFF_COLOR(prefix);
207  const char *bbgcol = DIFF_BGCOLOR(prefix);
208  newline = false;
209  bounds_idx = 0;
210 
211  rz_strbuf_appendf(sb, "%s%c", bcol, prefix);
212  for (st32 i = a_beg; i < a_end; ++i) {
213  if (newline) {
214  rz_strbuf_appendf(sb, "%s\n%s%c", ecol, bcol, prefix);
215  newline = false;
216  bounds_idx++;
217  }
219  elem = elem_at(a_array, i);
220  stringify(elem, &tmp);
222  p = rz_strbuf_get(&tmp);
223  if (len > 0 && p[len - 1] == '\n') {
224  len--;
225  newline = true;
226  }
227  st32 left = char_bounds[bounds_idx * 2];
228  st32 right = char_bounds[bounds_idx * 2 + 1];
229  if (left < 0 || right < 0 || len - right < left) {
231  } else {
232  rz_strbuf_append_n(sb, p, left);
233  rz_strbuf_append(sb, bbgcol);
234  rz_strbuf_append_n(sb, p + left, len - right - left);
235  rz_strbuf_append(sb, ebgcol);
236  rz_strbuf_append_n(sb, p + len - right, right);
237  }
239  }
240  rz_strbuf_appendf(sb, "%s\n", ecol);
241 
242  // Show inserted lines
243  prefix = ins_prefix;
244  bcol = DIFF_COLOR(prefix);
245  bbgcol = DIFF_BGCOLOR(prefix);
246  newline = false;
247  bounds_idx = 0;
248 
249  rz_strbuf_appendf(sb, "%s%c", bcol, prefix);
250  for (st32 i = b_beg; i < b_end; ++i) {
251  if (newline) {
252  rz_strbuf_appendf(sb, "%s\n%s%c", ecol, bcol, prefix);
253  newline = false;
254  bounds_idx++;
255  }
257  elem = elem_at(b_array, i);
258  stringify(elem, &tmp);
260  p = rz_strbuf_get(&tmp);
261  if (len > 0 && p[len - 1] == '\n') {
262  len--;
263  newline = true;
264  }
265  st32 left = char_bounds[bounds_idx * 2];
266  st32 right = char_bounds[bounds_idx * 2 + 1];
267  if (left < 0 || right < 0 || len - right < left) {
269  } else {
270  rz_strbuf_append_n(sb, p, left);
271  rz_strbuf_append(sb, bbgcol);
272  rz_strbuf_append_n(sb, p + left, len - right - left);
273  rz_strbuf_append(sb, ebgcol);
274  rz_strbuf_append_n(sb, p + len - right, right);
275  }
277  }
278  rz_strbuf_appendf(sb, "%s\n", ecol);
279  free(char_bounds);
280 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
void * malloc(size_t size)
Definition: malloc.c:123
#define Color_RESET_BG
Definition: rz_cons.h:619
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
#define RZ_MIN(x, y)
const void * a
Definition: diff.c:90
const void * b
Definition: diff.c:91
static ut32 count_newlines(RzDiff *diff, const void *array, st32 beg, st32 end)
Definition: unified_diff.c:18
#define DIFF_BGCOLOR(prefix)
Definition: unified_diff.c:16

References rz_diff_t::a, rz_diff_t::b, Color_RESET, Color_RESET_BG, count_newlines(), DIFF_BGCOLOR, DIFF_COLOR, methods_internal_t::elem_at, free(), i, len, malloc(), rz_diff_t::methods, p, prefix, RZ_MIN, rz_strbuf_append(), rz_strbuf_append_n(), rz_strbuf_appendf(), rz_strbuf_fini(), rz_strbuf_get(), rz_strbuf_init(), rz_strbuf_length(), sb, st32, methods_internal_t::stringify, and autogen_x86imm::tmp.

Referenced by rz_diff_unified_text().

◆ rz_diff_unified_json()

RZ_API RZ_OWN PJ* rz_diff_unified_json ( RZ_NONNULL RzDiff diff,
RZ_NULLABLE const char *  from,
RZ_NULLABLE const char *  to,
bool  show_time 
)

Produces a diff output to convert A in B in a JSON format.

Produces a diff output with A and B inputs and contains the operations required to convert A in B and the values to remove, insert or keep.

Definition at line 409 of file unified_diff.c.

409  {
410  rz_return_val_if_fail(diff && diff->methods.elem_at && diff->methods.stringify, NULL);
411  PJ *pj = NULL;
412  RzList *groups = NULL;
413  RzList *opcodes = NULL;
414  RzDiffOp *op = NULL;
415  RzListIter *itg = NULL;
416  RzListIter *ito = NULL;
417 
418  if (!from) {
419  from = "/original";
420  }
421  if (!to) {
422  to = "/modified";
423  }
424 
425  pj = pj_new();
426  if (!pj) {
427  RZ_LOG_ERROR("rz_diff_unified: failed to allocate json\n");
428  goto rz_diff_unified_json_fail;
429  }
430  pj_o(pj);
431 
432  if (show_time) {
434  if (!time) {
435  RZ_LOG_ERROR("rz_diff_unified: failed to allocate timestamp\n");
436  goto rz_diff_unified_json_fail;
437  }
438  pj_ks(pj, "timestamp", time);
439  free(time);
440  }
441 
442  pj_ks(pj, "from", from);
443  pj_ks(pj, "to", to);
444 
446  if (!groups) {
447  goto rz_diff_unified_json_fail;
448  }
449 
450  pj_ka(pj, "diff");
451  rz_list_foreach (groups, itg, opcodes) {
452  if (rz_list_length(opcodes) < 1) {
453  continue;
454  }
455  pj_o(pj);
457  pj_ka(pj, "ops");
458  rz_list_foreach (opcodes, ito, op) {
459  if (op->type == RZ_DIFF_OP_EQUAL) {
460  diff_unified_json_data(diff, diff->a, op->a_beg, op->a_end, pj, "equal");
461  continue;
462  }
463  if (op->type == RZ_DIFF_OP_DELETE || op->type == RZ_DIFF_OP_REPLACE) {
464  diff_unified_json_data(diff, diff->a, op->a_beg, op->a_end, pj, "delete");
465  }
466  if (op->type == RZ_DIFF_OP_INSERT || op->type == RZ_DIFF_OP_REPLACE) {
467  diff_unified_json_data(diff, diff->b, op->b_beg, op->b_end, pj, "insert");
468  }
469  }
470  pj_end(pj);
471  pj_end(pj);
472  }
473  pj_end(pj);
474  pj_end(pj);
475 
477  return pj;
478 
479 rz_diff_unified_json_fail:
480  pj_free(pj);
482  return NULL;
483 }
#define NULL
Definition: cris-opc.c:27
RZ_API RZ_OWN RzList * rz_diff_opcodes_grouped_new(RZ_NONNULL RzDiff *diff, ut32 n_groups)
Generates groups of opcodes needed to go from A to B.
Definition: diff.c:712
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_DIFF_OP_REPLACE
Definition: rz_diff.h:24
@ RZ_DIFF_OP_DELETE
Definition: rz_diff.h:21
@ RZ_DIFF_OP_EQUAL
Definition: rz_diff.h:22
@ RZ_DIFF_OP_INSERT
Definition: rz_diff.h:23
#define RZ_DIFF_DEFAULT_N_GROUPS
Definition: rz_diff.h:59
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API RZ_OWN char * rz_time_date_now_to_string(void)
Returns the timestamp in string format of the current time (now)
Definition: time.c:278
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
Definition: rz_pj.h:12
static void diff_unified_json_data(RzDiff *diff, const void *array, st32 beg, st32 end, PJ *pj, const char *op)
Definition: unified_diff.c:282
static void diff_unified_json_ranges(RzList *opcodes, PJ *pj)
Definition: unified_diff.c:53

References diff_unified_json_data(), diff_unified_json_ranges(), free(), from, make_dist_html::groups, NULL, opcodes, pj_end(), pj_free(), pj_ka(), pj_ks(), pj_new(), pj_o(), RZ_DIFF_DEFAULT_N_GROUPS, RZ_DIFF_OP_DELETE, RZ_DIFF_OP_EQUAL, RZ_DIFF_OP_INSERT, RZ_DIFF_OP_REPLACE, rz_diff_opcodes_grouped_new(), rz_list_free(), rz_list_length(), RZ_LOG_ERROR, rz_return_val_if_fail, rz_time_date_now_to_string(), time, and to.

Referenced by rz_diff_unified_files().

◆ rz_diff_unified_text()

RZ_API RZ_OWN char* rz_diff_unified_text ( RZ_NONNULL RzDiff diff,
RZ_NULLABLE const char *  from,
RZ_NULLABLE const char *  to,
bool  show_time,
bool  color 
)

Produces a diff output with A and B inputs presented immediately adjacent to each other.

Produces a diff output with A and B inputs presented immediately adjacent to each other. It begins with range information and is immediately followed with the line additions, line deletions, and any number of the contextual lines.

Definition at line 333 of file unified_diff.c.

333  {
334  rz_return_val_if_fail(diff && diff->methods.elem_at && diff->methods.stringify, NULL);
335  RzStrBuf *sb = NULL;
336  RzList *groups = NULL;
337  RzList *opcodes = NULL;
338  RzDiffOp *op = NULL;
339  RzListIter *itg = NULL;
340  RzListIter *ito = NULL;
341 
342  if (!from) {
343  from = "/original";
344  }
345  if (!to) {
346  to = "/modified";
347  }
348  sb = rz_strbuf_new("");
349  if (!sb) {
350  RZ_LOG_ERROR("rz_diff_unified: cannot allocate sb\n");
351  goto rz_diff_unified_text_fail;
352  }
353 
354  if (show_time) {
356  rz_strbuf_appendf(sb, "--- %s %s\n+++ %s %s\n", from, (time ? time : ""), to, (time ? time : ""));
357  free(time);
358  } else {
359  rz_strbuf_appendf(sb, "--- %s\n+++ %s\n", from, to);
360  }
361 
363  if (!groups) {
364  goto rz_diff_unified_text_fail;
365  }
366 
367  rz_list_foreach (groups, itg, opcodes) {
368  if (rz_list_length(opcodes) < 1) {
369  continue;
370  }
372  rz_list_foreach (opcodes, ito, op) {
373  if (op->type == RZ_DIFF_OP_EQUAL) {
374  diff_unified_append_data(diff, diff->a, op->a_beg, op->a_end, sb, ' ', color);
375  continue;
376  }
377  if (op->type == RZ_DIFF_OP_DELETE) {
378  diff_unified_append_data(diff, diff->a, op->a_beg, op->a_end, sb, '-', color);
379  } else if (op->type == RZ_DIFF_OP_INSERT) {
380  diff_unified_append_data(diff, diff->b, op->b_beg, op->b_end, sb, '+', color);
381  } else if (op->type == RZ_DIFF_OP_REPLACE) {
382  if (!color || !DIFF_IS_LINES_METHOD(diff->methods) ||
383  count_newlines(diff, diff->a, op->a_beg, op->a_end) !=
384  count_newlines(diff, diff->b, op->b_beg, op->b_end)) {
385  diff_unified_append_data(diff, diff->a, op->a_beg, op->a_end, sb, '-', color);
386  diff_unified_append_data(diff, diff->b, op->b_beg, op->b_end, sb, '+', color);
387  } else {
388  diff_unified_lines_hl(diff, op, sb, '-', '+');
389  }
390  }
391  }
392  }
393 
395  return rz_strbuf_drain(sb);
396 
397 rz_diff_unified_text_fail:
400  return NULL;
401 }
#define DIFF_IS_LINES_METHOD(x)
Definition: lines_diff.c:6
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
static void diff_unified_append_data(RzDiff *diff, const void *array, st32 beg, st32 end, RzStrBuf *sb, char prefix, bool color)
Definition: unified_diff.c:70
static void diff_unified_append_ranges(RzList *opcodes, RzStrBuf *sb, bool color)
Definition: unified_diff.c:41
static void diff_unified_lines_hl(RzDiff *diff, RzDiffOp *op, RzStrBuf *sb, char del_prefix, char ins_prefix)
Definition: unified_diff.c:113

References color, count_newlines(), DIFF_IS_LINES_METHOD, diff_unified_append_data(), diff_unified_append_ranges(), diff_unified_lines_hl(), free(), from, make_dist_html::groups, NULL, opcodes, RZ_DIFF_DEFAULT_N_GROUPS, RZ_DIFF_OP_DELETE, RZ_DIFF_OP_EQUAL, RZ_DIFF_OP_INSERT, RZ_DIFF_OP_REPLACE, rz_diff_opcodes_grouped_new(), rz_list_free(), rz_list_length(), RZ_LOG_ERROR, rz_return_val_if_fail, rz_strbuf_appendf(), rz_strbuf_drain(), rz_strbuf_free(), rz_strbuf_new(), rz_time_date_now_to_string(), sb, time, and to.

Referenced by core_analysis_graph_construct_nodes(), graph_construct_nodes(), print_diff(), rz_cmd_debug(), and rz_diff_unified_files().