623
* reveals whether they precede an in-range line (flush into range hunk) or
624
* an out-of-range line (discard).
625
*/
626
-struct line_range_callback {
626
+struct line_range_filter {
627
xdiff_emit_line_fn orig_line_fn;
628
void *orig_cb_data;
629
const struct range_set *ranges; /* 0-based [start, end) */
630
unsigned int cur_range; /* index into the range_set */
631
632
/* Post/pre-image line counters (1-based, set from hunk headers) */
633
- long lno_post;
634
- long lno_pre;
633
+ long lno_in_postimage;
634
+ long lno_in_preimage;
635
636
/*
637
* Function name from most recent xdiff hunk header;
640
char func[80];
641
long funclen;
642
643
- /* Range hunk being accumulated for the current range */
644
- struct strbuf rhunk;
645
- long rhunk_old_begin, rhunk_old_count;
646
- long rhunk_new_begin, rhunk_new_count;
647
- int rhunk_active;
648
- int rhunk_has_changes; /* any '+' or '-' lines? */
643
+ /* The range hunk being accumulated for the current range. */
644
+ struct {
645
+ struct strbuf lines; /* buffered in-range diff lines */
646
+ long old_begin, old_count;
647
+ long new_begin, new_count;
648
+ int active;
649
+ int has_changes; /* any '+' or '-' line? */
650
+ } hunk;
651
652
/* Removal lines not yet known to be in-range */
653
struct strbuf pending_rm;
2542
return 1;
2543
}
2544
2543
-static void discard_pending_rm(struct line_range_callback *s)
2545
+static void discard_pending_rm(struct line_range_filter *filter)
2546
{
2545
- strbuf_reset(&s->pending_rm);
2546
- s->pending_rm_count = 0;
2547
+ strbuf_reset(&filter->pending_rm);
2548
+ filter->pending_rm_count = 0;
2549
}
2550
2549
-static void flush_rhunk(struct line_range_callback *s)
2551
+static void flush_range_hunk(struct line_range_filter *filter)
2552
{
2553
struct strbuf hdr = STRBUF_INIT;
2554
const char *p, *end;
2555
2554
- if (!s->rhunk_active || s->ret)
2556
+ if (!filter->hunk.active || filter->ret)
2557
return;
2558
2559
/* Drain any pending removal lines into the range hunk */
2558
- if (s->pending_rm_count) {
2559
- strbuf_addbuf(&s->rhunk, &s->pending_rm);
2560
- s->rhunk_old_count += s->pending_rm_count;
2561
- s->rhunk_has_changes = 1;
2562
- discard_pending_rm(s);
2560
+ if (filter->pending_rm_count) {
2561
+ strbuf_addbuf(&filter->hunk.lines, &filter->pending_rm);
2562
+ filter->hunk.old_count += filter->pending_rm_count;
2563
+ filter->hunk.has_changes = 1;
2564
+ discard_pending_rm(filter);
2565
}
2566
2567
/*
2570
* ctxlen causes xdiff to emit context covering a range that
2571
* has no changes in this commit.
2572
*/
2571
- if (!s->rhunk_has_changes) {
2572
- s->rhunk_active = 0;
2573
- strbuf_reset(&s->rhunk);
2573
+ if (!filter->hunk.has_changes) {
2574
+ filter->hunk.active = 0;
2575
+ strbuf_reset(&filter->hunk.lines);
2576
return;
2577
}
2578
2579
strbuf_addf(&hdr, "@@ -%ld,%ld +%ld,%ld @@",
2578
- s->rhunk_old_begin, s->rhunk_old_count,
2579
- s->rhunk_new_begin, s->rhunk_new_count);
2580
- if (s->funclen > 0) {
2580
+ filter->hunk.old_begin, filter->hunk.old_count,
2581
+ filter->hunk.new_begin, filter->hunk.new_count);
2582
+ if (filter->funclen > 0) {
2583
strbuf_addch(&hdr, ' ');
2582
- strbuf_add(&hdr, s->func, s->funclen);
2584
+ strbuf_add(&hdr, filter->func, filter->funclen);
2585
}
2586
strbuf_addch(&hdr, '\n');
2587
2586
- s->ret = s->orig_line_fn(s->orig_cb_data, hdr.buf, hdr.len);
2588
+ filter->ret = filter->orig_line_fn(filter->orig_cb_data, hdr.buf, hdr.len);
2589
strbuf_release(&hdr);
2590
2591
/*
2593
* The cast discards const because xdiff_emit_line_fn takes
2594
* char *, though fn_out_consume does not modify the buffer.
2595
*/
2594
- p = s->rhunk.buf;
2595
- end = p + s->rhunk.len;
2596
- while (!s->ret && p < end) {
2596
+ p = filter->hunk.lines.buf;
2597
+ end = p + filter->hunk.lines.len;
2598
+ while (!filter->ret && p < end) {
2599
const char *eol = memchr(p, '\n', end - p);
2600
unsigned long line_len = eol ? (unsigned long)(eol - p + 1)
2601
: (unsigned long)(end - p);
2600
- s->ret = s->orig_line_fn(s->orig_cb_data, (char *)p, line_len);
2602
+ filter->ret = filter->orig_line_fn(filter->orig_cb_data, (char *)p, line_len);
2603
p += line_len;
2604
}
2605
2604
- s->rhunk_active = 0;
2605
- strbuf_reset(&s->rhunk);
2606
+ filter->hunk.active = 0;
2607
+ strbuf_reset(&filter->hunk.lines);
2608
}
2609
2610
static void line_range_hunk_fn(void *data,
2612
long new_begin, long new_nr UNUSED,
2613
const char *func, long funclen)
2614
{
2613
- struct line_range_callback *s = data;
2615
+ struct line_range_filter *filter = data;
2616
2617
/*
2618
* When count > 0, begin is 1-based. When count == 0, begin is
2624
* flush or discard them when the next content line reveals
2625
* whether the removals precede in-range content.
2626
*/
2625
- s->lno_post = new_begin;
2626
- s->lno_pre = old_begin;
2627
+ filter->lno_in_postimage = new_begin;
2628
+ filter->lno_in_preimage = old_begin;
2629
2630
if (funclen > 0) {
2629
- if (funclen > (long)sizeof(s->func))
2630
- funclen = sizeof(s->func);
2631
- memcpy(s->func, func, funclen);
2631
+ if (funclen > (long)sizeof(filter->func))
2632
+ funclen = sizeof(filter->func);
2633
+ memcpy(filter->func, func, funclen);
2634
}
2633
- s->funclen = funclen;
2635
+ filter->funclen = funclen;
2636
}
2637
2638
static int line_range_line_fn(void *priv, char *line, unsigned long len)
2639
{
2638
- struct line_range_callback *s = priv;
2640
+ struct line_range_filter *filter = priv;
2641
const struct range *cur;
2640
- long lno_0, cur_pre;
2642
+ long idx_in_postimage, cur_pre;
2643
2642
- if (s->ret)
2643
- return s->ret;
2644
+ if (filter->ret)
2645
+ return filter->ret;
2646
2647
if (line[0] == '-') {
2646
- if (!s->pending_rm_count)
2647
- s->pending_rm_pre_begin = s->lno_pre;
2648
- s->lno_pre++;
2649
- strbuf_add(&s->pending_rm, line, len);
2650
- s->pending_rm_count++;
2651
- return s->ret;
2648
+ if (!filter->pending_rm_count)
2649
+ filter->pending_rm_pre_begin = filter->lno_in_preimage;
2650
+ filter->lno_in_preimage++;
2651
+ strbuf_add(&filter->pending_rm, line, len);
2652
+ filter->pending_rm_count++;
2653
+ return filter->ret;
2654
}
2655
2656
if (line[0] == '\\') {
2655
- if (s->pending_rm_count)
2656
- strbuf_add(&s->pending_rm, line, len);
2657
- else if (s->rhunk_active)
2658
- strbuf_add(&s->rhunk, line, len);
2657
+ if (filter->pending_rm_count)
2658
+ strbuf_add(&filter->pending_rm, line, len);
2659
+ else if (filter->hunk.active)
2660
+ strbuf_add(&filter->hunk.lines, line, len);
2661
/* otherwise outside tracked range; drop silently */
2660
- return s->ret;
2662
+ return filter->ret;
2663
}
2664
2665
if (line[0] != '+' && line[0] != ' ')
2666
BUG("unexpected diff line type '%c'", line[0]);
2667
2666
- lno_0 = s->lno_post - 1;
2667
- cur_pre = s->lno_pre; /* save before advancing for context lines */
2668
- s->lno_post++;
2668
+ idx_in_postimage = filter->lno_in_postimage - 1;
2669
+ cur_pre = filter->lno_in_preimage; /* save before advancing for context lines */
2670
+ filter->lno_in_postimage++;
2671
if (line[0] == ' ')
2670
- s->lno_pre++;
2672
+ filter->lno_in_preimage++;
2673
2674
/* Advance past ranges we've passed */
2673
- while (s->cur_range < s->ranges->nr &&
2674
- lno_0 >= s->ranges->ranges[s->cur_range].end) {
2675
- if (s->rhunk_active)
2676
- flush_rhunk(s);
2677
- discard_pending_rm(s);
2678
- s->cur_range++;
2675
+ while (filter->cur_range < filter->ranges->nr &&
2676
+ idx_in_postimage >= filter->ranges->ranges[filter->cur_range].end) {
2677
+ if (filter->hunk.active)
2678
+ flush_range_hunk(filter);
2679
+ discard_pending_rm(filter);
2680
+ filter->cur_range++;
2681
}
2682
2683
/* Past all ranges */
2682
- if (s->cur_range >= s->ranges->nr) {
2683
- discard_pending_rm(s);
2684
- return s->ret;
2684
+ if (filter->cur_range >= filter->ranges->nr) {
2685
+ discard_pending_rm(filter);
2686
+ return filter->ret;
2687
}
2688
2687
- cur = &s->ranges->ranges[s->cur_range];
2689
+ cur = &filter->ranges->ranges[filter->cur_range];
2690
2691
/* Before current range */
2690
- if (lno_0 < cur->start) {
2691
- discard_pending_rm(s);
2692
- return s->ret;
2692
+ if (idx_in_postimage < cur->start) {
2693
+ discard_pending_rm(filter);
2694
+ return filter->ret;
2695
}
2696
2697
/* In range so start a new range hunk if needed */
2696
- if (!s->rhunk_active) {
2697
- s->rhunk_active = 1;
2698
- s->rhunk_has_changes = 0;
2699
- s->rhunk_new_begin = lno_0 + 1;
2700
- s->rhunk_old_begin = s->pending_rm_count
2701
- ? s->pending_rm_pre_begin : cur_pre;
2702
- s->rhunk_old_count = 0;
2703
- s->rhunk_new_count = 0;
2704
- strbuf_reset(&s->rhunk);
2698
+ if (!filter->hunk.active) {
2699
+ filter->hunk.active = 1;
2700
+ filter->hunk.has_changes = 0;
2701
+ filter->hunk.new_begin = idx_in_postimage + 1;
2702
+ filter->hunk.old_begin = filter->pending_rm_count
2703
+ ? filter->pending_rm_pre_begin : cur_pre;
2704
+ filter->hunk.old_count = 0;
2705
+ filter->hunk.new_count = 0;
2706
+ strbuf_reset(&filter->hunk.lines);
2707
}
2708
2709
/* Flush pending removals into range hunk */
2708
- if (s->pending_rm_count) {
2709
- strbuf_addbuf(&s->rhunk, &s->pending_rm);
2710
- s->rhunk_old_count += s->pending_rm_count;
2711
- s->rhunk_has_changes = 1;
2712
- discard_pending_rm(s);
2710
+ if (filter->pending_rm_count) {
2711
+ strbuf_addbuf(&filter->hunk.lines, &filter->pending_rm);
2712
+ filter->hunk.old_count += filter->pending_rm_count;
2713
+ filter->hunk.has_changes = 1;
2714
+ discard_pending_rm(filter);
2715
}
2716
2715
- strbuf_add(&s->rhunk, line, len);
2716
- s->rhunk_new_count++;
2717
+ strbuf_add(&filter->hunk.lines, line, len);
2718
+ filter->hunk.new_count++;
2719
if (line[0] == '+')
2718
- s->rhunk_has_changes = 1;
2720
+ filter->hunk.has_changes = 1;
2721
else
2720
- s->rhunk_old_count++;
2722
+ filter->hunk.old_count++;
2723
2722
- return s->ret;
2724
+ return filter->ret;
2725
}
2726
2727
static void pprint_rename(struct strbuf *name, const char *a, const char *b)
4088
xdi_diff_outf(&mf1, &mf2, NULL, quick_consume,
4089
&ecbdata, &xpp, &xecfg);
4090
} else if (line_ranges) {
4089
- struct line_range_callback lr_state;
4091
+ struct line_range_filter lr_state;
4092
unsigned int i;
4093
long max_span = 0;
4094
4096
lr_state.orig_line_fn = fn_out_consume;
4097
lr_state.orig_cb_data = &ecbdata;
4098
lr_state.ranges = line_ranges;
4097
- strbuf_init(&lr_state.rhunk, 0);
4099
+ strbuf_init(&lr_state.hunk.lines, 0);
4100
strbuf_init(&lr_state.pending_rm, 0);
4101
4102
/*
4127
die("unable to generate diff for %s",
4128
one->path);
4129
4128
- flush_rhunk(&lr_state);
4130
+ flush_range_hunk(&lr_state);
4131
if (lr_state.ret)
4132
die("unable to generate diff for %s",
4133
one->path);
4132
- strbuf_release(&lr_state.rhunk);
4134
+ strbuf_release(&lr_state.hunk.lines);
4135
strbuf_release(&lr_state.pending_rm);
4136
} else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
4137
&ecbdata, &xpp, &xecfg))