aboutsummaryrefslogtreecommitdiff
path: root/dfm.c
diff options
context:
space:
mode:
authorDylan Araps <dylan.araps@gmail.com>2026-03-02 06:52:56 +0200
committerDylan Araps <dylan.araps@gmail.com>2026-03-02 06:52:56 +0200
commit82a27c3530ea452858ceb462b7c663576fa68f20 (patch)
treefdefcf75d130c4ef3ec3cee29d8e45d772ea9e6b /dfm.c
parent8ed17a9a7a9ac21c7685815cf7679e0d4e9fe614 (diff)
draw: only sanitize if needed
Skips a loop over every byte in draw.
Diffstat (limited to 'dfm.c')
-rw-r--r--dfm.c95
1 files changed, 75 insertions, 20 deletions
diff --git a/dfm.c b/dfm.c
index b3be6bd..19d1043 100644
--- a/dfm.c
+++ b/dfm.c
@@ -253,7 +253,7 @@ enum {
#define ENT_IS_DIR(t) ((t) <= ENT_LNK_DIR)
#define ENT_UTF8 0, 1
-#define ENT_FREE 1, 1
+#define ENT_CTRL 1, 1
#define ENT_LOC 2, 16
#define ENT_LEN 18, 8
#define ENT_SIZE 26, 12
@@ -434,42 +434,87 @@ ent_map_stat_size(u64 *e, const struct stat *s)
}
static inline usize
-ent_name_len(const char *s, u8 *utf8)
+ent_name_len(const char *s, u8 *utf8, u8 *ctrl)
{
const unsigned char *m = (const unsigned char *)s;
const unsigned char *p = m;
*utf8 = 0;
+ *ctrl = 0;
#ifdef __GNUC__
typedef size_t __attribute__((__may_alias__)) W;
- #define ONES ((size_t)-1 / UCHAR_MAX)
+ #define ONES ((size_t)-1 / UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
+ #define HAS_NUL(v) (((v) - ONES) & ~(v) & HIGHS)
+ #define HAS_HIGH(v) ((v) & HIGHS)
+ #define HAS_BYTE_LT(v,n) (((v) - ONES*(n)) & ~(v) & HIGHS)
+ #define HAS_BYTE_EQ(v,c) HAS_BYTE_LT((v) ^ (ONES*(c)), 1)
+ #define HAS_CTRL(v) (HAS_BYTE_LT(v, 0x20) | HAS_BYTE_EQ(v, 0x7f))
for (; (uintptr_t)p % sizeof(W); p++) {
- if (!*p) return (size)(p - m);
- if (*p & 0x80) { *utf8 = 1; goto done; }
+ unsigned char b = *p;
+ if (!b) return (size)(p - m);
+ if (b & 0x80) { *utf8 = 1; goto done; }
+ if (b < 0x20 || b == 0x7f) {
+ *ctrl = 1;
+ if (*utf8) goto done;
+ }
}
for (const W *w = (const void *)p;; w++) {
W v = *w;
- if ((v & HIGHS) | ((v - ONES) & ~v & HIGHS)) {
+ if (HAS_HIGH(v) | HAS_NUL(v)) {
p = (const unsigned char *)w;
for (;; p++) {
- if (!*p) return (size)(p - m);
- if (*p & 0x80) { *utf8 = 1; goto done; }
+ unsigned char b = *p;
+ if (!b) return (size)(p - m);
+ if (b & 0x80) { *utf8 = 1; goto done; }
+ if (b < 0x20 || b == 0x7f) {
+ *ctrl = 1;
+ if (*utf8) goto done;
+ }
}
}
+ if (!*ctrl && HAS_CTRL(v)) *ctrl = 1;
}
#endif
for (;;) {
unsigned char b = *p;
if (!b) return (size)(p - m);
- if (b & 0x80) { *utf8 = 1; break; }
+ if (b & 0x80) { *utf8 = 1; goto done; }
+ if (b < 0x20 || b == 0x7f) {
+ *ctrl = 1;
+ if (*utf8) goto done;
+ }
p++;
}
done:
+ if (*ctrl) goto len;
+ for (p++;;) {
+#ifdef __GNUC__
+ for (; (uintptr_t)p % sizeof(W); p++) {
+ if (!*p) return (size)(p - m);
+ if (*p < 0x20 || *p == 0x7f) { *ctrl = 1; goto len; }
+ }
+ for (const W *w = (const void *)p;; w++) {
+ W v = *w;
+ if (HAS_NUL(v)) {
+ p = (const unsigned char *)w;
+ for (; *p; p++)
+ if (*p < 0x20 || *p == 0x7f) { *ctrl = 1; goto len; }
+ return (size)(p - m);
+ }
+ if (HAS_CTRL(v)) { *ctrl = 1; goto len; }
+ }
+#endif
+ if (!*p) return (size)(p - m);
+ if (*p < 0x20 || *p == 0x7f) { *ctrl = 1; goto len; }
+ p++;
+ }
+len:
for (p++;;) {
#ifdef __GNUC__
- for (; (uintptr_t)p % sizeof(W); p++) if (!*p) return (size)(p - m);
+ for (; (uintptr_t)p % sizeof(W); p++)
+ if (!*p) return (size)(p - m);
for (const W *w = (const void *)p;; w++) {
- if ((*w - ONES) & ~*w & HIGHS) {
+ if (HAS_NUL(*w)) {
p = (const unsigned char *)w;
for (; *p; p++);
return (size)(p - m);
@@ -1105,7 +1150,7 @@ fm_draw_flush(struct fm *p)
}
static inline void
-fm_draw_name_tail(str *s, const char *n, usize l, usize dr, int utf8)
+fm_draw_name_tail(str *s, const char *n, usize l, usize dr, int utf8, int ctrl)
{
usize mtc = dr > DFM_TRUNC_WIDTH ? dr - DFM_TRUNC_WIDTH : 0;
usize c = MIN(mtc, DFM_TRUNC_LEN);
@@ -1130,7 +1175,8 @@ fm_draw_name_tail(str *s, const char *n, usize l, usize dr, int utf8)
if (dr <= tc + tc + DFM_TRUNC_WIDTH) return;
vt_cub(s, tc + DFM_TRUNC_WIDTH + 1);
STR_PUSH(s, DFM_TRUNC_STR);
- str_push_sanitize(s, n + t, l - t);
+ if (ctrl) str_push_sanitize(s, n + t, l - t);
+ else str_push(s, n + t, l - t);
}
static inline usize
@@ -1138,16 +1184,19 @@ fm_draw_name_ellipsis(struct fm *p, u64 m, const char *n, usize l, usize c)
{
if (c < 2) return 0;
c--;
+ int ct = ent_get(m, CTRL);
if (!ent_get(m, UTF8)) {
usize d = MIN(l, c);
- str_push_sanitize(&p->io, n, d);
- if (l > d) fm_draw_name_tail(&p->io, n, l, d + 1, 0);
+ if (ct) str_push_sanitize(&p->io, n, d);
+ else str_push(&p->io, n, d);
+ if (l > d) fm_draw_name_tail(&p->io, n, l, d + 1, 0, ct);
return d;
}
usize dr;
usize tl = fm_cache_trunc_utf8(p, n, l, c, &dr);
- str_push_sanitize(&p->io, n, tl);
- if (tl < l) fm_draw_name_tail(&p->io, n, l, dr, 1);
+ if (ct) str_push_sanitize(&p->io, n, tl);
+ else str_push(&p->io, n, tl);
+ if (tl < l) fm_draw_name_tail(&p->io, n, l, dr, 1, ct);
return dr;
}
@@ -1209,7 +1258,9 @@ fm_draw_ent(struct fm *p, usize n)
if (sl) {
dn = &p->de[o + l + 2];
vw = fm_cache_trunc(p, dn[-1], dn, sl, vw);
- str_push_sanitize(&p->io, dn, vw);
+ int ct = ent_get(dn[-1], CTRL);
+ if (ct) str_push_sanitize(&p->io, dn, vw);
+ else str_push(&p->io, dn, vw);
} else
str_push_c(&p->io, '?');
}
@@ -1868,7 +1919,8 @@ fm_dir_load_ent(struct fm *p, const char *s)
return -1;
u8 utf8;
- u8 l = (u8)ent_name_len(s, &utf8);
+ u8 ctrl;
+ u8 l = (u8)ent_name_len(s, &utf8, &ctrl);
if (unlikely(p->del + sizeof(u64) + l + 1 >= p->dec))
return -1;
@@ -1883,6 +1935,7 @@ fm_dir_load_ent(struct fm *p, const char *s)
ent_set(&m, LEN, l);
ent_set(&m, LOC, (u16)p->dl);
ent_set(&m, UTF8, utf8);
+ ent_set(&m, CTRL, ctrl);
memcpy(p->de + p->del + sizeof(m), s, l + 1);
p->del += sizeof(m) + l + 1;
@@ -1910,9 +1963,11 @@ fm_dir_load_ent(struct fm *p, const char *s)
ssize_t r = readlinkat(p->dfd, s, lm, st.st_size);
if (likely(r != -1)) {
u8 lu;
- ent_name_len(lm, &lu);
+ u8 ct;
+ ent_name_len(lm, &lu, &ct);
u8 f = 0;
lnk_set(&f, UTF8, lu);
+ lnk_set(&f, CTRL, ct);
lm[-1] = f;
lm[ll] = 0;
p->del += ll + 2;