ref-filter: introduce enum atom_type

In the original ref-filter design, it will copy the parsed atom's name and attributes to `used_atom[i].name` in the atom's parsing step, and use it again for string matching in the later specific ref attributes filling step. It use a lot of string matching to determine which atom we need. Introduce the enum "atom_type", each enum value is named as `ATOM_*`, which is the index of each corresponding valid_atom entry. In the first step of the atom parsing, `used_atom.atom_type` will record corresponding enum value from valid_atom entry index, and then in specific reference attribute filling step, only need to compare the value of the `used_atom[i].atom_type` to check the atom type. Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Christian Couder <christian.couder@gmail.com> Signed-off-by: ZheNing Hu <adlternative@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

ZheNing Hu committed May 13, 2021 at 15:15 UTC 1197f1a46360d3ae96bd9c15908a3a6f8e562207
1 file changed +128 -69
ref-filter.c
+128 -69
@@ -108,6 +108,56 @@ static struct ref_to_worktree_map {
108 struct worktree **worktrees;
109 } ref_to_worktree_map;
110
111 +/*
112 + * The enum atom_type is used as the index of valid_atom array.
113 + * In the atom parsing stage, it will be passed to used_atom.atom_type
114 + * as the identifier of the atom type. We can check the type of used_atom
115 + * entry by `if (used_atom[i].atom_type == ATOM_*)`.
116 + */
117 +enum atom_type {
118 + ATOM_REFNAME,
119 + ATOM_OBJECTTYPE,
120 + ATOM_OBJECTSIZE,
121 + ATOM_OBJECTNAME,
122 + ATOM_DELTABASE,
123 + ATOM_TREE,
124 + ATOM_PARENT,
125 + ATOM_NUMPARENT,
126 + ATOM_OBJECT,
127 + ATOM_TYPE,
128 + ATOM_TAG,
129 + ATOM_AUTHOR,
130 + ATOM_AUTHORNAME,
131 + ATOM_AUTHOREMAIL,
132 + ATOM_AUTHORDATE,
133 + ATOM_COMMITTER,
134 + ATOM_COMMITTERNAME,
135 + ATOM_COMMITTEREMAIL,
136 + ATOM_COMMITTERDATE,
137 + ATOM_TAGGER,
138 + ATOM_TAGGERNAME,
139 + ATOM_TAGGEREMAIL,
140 + ATOM_TAGGERDATE,
141 + ATOM_CREATOR,
142 + ATOM_CREATORDATE,
143 + ATOM_SUBJECT,
144 + ATOM_BODY,
145 + ATOM_TRAILERS,
146 + ATOM_CONTENTS,
147 + ATOM_UPSTREAM,
148 + ATOM_PUSH,
149 + ATOM_SYMREF,
150 + ATOM_FLAG,
151 + ATOM_HEAD,
152 + ATOM_COLOR,
153 + ATOM_WORKTREEPATH,
154 + ATOM_ALIGN,
155 + ATOM_END,
156 + ATOM_IF,
157 + ATOM_THEN,
158 + ATOM_ELSE,
159 +};
160 +
161 /*
162 * An atom is a valid field atom listed below, possibly prefixed with
163 * a "*" to denote deref_tag().
@@ -119,6 +169,7 @@ static struct ref_to_worktree_map {
169 * array.
170 */
171 static struct used_atom {
172 + enum atom_type atom_type;
173 const char *name;
174 cmp_type type;
175 info_source source;
@@ -506,47 +557,47 @@ static struct {
557 int (*parser)(const struct ref_format *format, struct used_atom *atom,
558 const char *arg, struct strbuf *err);
559 } valid_atom[] = {
509 - { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
510 - { "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
511 - { "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
512 - { "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser },
513 - { "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser },
514 - { "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
515 - { "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
516 - { "numparent", SOURCE_OBJ, FIELD_ULONG },
517 - { "object", SOURCE_OBJ },
518 - { "type", SOURCE_OBJ },
519 - { "tag", SOURCE_OBJ },
520 - { "author", SOURCE_OBJ },
521 - { "authorname", SOURCE_OBJ },
522 - { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
523 - { "authordate", SOURCE_OBJ, FIELD_TIME },
524 - { "committer", SOURCE_OBJ },
525 - { "committername", SOURCE_OBJ },
526 - { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
527 - { "committerdate", SOURCE_OBJ, FIELD_TIME },
528 - { "tagger", SOURCE_OBJ },
529 - { "taggername", SOURCE_OBJ },
530 - { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
531 - { "taggerdate", SOURCE_OBJ, FIELD_TIME },
532 - { "creator", SOURCE_OBJ },
533 - { "creatordate", SOURCE_OBJ, FIELD_TIME },
534 - { "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
535 - { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
536 - { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
537 - { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
538 - { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
539 - { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
540 - { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
541 - { "flag", SOURCE_NONE },
542 - { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
543 - { "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
544 - { "worktreepath", SOURCE_NONE },
545 - { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
546 - { "end", SOURCE_NONE },
547 - { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
548 - { "then", SOURCE_NONE },
549 - { "else", SOURCE_NONE },
560 + [ATOM_REFNAME] = { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
561 + [ATOM_OBJECTTYPE] = { "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser },
562 + [ATOM_OBJECTSIZE] = { "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser },
563 + [ATOM_OBJECTNAME] = { "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser },
564 + [ATOM_DELTABASE] = { "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser },
565 + [ATOM_TREE] = { "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
566 + [ATOM_PARENT] = { "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser },
567 + [ATOM_NUMPARENT] = { "numparent", SOURCE_OBJ, FIELD_ULONG },
568 + [ATOM_OBJECT] = { "object", SOURCE_OBJ },
569 + [ATOM_TYPE] = { "type", SOURCE_OBJ },
570 + [ATOM_TAG] = { "tag", SOURCE_OBJ },
571 + [ATOM_AUTHOR] = { "author", SOURCE_OBJ },
572 + [ATOM_AUTHORNAME] = { "authorname", SOURCE_OBJ },
573 + [ATOM_AUTHOREMAIL] = { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
574 + [ATOM_AUTHORDATE] = { "authordate", SOURCE_OBJ, FIELD_TIME },
575 + [ATOM_COMMITTER] = { "committer", SOURCE_OBJ },
576 + [ATOM_COMMITTERNAME] = { "committername", SOURCE_OBJ },
577 + [ATOM_COMMITTEREMAIL] = { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
578 + [ATOM_COMMITTERDATE] = { "committerdate", SOURCE_OBJ, FIELD_TIME },
579 + [ATOM_TAGGER] = { "tagger", SOURCE_OBJ },
580 + [ATOM_TAGGERNAME] = { "taggername", SOURCE_OBJ },
581 + [ATOM_TAGGEREMAIL] = { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
582 + [ATOM_TAGGERDATE] = { "taggerdate", SOURCE_OBJ, FIELD_TIME },
583 + [ATOM_CREATOR] = { "creator", SOURCE_OBJ },
584 + [ATOM_CREATORDATE] = { "creatordate", SOURCE_OBJ, FIELD_TIME },
585 + [ATOM_SUBJECT] = { "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
586 + [ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
587 + [ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
588 + [ATOM_CONTENTS] = { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
589 + [ATOM_UPSTREAM] = { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
590 + [ATOM_PUSH] = { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
591 + [ATOM_SYMREF] = { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
592 + [ATOM_FLAG] = { "flag", SOURCE_NONE },
593 + [ATOM_HEAD] = { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
594 + [ATOM_COLOR] = { "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
595 + [ATOM_WORKTREEPATH] = { "worktreepath", SOURCE_NONE },
596 + [ATOM_ALIGN] = { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
597 + [ATOM_END] = { "end", SOURCE_NONE },
598 + [ATOM_IF] = { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
599 + [ATOM_THEN] = { "then", SOURCE_NONE },
600 + [ATOM_ELSE] = { "else", SOURCE_NONE },
601 /*
602 * Please update $__git_ref_fieldlist in git-completion.bash
603 * when you add new atoms
@@ -628,6 +679,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,
679 at = used_atom_cnt;
680 used_atom_cnt++;
681 REALLOC_ARRAY(used_atom, used_atom_cnt);
682 + used_atom[at].atom_type = i;
683 used_atom[at].name = xmemdupz(atom, ep - atom);
684 used_atom[at].type = valid_atom[i].cmp_type;
685 used_atom[at].source = valid_atom[i].source;
@@ -652,7 +704,7 @@ static int parse_ref_filter_atom(const struct ref_format *format,
704 return -1;
705 if (*atom == '*')
706 need_tagged = 1;
655 - if (!strcmp(valid_atom[i].name, "symref"))
707 + if (i == ATOM_SYMREF)
708 need_symref = 1;
709 return at;
710 }
@@ -965,14 +1017,15 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
1017
1018 for (i = 0; i < used_atom_cnt; i++) {
1019 const char *name = used_atom[i].name;
1020 + enum atom_type atom_type = used_atom[i].atom_type;
1021 struct atom_value *v = &val[i];
1022 if (!!deref != (*name == '*'))
1023 continue;
1024 if (deref)
1025 name++;
973 - if (!strcmp(name, "objecttype"))
1026 + if (atom_type == ATOM_OBJECTTYPE)
1027 v->s = xstrdup(type_name(oi->type));
975 - else if (starts_with(name, "objectsize")) {
1028 + else if (atom_type == ATOM_OBJECTSIZE) {
1029 if (used_atom[i].u.objectsize.option == O_SIZE_DISK) {
1030 v->value = oi->disk_size;
1031 v->s = xstrfmt("%"PRIuMAX, (uintmax_t)oi->disk_size);
@@ -980,9 +1033,9 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
1033 v->value = oi->size;
1034 v->s = xstrfmt("%"PRIuMAX , (uintmax_t)oi->size);
1035 }
983 - } else if (!strcmp(name, "deltabase"))
1036 + } else if (atom_type == ATOM_DELTABASE)
1037 v->s = xstrdup(oid_to_hex(&oi->delta_base_oid));
985 - else if (deref)
1038 + else if (atom_type == ATOM_OBJECTNAME && deref)
1039 grab_oid(name, "objectname", &oi->oid, v, &used_atom[i]);
1040 }
1041 }
@@ -995,16 +1048,17 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
1048
1049 for (i = 0; i < used_atom_cnt; i++) {
1050 const char *name = used_atom[i].name;
1051 + enum atom_type atom_type = used_atom[i].atom_type;
1052 struct atom_value *v = &val[i];
1053 if (!!deref != (*name == '*'))
1054 continue;
1055 if (deref)
1056 name++;
1003 - if (!strcmp(name, "tag"))
1057 + if (atom_type == ATOM_TAG)
1058 v->s = xstrdup(tag->tag);
1005 - else if (!strcmp(name, "type") && tag->tagged)
1059 + else if (atom_type == ATOM_TYPE && tag->tagged)
1060 v->s = xstrdup(type_name(tag->tagged->type));
1007 - else if (!strcmp(name, "object") && tag->tagged)
1061 + else if (atom_type == ATOM_OBJECT && tag->tagged)
1062 v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
1063 }
1064 }
@@ -1017,18 +1071,20 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
1071
1072 for (i = 0; i < used_atom_cnt; i++) {
1073 const char *name = used_atom[i].name;
1074 + enum atom_type atom_type = used_atom[i].atom_type;
1075 struct atom_value *v = &val[i];
1076 if (!!deref != (*name == '*'))
1077 continue;
1078 if (deref)
1079 name++;
1025 - if (grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
1080 + if (atom_type == ATOM_TREE &&
1081 + grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
1082 continue;
1027 - if (!strcmp(name, "numparent")) {
1083 + if (atom_type == ATOM_NUMPARENT) {
1084 v->value = commit_list_count(commit->parents);
1085 v->s = xstrfmt("%lu", (unsigned long)v->value);
1086 }
1031 - else if (starts_with(name, "parent")) {
1087 + else if (atom_type == ATOM_PARENT) {
1088 struct commit_list *parents;
1089 struct strbuf s = STRBUF_INIT;
1090 for (parents = commit->parents; parents; parents = parents->next) {
@@ -1208,15 +1264,16 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
1264 return;
1265 for (i = 0; i < used_atom_cnt; i++) {
1266 const char *name = used_atom[i].name;
1267 + enum atom_type atom_type = used_atom[i].atom_type;
1268 struct atom_value *v = &val[i];
1269 if (!!deref != (*name == '*'))
1270 continue;
1271 if (deref)
1272 name++;
1273
1217 - if (starts_with(name, "creatordate"))
1274 + if (atom_type == ATOM_CREATORDATE)
1275 grab_date(wholine, v, name);
1219 - else if (!strcmp(name, "creator"))
1276 + else if (atom_type == ATOM_CREATOR)
1277 v->s = copy_line(wholine);
1278 }
1279 }
@@ -1696,6 +1753,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1753 /* Fill in specials first */
1754 for (i = 0; i < used_atom_cnt; i++) {
1755 struct used_atom *atom = &used_atom[i];
1756 + enum atom_type atom_type = atom->atom_type;
1757 const char *name = used_atom[i].name;
1758 struct atom_value *v = &ref->value[i];
1759 int deref = 0;
@@ -1710,18 +1768,18 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1768 name++;
1769 }
1770
1713 - if (starts_with(name, "refname"))
1771 + if (atom_type == ATOM_REFNAME)
1772 refname = get_refname(atom, ref);
1715 - else if (!strcmp(name, "worktreepath")) {
1773 + else if (atom_type == ATOM_WORKTREEPATH) {
1774 if (ref->kind == FILTER_REFS_BRANCHES)
1775 v->s = get_worktree_path(atom, ref);
1776 else
1777 v->s = xstrdup("");
1778 continue;
1779 }
1722 - else if (starts_with(name, "symref"))
1780 + else if (atom_type == ATOM_SYMREF)
1781 refname = get_symref(atom, ref);
1724 - else if (starts_with(name, "upstream")) {
1782 + else if (atom_type == ATOM_UPSTREAM) {
1783 const char *branch_name;
1784 /* only local branches may have an upstream */
1785 if (!skip_prefix(ref->refname, "refs/heads/",
@@ -1737,7 +1795,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1795 else
1796 v->s = xstrdup("");
1797 continue;
1740 - } else if (atom->u.remote_ref.push) {
1798 + } else if (atom_type == ATOM_PUSH && atom->u.remote_ref.push) {
1799 const char *branch_name;
1800 v->s = xstrdup("");
1801 if (!skip_prefix(ref->refname, "refs/heads/",
@@ -1756,10 +1814,10 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1814 free((char *)v->s);
1815 fill_remote_ref_details(atom, refname, branch, &v->s);
1816 continue;
1759 - } else if (starts_with(name, "color:")) {
1817 + } else if (atom_type == ATOM_COLOR) {
1818 v->s = xstrdup(atom->u.color);
1819 continue;
1762 - } else if (!strcmp(name, "flag")) {
1820 + } else if (atom_type == ATOM_FLAG) {
1821 char buf[256], *cp = buf;
1822 if (ref->flag & REF_ISSYMREF)
1823 cp = copy_advance(cp, ",symref");
@@ -1772,23 +1830,24 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1830 v->s = xstrdup(buf + 1);
1831 }
1832 continue;
1775 - } else if (!deref && grab_oid(name, "objectname", &ref->objectname, v, atom)) {
1776 - continue;
1777 - } else if (!strcmp(name, "HEAD")) {
1833 + } else if (!deref && atom_type == ATOM_OBJECTNAME &&
1834 + grab_oid(name, "objectname", &ref->objectname, v, atom)) {
1835 + continue;
1836 + } else if (atom_type == ATOM_HEAD) {
1837 if (atom->u.head && !strcmp(ref->refname, atom->u.head))
1838 v->s = xstrdup("*");
1839 else
1840 v->s = xstrdup(" ");
1841 continue;
1783 - } else if (starts_with(name, "align")) {
1842 + } else if (atom_type == ATOM_ALIGN) {
1843 v->handler = align_atom_handler;
1844 v->s = xstrdup("");
1845 continue;
1787 - } else if (!strcmp(name, "end")) {
1846 + } else if (atom_type == ATOM_END) {
1847 v->handler = end_atom_handler;
1848 v->s = xstrdup("");
1849 continue;
1791 - } else if (starts_with(name, "if")) {
1850 + } else if (atom_type == ATOM_IF) {
1851 const char *s;
1852 if (skip_prefix(name, "if:", &s))
1853 v->s = xstrdup(s);
@@ -1796,11 +1855,11 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1855 v->s = xstrdup("");
1856 v->handler = if_atom_handler;
1857 continue;
1799 - } else if (!strcmp(name, "then")) {
1858 + } else if (atom_type == ATOM_THEN) {
1859 v->handler = then_atom_handler;
1860 v->s = xstrdup("");
1861 continue;
1803 - } else if (!strcmp(name, "else")) {
1862 + } else if (atom_type == ATOM_ELSE) {
1863 v->handler = else_atom_handler;
1864 v->s = xstrdup("");
1865 continue;