summaryrefslogtreecommitdiff
path: root/src/palette.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 19:22:05 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 19:22:05 +0300
commit01e1c61e9fcf4a0b0164a7fe5395a209a50f6905 (patch)
tree1f1eb33e49eab338650a42e8f602af75d8d28a24 /src/palette.c
parent2d02d39d2cd32e9eb559638865d2746f02c08556 (diff)
Optimize hot loops with direct access, LUTs, and closed-form formulas
Diffstat (limited to 'src/palette.c')
-rw-r--r--src/palette.c73
1 files changed, 52 insertions, 21 deletions
diff --git a/src/palette.c b/src/palette.c
index a8add4e..bfaba6c 100644
--- a/src/palette.c
+++ b/src/palette.c
@@ -133,13 +133,19 @@ static uint32_t *palette_slot(struct term_theme *p, const char *key,
const char *digits = key + 5;
if (!*digits || (*digits == '0' && digits[1]))
return NULL;
- int i = 0;
- for (const char *d = digits; *d; d++) {
- if (*d < '0' || *d > '9')
+ int i;
+ if (!digits[1]) {
+ if (digits[0] < '0' || digits[0] > '9')
return NULL;
- i = i * 10 + (*d - '0');
+ i = digits[0] - '0';
+ } else if (!digits[2]) {
+ if (digits[0] < '0' || digits[0] > '9' || digits[1] < '0' || digits[1] > '9')
+ return NULL;
+ i = (digits[0] - '0') * 10 + (digits[1] - '0');
if (i > 15)
return NULL;
+ } else {
+ return NULL;
}
*fallback = builtin_theme.ansi[i];
return &p->ansi[i];
@@ -166,19 +172,36 @@ bool term_theme_set_key(struct term_theme *p, const char *key, const char *val)
static bool parse_hex_channel(const char *s, size_t len, uint8_t *out)
{
- if (len == 0 || len > 4)
- return false;
- unsigned v = 0;
- for (size_t i = 0; i < len; i++) {
- int d = term_hex_nib(s[i]);
+ if (len == 2) {
+ int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]);
+ if ((d0 | d1) < 0)
+ return false;
+ *out = (uint8_t)((d0 << 4) | d1);
+ return true;
+ }
+ if (len == 1) {
+ int d = term_hex_nib(s[0]);
if (d < 0)
return false;
- v = (v << 4) | (unsigned)d;
+ *out = (uint8_t)(d * 17);
+ return true;
}
- static const unsigned max_for_len[5] = {0, 15, 255, 4095, 65535};
- unsigned max = max_for_len[len];
- *out = (uint8_t)((unsigned long)v * 255 / max);
- return true;
+ if (len == 4) {
+ int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]);
+ int d2 = term_hex_nib(s[2]), d3 = term_hex_nib(s[3]);
+ if ((d0 | d1 | d2 | d3) < 0)
+ return false;
+ *out = (uint8_t)((((unsigned)d0 << 12) | ((unsigned)d1 << 8) | ((unsigned)d2 << 4) | (unsigned)d3) * 255 / 65535);
+ return true;
+ }
+ if (len == 3) {
+ int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]), d2 = term_hex_nib(s[2]);
+ if ((d0 | d1 | d2) < 0)
+ return false;
+ *out = (uint8_t)((((unsigned)d0 << 8) | ((unsigned)d1 << 4) | (unsigned)d2) * 255 / 4095);
+ return true;
+ }
+ return false;
}
static bool parse_fraction(const char *s, size_t len, uint8_t *out)
@@ -224,6 +247,8 @@ static bool parse_fraction(const char *s, size_t len, uint8_t *out)
static const char *skip_leading_ws(const char *s)
{
+ if (*s != ' ' && *s != '\t')
+ return s;
while (*s == ' ' || *s == '\t')
s++;
return s;
@@ -232,6 +257,8 @@ static const char *skip_leading_ws(const char *s)
static size_t rtrimmed_len(const char *s)
{
size_t n = strlen(s);
+ if (n == 0 || (s[n - 1] != ' ' && s[n - 1] != '\t'))
+ return n;
while (n > 0 && (s[n - 1] == ' ' || s[n - 1] == '\t'))
n--;
return n;
@@ -294,15 +321,19 @@ bool term_color_parse(const char *input, uint32_t *out)
}
if (ci != 3)
return false;
- uint8_t c[3];
- for (int k = 0; k < 3; k++) {
- bool ok = intensity
- ? parse_fraction(channels[k], chlens[k], &c[k])
- : parse_hex_channel(channels[k], chlens[k], &c[k]);
- if (!ok)
+ uint8_t c0, c1, c2;
+ if (intensity) {
+ if (!parse_fraction(channels[0], chlens[0], &c0) ||
+ !parse_fraction(channels[1], chlens[1], &c1) ||
+ !parse_fraction(channels[2], chlens[2], &c2))
+ return false;
+ } else {
+ if (!parse_hex_channel(channels[0], chlens[0], &c0) ||
+ !parse_hex_channel(channels[1], chlens[1], &c1) ||
+ !parse_hex_channel(channels[2], chlens[2], &c2))
return false;
}
- *out = term_rgb(c[0], c[1], c[2]);
+ *out = term_rgb(c0, c1, c2);
return true;
}