Skip to content

Commit 1ecc1cb

Browse files
committed
diff: preparse --diff-filter string argument
Instead of running strchr() on the list of status characters over and over again, parse the --diff-filter option into bitfields and use the bits to see if the change to the filepair matches the status requested. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 08578fa commit 1ecc1cb

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

diff.c

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,6 +3496,53 @@ static int parse_submodule_opt(struct diff_options *options, const char *value)
34963496
return 1;
34973497
}
34983498

3499+
static const char diff_status_letters[] = {
3500+
DIFF_STATUS_ADDED,
3501+
DIFF_STATUS_COPIED,
3502+
DIFF_STATUS_DELETED,
3503+
DIFF_STATUS_MODIFIED,
3504+
DIFF_STATUS_RENAMED,
3505+
DIFF_STATUS_TYPE_CHANGED,
3506+
DIFF_STATUS_UNKNOWN,
3507+
DIFF_STATUS_UNMERGED,
3508+
DIFF_STATUS_FILTER_AON,
3509+
DIFF_STATUS_FILTER_BROKEN,
3510+
'\0',
3511+
};
3512+
3513+
static unsigned int filter_bit['Z' + 1];
3514+
3515+
static void prepare_filter_bits(void)
3516+
{
3517+
int i;
3518+
3519+
if (!filter_bit[DIFF_STATUS_ADDED]) {
3520+
for (i = 0; diff_status_letters[i]; i++)
3521+
filter_bit[(int) diff_status_letters[i]] = (1 << i);
3522+
}
3523+
}
3524+
3525+
static unsigned filter_bit_tst(char status, const struct diff_options *opt)
3526+
{
3527+
return opt->filter & filter_bit[(int) status];
3528+
}
3529+
3530+
static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt)
3531+
{
3532+
int i, optch;
3533+
3534+
prepare_filter_bits();
3535+
for (i = 0; (optch = optarg[i]) != '\0'; i++) {
3536+
unsigned int bit;
3537+
3538+
bit = (0 <= optch && optch <= 'Z') ? filter_bit[optch] : 0;
3539+
if (!bit)
3540+
continue; /* ignore unknown ones, like we always have */
3541+
opt->filter |= bit;
3542+
}
3543+
return 0;
3544+
}
3545+
34993546
int diff_opt_parse(struct diff_options *options, const char **av, int ac)
35003547
{
35013548
const char *arg = av[0];
@@ -3717,7 +3764,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
37173764
return argcount;
37183765
}
37193766
else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
3720-
options->filter = optarg;
3767+
int offending = parse_diff_filter_opt(optarg, options);
3768+
if (offending)
3769+
die("unknown change class '%c' in --diff-filter=%s",
3770+
offending, optarg);
37213771
return argcount;
37223772
}
37233773
else if (!strcmp(arg, "--abbrev"))
@@ -4513,26 +4563,25 @@ static int match_filter(const struct diff_options *options, const struct diff_fi
45134563
{
45144564
return (((p->status == DIFF_STATUS_MODIFIED) &&
45154565
((p->score &&
4516-
strchr(options->filter, DIFF_STATUS_FILTER_BROKEN)) ||
4566+
filter_bit_tst(DIFF_STATUS_FILTER_BROKEN, options)) ||
45174567
(!p->score &&
4518-
strchr(options->filter, DIFF_STATUS_MODIFIED)))) ||
4568+
filter_bit_tst(DIFF_STATUS_MODIFIED, options)))) ||
45194569
((p->status != DIFF_STATUS_MODIFIED) &&
4520-
strchr(options->filter, p->status)));
4570+
filter_bit_tst(p->status, options)));
45214571
}
45224572

45234573
static void diffcore_apply_filter(struct diff_options *options)
45244574
{
45254575
int i;
45264576
struct diff_queue_struct *q = &diff_queued_diff;
45274577
struct diff_queue_struct outq;
4528-
const char *filter = options->filter;
45294578

45304579
DIFF_QUEUE_CLEAR(&outq);
45314580

4532-
if (!filter)
4581+
if (!options->filter)
45334582
return;
45344583

4535-
if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
4584+
if (filter_bit_tst(DIFF_STATUS_FILTER_AON, options)) {
45364585
int found;
45374586
for (i = found = 0; !found && i < q->nr; i++) {
45384587
if (match_filter(options, q->queue[i]))

diff.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,15 @@ enum diff_words_type {
103103
};
104104

105105
struct diff_options {
106-
const char *filter;
107106
const char *orderfile;
108107
const char *pickaxe;
109108
const char *single_follow;
110109
const char *a_prefix, *b_prefix;
111110
unsigned flags;
111+
112+
/* diff-filter bits */
113+
unsigned int filter;
114+
112115
int use_color;
113116
int context;
114117
int interhunkcontext;

0 commit comments

Comments
 (0)