Skip to content

Commit

Permalink
Optimize git status parsing slightly.
Browse files Browse the repository at this point in the history
Instead of paying for multiple function calls and any string parsing at
all, use a fast integer that can fit at least two chars inside and
compare them directly.

We also move the struct and enum declarations into the only function
that uses them.

Also make the .s buffer for the resulting string smaller. It doesn't
need 64 chars.
  • Loading branch information
ericonr committed Jul 17, 2021
1 parent 2bf4d41 commit 11e4318
Showing 1 changed file with 19 additions and 16 deletions.
35 changes: 19 additions & 16 deletions git.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <limits.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
Expand Down Expand Up @@ -104,14 +106,6 @@ void *git_thread(void *arg)
return git_info;
}

struct statuses {
size_t c;
char s[64];
char format[3];
char prefix;
};
enum status_index { added, deleted, modified_unstaged, modified_staged, modified_both, untracked, status_index_n };

static void *get_git_status(void *arg)
{
struct git_info *git_info = arg;
Expand All @@ -120,13 +114,21 @@ static void *get_git_status(void *arg)
if (!f)
return NULL;

struct statuses g[status_index_n] = {
[added] = { .format = "A ", .prefix = '+' },
[deleted] = { .format = "D ", .prefix = '-' },
[modified_unstaged] = { .format = " M", .prefix = '~' },
[modified_staged] = { .format = "M ", .prefix = '>' },
[modified_both] = { .format = "MM", .prefix = '~' },
[untracked] = { .format = "??", .prefix = '+' },
typedef uint_fast16_t t_format;
#define FORMAT(s) (((t_format)(unsigned char)s[0]) | (((t_format)(unsigned char)s[1]) << CHAR_BIT))
enum status_index { added, deleted, modified_unstaged, modified_staged, modified_both, untracked, status_index_n };
struct statuses {
size_t c;
char s[32];
t_format format;
char prefix;
} g[status_index_n] = {
[added] = { .format = FORMAT("A "), .prefix = '+' },
[deleted] = { .format = FORMAT("D "), .prefix = '-' },
[modified_unstaged] = { .format = FORMAT(" M"), .prefix = '~' },
[modified_staged] = { .format = FORMAT("M "), .prefix = '>' },
[modified_both] = { .format = FORMAT("MM"), .prefix = '~' },
[untracked] = { .format = FORMAT("??"), .prefix = '+' },
};

char *line = NULL;
Expand All @@ -135,11 +137,12 @@ static void *get_git_status(void *arg)
while ((l = getdelim(&line, &n, 0, f)) != -1) {
if (l > 4) {
for (int i = 0; i < status_index_n; i++) {
g[i].c += !strncmp(g[i].format, line, 2);
g[i].c += FORMAT(line) == g[i].format;
}
}
}
free(line);
#undef FORMAT

/* cheat to display things closer to a "userful" measure */
g[added].c += g[modified_staged].c + g[modified_both].c;
Expand Down

0 comments on commit 11e4318

Please sign in to comment.