status

statusbar program for dwm
git clone anongit@rnpnr.xyz:status.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 097fda3f32942da2f4bbf8495c9dbb6c152fef58
Parent: 7bced14670d73a48fc528ab2cafd8a6ddf0e0b94
Author: Randy Palamar
Date:   Tue, 24 Dec 2024 12:11:22 -0700

delete pscanf function

scanf in general is an awful function and reading strings with it
is completely inexcusable. This removes more pointless c-runtime
code.

Diffstat:
Mblocks/linux/backlight.c | 8+++-----
Mblocks/linux/battery_info.c | 22++++++++++++----------
Mstatus.c | 56++++++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 57 insertions(+), 29 deletions(-)

diff --git a/blocks/linux/backlight.c b/blocks/linux/backlight.c @@ -7,10 +7,7 @@ static BLOCK_UPDATE_FN(backlight_update) return 0; struct linux_backlight_data *lbd = b->user_data; - i64 current; - if (pscanf(lbd->brightness_path, "%ld", &current) != 1) - current = 0; - + i64 current = read_i64(lbd->brightness_path); f32 percent = 100 * current / (f32)lbd->max_brightness + 0.5; i64 len = snprintf(buffer, sizeof(buffer), "%d%%", (i32)percent); buffer[len] = 0; @@ -30,7 +27,8 @@ static BLOCK_INIT_FN(backlight_init) stream_push_s8(&path, *(s8 *)b->arg); size sidx = path.write_index; stream_push_s8(&path, s8("/max_brightness")); - if (pscanf(stream_ensure_c_str(&path), "%ld", &lbd->max_brightness) != 1) + lbd->max_brightness = read_i64(stream_ensure_c_str(&path)); + if (!lbd->max_brightness) die("backlight_init: failed to read max brightness\n"); path.write_index = sidx; diff --git a/blocks/linux/battery_info.c b/blocks/linux/battery_info.c @@ -19,7 +19,6 @@ static BLOCK_UPDATE_FN(battery_info_update) char *pre = ba->pre ? ba->pre : ""; char *suf = ba->suf ? ba->suf : ""; - char state[12]; i32 h, m; i64 power_now, energy_now; @@ -28,24 +27,26 @@ static BLOCK_UPDATE_FN(battery_info_update) size sidx = lbd->path_base.write_index; stream_push_s8(&lbd->path_base, s8("/energy_now")); - if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &energy_now) != 1) - energy_now = 0; + energy_now = read_i64(stream_ensure_c_str(&lbd->path_base)); lbd->path_base.write_index = sidx; f32 percent = (100 * energy_now / (f64)lbd->energy_full) + 0.5; b32 warn = percent < ba->thres; + char state_buffer[16] = {0}; stream_push_s8(&lbd->path_base, s8("/status")); - if (pscanf(stream_ensure_c_str(&lbd->path_base), "%12s", &state) != 1) - snprintf(state, sizeof(state), "Unknown"); + s8 state = s8_trim_space(read_s8(stream_ensure_c_str(&lbd->path_base), + (s8){.len = sizeof(state_buffer), + .data = (u8 *)state_buffer})); + if (state.len <= 0) state = s8("Unknown"); lbd->path_base.write_index = sidx; /* NOTE(rnp): proper devices use negative power to indicate discharging but that * is not always the case. The status string can mostly be trusted */ - if (!strcmp(state, "Discharging")) { + if (s8_equal(state, s8("Discharging"))) { stream_push_s8(&lbd->path_base, s8("/power_now")); - if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &power_now) != 1) - power_now = 1; + power_now = read_i64(stream_ensure_c_str(&lbd->path_base)); + if (!power_now) power_now = 1; lbd->path_base.write_index = sidx; timeleft = energy_now / (f64)ABS(power_now); @@ -57,7 +58,7 @@ static BLOCK_UPDATE_FN(battery_info_update) buffer[len] = 0; } else { i64 len = snprintf(buffer, sizeof(buffer), "%s%d%% (%s)%s", warn? pre : "", - (i32)percent, state, warn? suf : ""); + (i32)percent, (char *)state.data, warn? suf : ""); buffer[len] = 0; } b->len = snprintf(b->data, sizeof(b->data), b->fmt, buffer); @@ -89,7 +90,8 @@ static BLOCK_INIT_FN(battery_info_init) stream_push_s8(&lbd->path_base, ba->bat); size sidx = lbd->path_base.write_index; stream_push_s8(&lbd->path_base, s8("/energy_full")); - if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &lbd->energy_full) != 1) + lbd->energy_full = read_i64(stream_ensure_c_str(&lbd->path_base)); + if (!lbd->energy_full) die("battery_info_init: failed to read battery capacity\n"); lbd->path_base.write_index = sidx; diff --git a/status.c b/status.c @@ -12,9 +12,12 @@ #include <X11/Xlib.h> #define ABS(a) ((a) < 0 ? -(a) : (a)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) #define BLOCKLEN 128 +#define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\t') + #define TICK_RATE_SECONDS 1 #define TICK_RATE_NANOSECONDS 0 @@ -101,6 +104,8 @@ static FileWatch file_watches; static i32 dflag; +i64 strtol(const char *, char **, i32); + static void die(const char *errstr, ...) { @@ -131,22 +136,26 @@ timer_update(f32 *timer, f32 interval, f32 dt) return result; } -static int -pscanf(const char *path, const char *fmt, ...) +static s8 +read_s8(char *path, s8 buffer) { - FILE *fp; - va_list ap; - int ret; - - if (!(fp = fopen(path, "r"))) - return -1; - - va_start(ap, fmt); - ret = vfscanf(fp, fmt, ap); - va_end(ap); - fclose(fp); + i32 fd = open(path, O_RDONLY); + buffer.len = read(fd, buffer.data, buffer.len); + close(fd); + return buffer; +} - return (ret == EOF) ? -1 : ret; +static i64 +read_i64(char *path) +{ + i64 result = 0; + char buffer[64]; + s8 str = read_s8(path, (s8){.len = sizeof(buffer), .data = (u8 *)buffer}); + if (str.len > 0) { + buffer[MIN(str.len, sizeof(buffer) - 1)] = 0; + result = strtol(buffer, 0, 10); + } + return result; } static void * @@ -174,6 +183,25 @@ alloc_(Arena *a, size len, size align, size count) return mem_clear(p, 0, count * len); } +static b32 +s8_equal(s8 a, s8 b) +{ + b32 result = a.len == b.len; + if (result) { + for (size i = 0; i < a.len; i++) + result &= a.data[i] == b.data[i]; + } + return result; +} + +static s8 +s8_trim_space(s8 a) +{ + while (a.len > 0 && ISSPACE(a.data[0])) { a.len--; a.data++; } + while (a.len > 0 && ISSPACE(a.data[a.len - 1])) { a.len--; } + return a; +} + static Stream stream_alloc(Arena *a, size capacity) {