Alien-libhisto

 view release on metacpan or  search on metacpan

bundled/CMakeLists.txt  view on Meta::CPAN

else()
    target_compile_options(histo_compiler_flags INTERFACE -Wall -Wextra -Wpedantic)
    if(LIBHISTO_WARNINGS_AS_ERRORS)
        target_compile_options(histo_compiler_flags INTERFACE -Werror)
    endif()
endif()

# Sanitizers configuration
if(NOT MSVC)
    if(LIBHISTO_ENABLE_ASAN)
        target_compile_options(histo_compiler_flags INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer)
        target_link_options(histo_compiler_flags INTERFACE -fsanitize=address,undefined)
    elseif(LIBHISTO_ENABLE_TSAN)
        target_compile_options(histo_compiler_flags INTERFACE -fsanitize=thread -fno-omit-frame-pointer)
        target_link_options(histo_compiler_flags INTERFACE -fsanitize=thread)
    elseif(LIBHISTO_ENABLE_MSAN)
        target_compile_options(histo_compiler_flags INTERFACE -fsanitize=memory -fno-omit-frame-pointer)
        target_link_options(histo_compiler_flags INTERFACE -fsanitize=memory)
    endif()
endif()

# Valgrind integration
find_program(VALGRIND_EXECUTABLE valgrind)
if(VALGRIND_EXECUTABLE)
    set(MEMORYCHECK_COMMAND ${VALGRIND_EXECUTABLE})
    set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1")
    set(CTEST_MEMORYCHECK_COMMAND ${VALGRIND_EXECUTABLE})

bundled/tools/include/tui_term.h  view on Meta::CPAN

} tui_key_type_t;

typedef struct {
    tui_key_type_t type;
    int ch;
    int mouse_x;
    int mouse_y;
    int mouse_btn;
} tui_key_event_t;

/* Double-buffered frame buffer */
typedef struct {
    char *buf;
    size_t len;
    size_t cap;
} tui_frame_t;

/* Terminal state lifecycle */
bool tui_term_init(void);
void tui_term_restore(void);
bool tui_term_raw_enter(void);
void tui_term_raw_leave(void);
void tui_term_get_size(int *out_cols, int *out_rows);
int  tui_term_get_tty_fd(void);

/* Non-blocking key event reader from tty */
tui_key_event_t tui_term_read_key(int tty_fd, int timeout_ms);

/* Frame buffer methods */
void tui_frame_init(tui_frame_t *f, size_t initial_cap);
void tui_frame_clear(tui_frame_t *f);
void tui_frame_append(tui_frame_t *f, const char *str, size_t len);
void tui_frame_puts(tui_frame_t *f, const char *str);
void tui_frame_printf(tui_frame_t *f, const char *fmt, ...);
void tui_frame_flush(tui_frame_t *f, FILE *out_fp);
void tui_frame_free(tui_frame_t *f);

/* Color & style helpers */
void tui_term_get_color(double fraction, bool monochrome, char *out_ansi, size_t max_len);
int  tui_visual_width(const char *str);
void tui_render_row(tui_frame_t *f, const char *content, int width, bool newline);

#ifdef __cplusplus
}
#endif

#endif /* HISTO_TUI_TERM_H */

bundled/tools/src/cmd_top.c  view on Meta::CPAN


    char status_msg[128];
    double status_msg_time;

    histo_t *frozen_snapshot;
    histo2d_t *frozen_snapshot_2d;
} tui_state_t;

static const char *const BLOCKS_UTF8[9] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };

static void render_top_border(tui_frame_t *f, const char *title, const char *badge, int width) {
    tui_frame_printf(f, "\033[1m┌─ %s ", title);
    int title_cols = 3 + (int)strlen(title) + 1; // "┌─ " (3) + title + " " (1)
    int badge_cols = (badge && badge[0]) ? (tui_visual_width(badge) + 4) : 2; // " " + badge + " ─┐"
    int dashes = width - title_cols - badge_cols;
    if (dashes < 0) dashes = 0;
    for (int i = 0; i < dashes; ++i) tui_frame_puts(f, "─");
    if (badge && badge[0]) {
        tui_frame_printf(f, " %s ─┐\033[0m\r\n", badge);
    } else {
        tui_frame_puts(f, "─┐\033[0m\r\n");
    }
}

static void render_divider(tui_frame_t *f, int width) {
    tui_frame_puts(f, "├");
    for (int i = 0; i < width - 2; ++i) tui_frame_puts(f, "─");
    tui_frame_puts(f, "┤\r\n");
}

static void render_bottom_border(tui_frame_t *f, int width, bool newline) {
    tui_frame_puts(f, "â””");
    for (int i = 0; i < width - 2; ++i) tui_frame_puts(f, "─");
    tui_frame_puts(f, "┘");
    if (newline) tui_frame_puts(f, "\r\n");
}

static void render_2d_heatmap_viewport(tui_frame_t *f, const tui_state_t *st, const histo2d_t *h, int width, int max_rows) {
    if (!h || max_rows <= 0) {
        for (int r = 0; r < max_rows; ++r) tui_render_row(f, "", width, true);
        return;
    }

    uint32_t nx = histo2d_nbins_x(h);
    uint32_t ny = histo2d_nbins_y(h);
    if (nx == 0 || ny == 0) {
        for (int r = 0; r < max_rows; ++r) tui_render_row(f, "", width, true);
        return;

bundled/tools/src/cmd_top.c  view on Meta::CPAN

        snprintf(buf, sz, "%8.2e", val);
    } else if (fabs(val) >= 10000.0) {
        snprintf(buf, sz, "%8.1f", val);
    } else if (fabs(val) >= 100.0) {
        snprintf(buf, sz, "%7.2f", val);
    } else {
        snprintf(buf, sz, "%6.2f", val);
    }
}

static void render_1d_bars_viewport(tui_frame_t *f, const tui_state_t *st, const histo_t *h, int width, int max_rows) {
    if (!h || max_rows <= 0) {
        for (int r = 0; r < max_rows; ++r) tui_render_row(f, "", width, true);
        return;
    }

    uint32_t nbins = histo_nbins(h);
    if (nbins == 0) {
        for (int r = 0; r < max_rows; ++r) tui_render_row(f, "", width, true);
        return;
    }

bundled/tools/src/cmd_top.c  view on Meta::CPAN


    if (kde) histo_kde_destroy(kde);
    if (fit_res) histo_fit_result_destroy(fit_res);

    while (rows_drawn < max_rows) {
        tui_render_row(f, "", width, true);
        rows_drawn++;
    }
}

static void render_help_viewport(tui_frame_t *f, const tui_state_t *st, int width, int max_rows) {
    if (st && st->view_mode == VIEW_2D_HEATMAP) {
        const char *help_lines_2d[] = {
            "── Interactive Help Cheatsheet (2D Heatmap Mode) ───────────────────────────",
            "",
            "DISPLAY & INTENSITY SCALING",
            "  l           Toggle Log-Z intensity color scale (LIN <-> LOG-Z)",
            "  p / P       Cycle color palettes (viridis, plasma, inferno, magma, turbo, cividis, gray, rainbow)",
            "  C           Toggle TrueColor / Monochrome ASCII density",
            "  g           Toggle Color Range Legend reference bar",
            "  [Space]     Freeze / Unfreeze live streaming display",

bundled/tools/src/cmd_top.c  view on Meta::CPAN

    tui_state_t st;
    memset(&st, 0, sizeof(st));
    st.monochrome = monochrome;
    st.palette = palette;
    st.view_mode = is_2d ? VIEW_2D_HEATMAP : VIEW_1D_BARS;

    tui_engine_start(&eng);

    int tty_fd = tui_term_get_tty_fd();

    tui_frame_t frame;
    tui_frame_init(&frame, 65536);

    while (eng.running) {
        tui_key_event_t ev = tui_term_read_key(tty_fd, 33);
        if (ev.type != TUI_KEY_NONE) {
            if (ev.type == TUI_KEY_CTRL_C || (ev.type == TUI_KEY_CHAR && ev.ch == 3)) {
                eng.running = false;
                break;
            }
            if (st.cmd_active) {
                if (ev.type == TUI_KEY_ESC) {

bundled/tools/src/cmd_top.c  view on Meta::CPAN

        if (eng.is_2d) {
            snap_2d = tui_engine_get_snapshot_2d(&eng);
            n_entries = snap_2d ? histo2d_num_entries(snap_2d) : 0;
            tot_w = snap_2d ? histo2d_total_weight(snap_2d) : 0.0;
        } else {
            snap = st.paused ? st.frozen_snapshot : tui_engine_get_snapshot_1d(&eng);
            n_entries = snap ? histo_num_entries(snap) : 0;
            tot_w = snap ? histo_total_weight(snap) : 0.0;
        }

        tui_frame_clear(&frame);
        tui_frame_puts(&frame, "\033[H"); // Cursor home

        // Row 1: Top border with badge
        char badge[96] = "";
        if (st.paused) {
            if (eng.has_weights) {
                snprintf(badge, sizeof(badge), "[PAUSED | N=%lu | W=%.2f]", (unsigned long)n_entries, tot_w);
            } else {
                snprintf(badge, sizeof(badge), "[PAUSED | N=%lu]", (unsigned long)n_entries);
            }
        } else if (tui_engine_is_finished(&eng)) {

bundled/tools/src/cmd_top.c  view on Meta::CPAN

            if (rate >= 1e6) snprintf(rate_str, sizeof(rate_str), "%.1fM/s", rate / 1e6);
            else if (rate >= 1e3) snprintf(rate_str, sizeof(rate_str), "%.1fk/s", rate / 1e3);
            else snprintf(rate_str, sizeof(rate_str), "%.0f/s", rate);

            if (eng.has_weights) {
                snprintf(badge, sizeof(badge), "[LIVE: %s | N=%lu | W=%.2f]", rate_str, (unsigned long)n_entries, tot_w);
            } else {
                snprintf(badge, sizeof(badge), "[LIVE: %s | N=%lu]", rate_str, (unsigned long)n_entries);
            }
        }
        render_top_border(&frame, eng.is_2d ? "libhisto top (2D)" : "libhisto top", badge, cols);

        if (st.compact_header) {
            char stats_buf[256];
            if (eng.is_2d) {
                if (snap_2d && n_entries > 0) {
                    histo2d_axis_t ax, ay;
                    histo2d_axis_x(snap_2d, &ax);
                    histo2d_axis_y(snap_2d, &ay);
                    snprintf(stats_buf, sizeof(stats_buf), "[2D] X:[%.1f,%.1f] Y:[%.1f,%.1f] │ N=%lu │ %s │ Pal:%s",
                             ax.min, ax.max, ay.min, ay.max, (unsigned long)n_entries,

bundled/tools/src/cmd_top.c  view on Meta::CPAN

                    histo_mean(snap, &mean);
                    histo_std_dev(snap, &sdev);
                    histo_median(snap, &med);
                    histo_quantile(snap, 0.95, &p95);
                    snprintf(stats_buf, sizeof(stats_buf), "[Col %d] Mean: %.2f ± %.2f │ Med: %.2f │ P95: %.2f │ N=%lu │ Pal:%s",
                             eng.val_col, mean, sdev, med, p95, (unsigned long)n_entries, histo_palette_name(st.palette));
                } else {
                    snprintf(stats_buf, sizeof(stats_buf), "Waiting for stream...");
                }
            }
            tui_render_row(&frame, stats_buf, cols, true);
            render_divider(&frame, cols);
        } else {
            // Row 2: Stats summary
            char stats_buf[256];
            if (eng.is_2d) {
                if (snap_2d && n_entries > 0) {
                    histo2d_axis_t ax, ay;
                    histo2d_axis_x(snap_2d, &ax);
                    histo2d_axis_y(snap_2d, &ay);
                    snprintf(stats_buf, sizeof(stats_buf),
                             "X: [%.2f, %.2f] %ux │ Y: [%.2f, %.2f] %uy │ Entries: %lu │ Weight: %.2f",

bundled/tools/src/cmd_top.c  view on Meta::CPAN

                    histo_median(snap, &med);
                    histo_iqr(snap, &iqr);
                    histo_quantile(snap, 0.95, &p95);
                    histo_quantile(snap, 0.99, &p99);
                    snprintf(stats_buf, sizeof(stats_buf), "Mean: %.2f ± %.2f │ Med: %.2f │ IQR: %.2f │ P95: %.2f │ P99: %.2f",
                             mean, sdev, med, iqr, p95, p99);
                } else {
                    snprintf(stats_buf, sizeof(stats_buf), "Waiting for streaming samples...");
                }
            }
            tui_render_row(&frame, stats_buf, cols, true);

            // Row 3: Divider
            render_divider(&frame, cols);

            // Row 4: Subheader
            char subhdr[384];
            if (eng.is_2d) {
                if (snap_2d) {
                    histo2d_axis_t ax, ay;
                    histo2d_axis_x(snap_2d, &ax);
                    histo2d_axis_y(snap_2d, &ay);
                    snprintf(subhdr, sizeof(subhdr), "2D Heatmap │ X: %u bins [%.1f, %.1f] │ Y: %u bins [%.1f, %.1f] │ Pal: %s │ %s %s",
                             histo2d_nbins_x(snap_2d), ax.min, ax.max,

bundled/tools/src/cmd_top.c  view on Meta::CPAN

                if (eng.window_size > 0) snprintf(win_tag, sizeof(win_tag), "Win:%zu │ ", eng.window_size);

                snprintf(subhdr, sizeof(subhdr), "%s%sRange: [%.2f, %.2f] │ Bins: %u │ Scale: %s │ Pal: %s │ Auto: %s %s%s%s%s",
                         col_tag, win_tag, r_min, r_max, nb, sc,
                         histo_palette_name(st.palette),
                         eng.auto_range ? "ON" : "OFF",
                         kde_tag, fit_tag, err_tag, yaxis_tag);
            } else {
                snprintf(subhdr, sizeof(subhdr), "Initializing...");
            }
            tui_render_row(&frame, subhdr, cols, true);
        }

        if (st.modal == MODAL_HELP) {
            render_help_viewport(&frame, &st, cols, viewport_rows);
        } else if (eng.is_2d) {
            render_2d_heatmap_viewport(&frame, &st, snap_2d, cols, viewport_rows);
        } else {
            render_1d_bars_viewport(&frame, &st, snap, cols, viewport_rows);
        }

        // Row rows - 2: Divider
        render_divider(&frame, cols);

        // Row rows - 1: Footer / Command
        if (st.cmd_active) {
            char cmd_line[300];
            snprintf(cmd_line, sizeof(cmd_line), ":%s\033[7m \033[0m", st.cmd_buf);
            tui_render_row(&frame, cmd_line, cols, true);
        } else if (st.status_msg[0] != '\0' && (cli_get_time_sec() - st.status_msg_time < 3.0)) {
            char status_row[256];
            snprintf(status_row, sizeof(status_row), ">> %s", st.status_msg);
            tui_render_row(&frame, status_row, cols, true);
        } else {
            const char *hints = eng.is_2d ?
                "[Space] Freeze  [+/-] Zoom  [←↑→↓] Pan  [l] Log-Z  [p] Pal  [g] Legend  [:] Cmd  [?] Help  [q] Quit" :
                "[Space] Freeze  [+/-] Zoom  [Tab] Col  [w] Win  [s] Save  [H] Compact  [B] Auto-Bins  [:] Cmd  [?] Help";
            tui_render_row(&frame, hints, cols, true);
        }

        // Row rows: Bottom border (no trailing newline to avoid scrolling on final cell)
        render_bottom_border(&frame, cols, false);
        tui_frame_puts(&frame, "\033[J"); // Erase below in case window grew or shrank

        tui_frame_flush(&frame, stdout);

        if (!st.paused && snap) {
            histo_destroy(snap);
        }
        if (!st.paused && snap_2d) {
            histo2d_destroy(snap_2d);
        }
    }

    if (st.frozen_snapshot) {
        histo_destroy(st.frozen_snapshot);
    }
    if (st.frozen_snapshot_2d) {
        histo2d_destroy(st.frozen_snapshot_2d);
    }

    tui_frame_free(&frame);
    tui_term_restore();
    tui_engine_free(&eng);
    if (in_fp != stdin) fclose(in_fp);
    return 0;
}

bundled/tools/src/tui_term.c  view on Meta::CPAN

        return ev;
    }

    ev.type = TUI_KEY_CHAR;
    ev.ch = (unsigned char)c;
#endif
    return ev;
}

/* Frame buffer methods */
void tui_frame_init(tui_frame_t *f, size_t initial_cap) {
    if (!f) return;
    if (initial_cap < 4096) initial_cap = 65536;
    f->buf = (char *)malloc(initial_cap);
    f->len = 0;
    f->cap = initial_cap;
    if (f->buf) f->buf[0] = '\0';
}

void tui_frame_clear(tui_frame_t *f) {
    if (!f) return;
    f->len = 0;
    if (f->buf) f->buf[0] = '\0';
}

void tui_frame_append(tui_frame_t *f, const char *str, size_t len) {
    if (!f || !str || len == 0) return;
    if (f->len + len + 1 > f->cap) {
        size_t new_cap = (f->cap * 2 > f->len + len + 1) ? f->cap * 2 : f->len + len + 4096;
        char *new_buf = (char *)realloc(f->buf, new_cap);
        if (!new_buf) return;
        f->buf = new_buf;
        f->cap = new_cap;
    }
    memcpy(f->buf + f->len, str, len);
    f->len += len;
    f->buf[f->len] = '\0';
}

void tui_frame_puts(tui_frame_t *f, const char *str) {
    if (!f || !str) return;
    tui_frame_append(f, str, strlen(str));
}

void tui_frame_printf(tui_frame_t *f, const char *fmt, ...) {
    if (!f || !fmt) return;
    char stack_buf[1024];
    va_list args;
    va_start(args, fmt);
    int written = vsnprintf(stack_buf, sizeof(stack_buf), fmt, args);
    va_end(args);

    if (written < 0) return;
    if ((size_t)written < sizeof(stack_buf)) {
        tui_frame_append(f, stack_buf, (size_t)written);
    } else {
        char *heap_buf = (char *)malloc((size_t)written + 1);
        if (heap_buf) {
            va_start(args, fmt);
            vsnprintf(heap_buf, (size_t)written + 1, fmt, args);
            va_end(args);
            tui_frame_append(f, heap_buf, (size_t)written);
            free(heap_buf);
        }
    }
}

void tui_frame_flush(tui_frame_t *f, FILE *out_fp) {
    if (!f || !f->buf || f->len == 0) return;
    if (!out_fp) out_fp = stdout;
    fwrite(f->buf, 1, f->len, out_fp);
    fflush(out_fp);
    tui_frame_clear(f);
}

void tui_frame_free(tui_frame_t *f) {
    if (!f) return;
    if (f->buf) {
        free(f->buf);
        f->buf = NULL;
    }
    f->len = 0;
    f->cap = 0;
}

void tui_term_get_color(double fraction, bool monochrome, char *out_ansi, size_t max_len) {

bundled/tools/src/tui_term.c  view on Meta::CPAN

        } else if ((*p & 0xF8) == 0xF0) {
            cols += 2;
            p += (*(p + 1) && *(p + 2) && *(p + 3)) ? 4 : 1;
        } else {
            p++;
        }
    }
    return cols;
}

void tui_render_row(tui_frame_t *f, const char *content, int width, bool newline) {
    if (!f) return;
    tui_frame_puts(f, "│ ");
    int vis = tui_visual_width(content);
    int inner_width = width - 4;
    if (inner_width < 1) inner_width = 1;

    if (vis <= inner_width) {
        tui_frame_puts(f, content ? content : "");
        int pad = inner_width - vis;
        for (int i = 0; i < pad; ++i) tui_frame_puts(f, " ");
    } else {
        const unsigned char *p = (const unsigned char *)(content ? content : "");
        int cur_cols = 0;
        while (*p && cur_cols < inner_width) {
            if (*p == '\033') {
                const unsigned char *start = p++;
                if (*p == '[') {
                    p++;
                    while (*p && (*p < 0x40 || *p > 0x7E)) p++;
                    if (*p) p++;
                }
                tui_frame_append(f, (const char *)start, (size_t)(p - start));
            } else if (*p < 0x80) {
                if (*p >= 32 && *p <= 126) cur_cols++;
                tui_frame_append(f, (const char *)p, 1);
                p++;
            } else if ((*p & 0xE0) == 0xC0) {
                cur_cols++;
                size_t len = (*(p + 1)) ? 2 : 1;
                tui_frame_append(f, (const char *)p, len);
                p += len;
            } else if ((*p & 0xF0) == 0xE0) {
                cur_cols++;
                size_t len = (*(p + 1) && *(p + 2)) ? 3 : 1;
                tui_frame_append(f, (const char *)p, len);
                p += len;
            } else if ((*p & 0xF8) == 0xF0) {
                if (cur_cols + 2 <= inner_width) {
                    cur_cols += 2;
                    size_t len = (*(p + 1) && *(p + 2) && *(p + 3)) ? 4 : 1;
                    tui_frame_append(f, (const char *)p, len);
                    p += len;
                } else break;
            } else {
                p++;
            }
        }
        int pad = inner_width - cur_cols;
        for (int i = 0; i < pad; ++i) tui_frame_puts(f, " ");
    }

    tui_frame_puts(f, "\033[0m │");
    if (newline) tui_frame_puts(f, "\r\n");
}



( run in 0.622 second using v1.01-cache-2.11-cpan-2e0ccfb7a10 )