Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
perf: compare multiple bytes at once in strcasechr
Browse files Browse the repository at this point in the history
This merges jhawthorn/fzy#174 into the the
embedded fzy UI.
  • Loading branch information
vigoux committed Sep 18, 2022
1 parent 3914085 commit e3ed57f
Showing 1 changed file with 42 additions and 13 deletions.
55 changes: 42 additions & 13 deletions lua/fzy/match.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "match.h"
#include "bonus.h"

#include "config.h"

char *strcasechr(const char *s, char c) {
const char accept[3] = {c, toupper(c), 0};
return strpbrk(s, accept);
typedef uint32_t long_t;
long_t *ws = NULL, w;
char u = toupper(c);
c = tolower(c);
if (c & 0x80) /* utf-8 bytes searched literally */
return strchr(s, c);
chr:
for (; ws || (uintptr_t)s % sizeof(long_t); s++) {
if (*s == '\0')
return NULL;
else if (*s == c)
return (char *)s;
else if (*s == u)
return (char *)s;
};
const long_t magic = (long_t) ~(-1ul / 0xff << 7);
const long_t cm = -1ul / 0xff * c;
const long_t um = -1ul / 0xff * u;
for (ws = (long_t *)s;; s = (char *)++ws) {
w = (*ws | (*ws & ~magic) / 2) & magic;
w = (w + magic) & ((w ^ cm) + magic) & ((w ^ um) + magic);
if (w ^ ~magic)
goto chr;
};
}

int has_match(const char *needle, const char *haystack) {
Expand All @@ -28,7 +51,12 @@ int has_match(const char *needle, const char *haystack) {
return 1;
}

#define SWAP(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)
#define SWAP(x, y, T) \
do { \
T SWAP = x; \
x = y; \
y = SWAP; \
} while (0)

#define max(a, b) (((a) > (b)) ? (a) : (b))

Expand All @@ -52,7 +80,8 @@ static void precompute_bonus(const char *haystack, score_t *match_bonus) {
}
}

static void setup_match_struct(struct match_struct *match, const char *needle, const char *haystack) {
static void setup_match_struct(struct match_struct *match, const char *needle,
const char *haystack) {
match->needle_len = strlen(needle);
match->haystack_len = strlen(haystack);

Expand All @@ -69,7 +98,8 @@ static void setup_match_struct(struct match_struct *match, const char *needle, c
precompute_bonus(haystack, match->match_bonus);
}

static inline void match_row(const struct match_struct *match, int row, score_t *curr_D, score_t *curr_M, const score_t *last_D, const score_t *last_M) {
static inline void match_row(const struct match_struct *match, int row, score_t *curr_D,
score_t *curr_M, const score_t *last_D, const score_t *last_M) {
int n = match->needle_len;
int m = match->haystack_len;
int i = row;
Expand All @@ -87,11 +117,10 @@ static inline void match_row(const struct match_struct *match, int row, score_t
if (!i) {
score = (j * SCORE_GAP_LEADING) + match_bonus[j];
} else if (j) { /* i > 0 && j > 0*/
score = max(
last_M[j - 1] + match_bonus[j],
score = max(last_M[j - 1] + match_bonus[j],

/* consecutive match, doesn't stack with match_bonus */
last_D[j - 1] + SCORE_MATCH_CONSECUTIVE);
/* consecutive match, doesn't stack with match_bonus */
last_D[j - 1] + SCORE_MATCH_CONSECUTIVE);
}
curr_D[j] = score;
curr_M[j] = prev_score = max(score, prev_score + gap_score);
Expand Down Expand Up @@ -183,7 +212,7 @@ score_t match_positions(const char *needle, const char *haystack, size_t *positi
* D[][] Stores the best score for this position ending with a match.
* M[][] Stores the best possible score at this position.
*/
score_t (*D)[MATCH_MAX_LEN], (*M)[MATCH_MAX_LEN];
score_t(*D)[MATCH_MAX_LEN], (*M)[MATCH_MAX_LEN];
M = malloc(sizeof(score_t) * MATCH_MAX_LEN * n);
D = malloc(sizeof(score_t) * MATCH_MAX_LEN * n);

Expand Down

0 comments on commit e3ed57f

Please sign in to comment.