#include #include #include #include #include #include "util.h" #include "any_log.h" char *color_to_string(color_t *color) { unsigned int r = color->r * 255, g = color->g * 255, b = color->b * 255, a = color->a * 255; char buffer[32]; int n = snprintf(buffer, 32, "#%02x%02x%02x%02x", r, g, b, a); return strslice(buffer, 0, n); } void color_print(FILE *stream, color_t *color) { unsigned int r = color->r * 255, g = color->g * 255, b = color->b * 255, a = color->a * 255; fprintf(stream, "#%02x%02x%02x%02x", r, g, b, a); } const struct timespec timespec_from_ms(long ms) { struct timespec ts = { .tv_sec = ms / 1000, .tv_nsec = (ms % 1000) * 1000000ul, }; return ts; } const long timespec_to_ms(struct timespec ts) { return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000ul); } struct timespec timespec_diff(struct timespec a, struct timespec b) { bool over = (a.tv_nsec - b.tv_nsec) < 0; struct timespec ts = { .tv_sec = a.tv_sec - b.tv_sec - over, .tv_nsec = a.tv_nsec - b.tv_nsec + over * 1000000000ul, }; return ts; } struct timespec timespec_add(struct timespec a, struct timespec b) { bool over = (a.tv_nsec + b.tv_nsec) > 1000000000ul; struct timespec ts = { .tv_sec = a.tv_sec + b.tv_sec + over, .tv_nsec = a.tv_nsec + b.tv_nsec - over * 1000000000ul, }; return ts; } struct timespec timespec_div(struct timespec ts, int n) { ts.tv_nsec /= n; ts.tv_nsec += ((ts.tv_sec % n) * 1000000000ul) / n; ts.tv_sec /= n; return ts; } bool timespec_greater(struct timespec a, struct timespec b) { return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_nsec > b.tv_nsec); } bool timespec_zero(struct timespec ts) { return ts.tv_sec == 0 && ts.tv_nsec == 0; } void timespec_print(FILE *stream, struct timespec *ts) { fprintf(stream, "%ld.%.9ld", ts->tv_sec, ts->tv_nsec); } bool check_rect(int px, int py, int x, int y, int w, int h) { return px >= x && px <= x + w && py >= y && py <= y + h; } bool check_circle(int px, int py, int x, int y, int r) { int dx = x - px; int dy = y - py; return (dx * dx + dy * dy) <= r * r; } bool check_capsule(int px, int py, int x, int y, int w, int h) { assert(w >= h); int radius = h / 2; // Trivial case if (w == h) return check_circle(px, py, x + radius, y + radius, radius); // General case return check_circle(px, py, x + radius, y + radius, radius) || check_circle(px, py, x + w - radius, y + radius, radius) || check_rect(px, py, x + radius, y, w - 2 * radius, h); } char *strslice(const char *string, size_t start, size_t end) { if (string == NULL) return NULL; char *result = malloc(end - start + 1); memcpy(result, string + start, end - start); result[end - start] = '\0'; return result; } char *strcopy(const char *string) { if (string == NULL) return NULL; return strslice(string, 0, strlen(string)); } bool strfind(const char *string, const char *cases[]) { for (int i = 0; cases[i] != NULL; i++) { if (strstr(string, cases[i]) != NULL) return true; } return false; } size_t strprefix(const char *string, const char *prefix) { size_t i = 0; for ( ; prefix[i] != '\0'; i++) { if (string[i] != prefix[i]) return 0; } return i; } void strfree(char **list) { if (list == NULL) return; for (char **head = list; *head != NULL; head++) free(*head); free(list); } bool iszero(const void *ptr, size_t size) { for (size_t i = 0; i < size; i++) { if (((const char *)ptr)[i] != 0) return false; } return true; } int snprintf_units(char *buffer, size_t max, uint64_t bytes, unit_t unit) { int base = unit & UNIT_SI ? 1000 : 1024; double value = bytes; const char *label = ""; switch (unit & ~UNIT_SI) { case UNIT_B: break; case UNIT_TB: value /= base; // fallthrough case UNIT_GB: value /= base; // fallthrough case UNIT_MB: value /= base; // fallthrough case UNIT_KB: value /= base; break; default: { int i = -1; do { value /= base; i++; } while (round(value * 10) / 10 >= base && i < 4); const char *units[2][5] = { { " B", " kB", " MB", " GB", " TB" }, { " B", " KiB", " MiB", " GiB", " TiB" }, }; label = units[!(unit & UNIT_SI)][i]; break; } } int prec = 1; if (floor(value) >= 100.0) { value = ceil(value); prec = 0; } int ret = snprintf(buffer, max, "%.*lf%s", prec, value, label); assert(ret > 0); return ret; }