git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/6] diff: preparse --diff-filter string argument

From
Junio C Hamano <gitster@pobox.com>
Date
Jul 18, 2013, 00:30 UTC
Message-ID
<1374107406-14357-4-git-send-email-gitster@pobox.com>
In-Reply-To
<1374107406-14357-1-git-send-email-gitster@pobox.com>

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>
---
 diff.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 diff.h |  5 ++++-
 2 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/diff.c b/diff.c
index 0220c19..03f10e6 100644
--- a/diff.c
+++ b/diff.c
@@ -3496,6 +3496,53 @@ static int parse_submodule_opt(struct diff_options *options, const char *value)
 	return 1;
 }
 
+static const char diff_status_letters[] = {
+	DIFF_STATUS_ADDED,
+	DIFF_STATUS_COPIED,
+	DIFF_STATUS_DELETED,
+	DIFF_STATUS_MODIFIED,
+	DIFF_STATUS_RENAMED,
+	DIFF_STATUS_TYPE_CHANGED,
+	DIFF_STATUS_UNKNOWN,
+	DIFF_STATUS_UNMERGED,
+	DIFF_STATUS_FILTER_AON,
+	DIFF_STATUS_FILTER_BROKEN,
+	'\0',
+};
+
+static unsigned int filter_bit['Z' + 1];
+
+static void prepare_filter_bits(void)
+{
+	int i;
+
+	if (!filter_bit[DIFF_STATUS_ADDED]) {
+		for (i = 0; diff_status_letters[i]; i++)
+			filter_bit[(int) diff_status_letters[i]] = (1 << i);
+	}
+}
+
+static unsigned filter_bit_tst(char status, const struct diff_options *opt)
+{
+	return opt->filter & filter_bit[(int) status];
+}
+
+static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt)
+{
+	int i, optch;
+
+	prepare_filter_bits();
+	for (i = 0; (optch = optarg[i]) != '\0'; i++) {
+		unsigned int bit;
+
+		bit = (0 <= optch && optch <= 'Z') ? filter_bit[optch] : 0;
+		if (!bit)
+			continue; /* ignore unknown ones, like we always have */
+		opt->filter |= bit;
+	}
+	return 0;
+}
+
 int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 {
 	const char *arg = av[0];
@@ -3717,7 +3764,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		return argcount;
 	}
 	else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
-		options->filter = optarg;
+		int offending = parse_diff_filter_opt(optarg, options);
+		if (offending)
+			die("unknown change class '%c' in --diff-filter=%s",
+			    offending, optarg);
 		return argcount;
 	}
 	else if (!strcmp(arg, "--abbrev"))
@@ -4513,11 +4563,11 @@ static int match_filter(const struct diff_options *options, const struct diff_fi
 {
 	return (((p->status == DIFF_STATUS_MODIFIED) &&
 		 ((p->score &&
-		   strchr(options->filter, DIFF_STATUS_FILTER_BROKEN)) ||
+		   filter_bit_tst(DIFF_STATUS_FILTER_BROKEN, options)) ||
 		  (!p->score &&
-		   strchr(options->filter, DIFF_STATUS_MODIFIED)))) ||
+		   filter_bit_tst(DIFF_STATUS_MODIFIED, options)))) ||
 		((p->status != DIFF_STATUS_MODIFIED) &&
-		 strchr(options->filter, p->status)));
+		 filter_bit_tst(p->status, options)));
 }
 
 static void diffcore_apply_filter(struct diff_options *options)
@@ -4525,14 +4575,13 @@ static void diffcore_apply_filter(struct diff_options *options)
 	int i;
 	struct diff_queue_struct *q = &diff_queued_diff;
 	struct diff_queue_struct outq;
-	const char *filter = options->filter;
 
 	DIFF_QUEUE_CLEAR(&outq);
 
-	if (!filter)
+	if (!options->filter)
 		return;
 
-	if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
+	if (filter_bit_tst(DIFF_STATUS_FILTER_AON, options)) {
 		int found;
 		for (i = found = 0; !found && i < q->nr; i++) {
 			if (match_filter(options, q->queue[i]))
diff --git a/diff.h b/diff.h
index 78b4091..a367207 100644
--- a/diff.h
+++ b/diff.h
@@ -103,12 +103,15 @@ enum diff_words_type {
 };
 
 struct diff_options {
-	const char *filter;
 	const char *orderfile;
 	const char *pickaxe;
 	const char *single_follow;
 	const char *a_prefix, *b_prefix;
 	unsigned flags;
+
+	/* diff-filter bits */
+	unsigned int filter;
+
 	int use_color;
 	int context;
 	int interhunkcontext;
-- 
1.8.3.3-962-gf04df43
Previous: Junio C HamanoNext: Junio C Hamano
Message 15 of 25 in “daemon.c:handle: Remove unneeded check for null pointer.”
  1. 1/4 daemon.c:handle: Remove unneeded check for null pointer.Stefan Beller, Jul 14, 2013
  2. 2/4 commit: Fix a memory leak in determine_author_infoStefan Beller, Jul 14, 2013
  3. Jonathan NiederJul 14, 2013
  4. 3/4 diff-no-index: Remove unused variable.Stefan Beller, Jul 14, 2013
  5. Jonathan NiederJul 14, 2013
  6. 0/2 git diff -q option removalStefan Beller, Jul 16, 2013
  7. 1/2 diff --no-index: remove nonfunctional "-q" handlingStefan Beller, Jul 16, 2013
  8. 2/2 diff: Remove -q to stay silent on missing files.Stefan Beller, Jul 16, 2013
  9. Junio C HamanoJul 17, 2013
  10. Junio C HamanoJul 17, 2013
  11. Stefan BellerJul 17, 2013
  12. 0/6 Deprecating "diff-files -q"Junio C Hamano, Jul 18, 2013
  13. 1/6 diff: pass the whole diff_options to diffcore_apply_filter()Junio C Hamano, Jul 18, 2013
  14. 2/6 diff: factor out match_filter()Junio C Hamano, Jul 18, 2013
  15. 3/6 diff: preparse --diff-filter string argumentJunio C Hamano, Jul 18, 2013
  16. 4/6 diff: reject unknown change class given to --diff-filterJunio C Hamano, Jul 18, 2013
  17. 5/6 diff: allow lowercase letter to specify what change class to excludeJunio C Hamano, Jul 18, 2013
  18. 6/6 diff: deprecate -q option to diff-filesJunio C Hamano, Jul 18, 2013
  19. 7/6 diff: remove "diff-files -q" at Git 2.0 version boundaryJunio C Hamano, Jul 19, 2013
  20. Jonathan NiederJul 19, 2013
  21. Junio C HamanoJul 19, 2013
  22. Jonathan NiederJul 19, 2013
  23. 4/4 diff.c: Do not initialize a variable, which gets reassigned anyway.Stefan Beller, Jul 14, 2013
  24. Jonathan NiederJul 14, 2013
  25. Jonathan NiederJul 14, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.