diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 10:58:21 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 10:58:21 -0400 |
| commit | 002e3d7d13c414ea874abbee8d82803dd3a72fe5 (patch) | |
| tree | 6627c12fa07f6a1cf73e5aaeb7390e698dd3a896 /tools/rmtool/src/output.c | |
| parent | 2f249817df327f5dcccf0464ad517fa60d6071d3 (diff) | |
| download | open-iov-002e3d7d13c414ea874abbee8d82803dd3a72fe5.tar.gz open-iov-002e3d7d13c414ea874abbee8d82803dd3a72fe5.zip | |
debug: green-eye wave 3 - RM harness, local simulator, device map, MCP plugin, value-validation demos, CI pipeline, toolchain docs; add host RM tools rmtool/rmtop
Diffstat (limited to 'tools/rmtool/src/output.c')
| -rw-r--r-- | tools/rmtool/src/output.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/tools/rmtool/src/output.c b/tools/rmtool/src/output.c new file mode 100644 index 0000000..6de5d02 --- /dev/null +++ b/tools/rmtool/src/output.c @@ -0,0 +1,251 @@ +/* output.c - table/JSON/CSV formatting helpers shared by rmtool commands. */ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "rmtool.h" + +enum rm_format rm_format_parse(const char *name) +{ + if (name == NULL || strcmp(name, "table") == 0) + return RM_FMT_TABLE; + if (strcmp(name, "json") == 0) + return RM_FMT_JSON; + if (strcmp(name, "csv") == 0) + return RM_FMT_CSV; + return (enum rm_format)-1; +} + +const char *rm_human_kib(NvU64 kib, char *buf, size_t len) +{ + if (kib >= 1024ULL * 1024ULL) + snprintf(buf, len, "%.2f GiB", (double)kib / (1024.0 * 1024.0)); + else if (kib >= 1024ULL) + snprintf(buf, len, "%.1f MiB", (double)kib / 1024.0); + else + snprintf(buf, len, "%llu KiB", (unsigned long long)kib); + return buf; +} + +static int json_plain_number(const char *value) +{ + char *end; + double d; + + if (value == NULL || *value == '\0') + return 0; + d = strtod(value, &end); + if (end == value || *end != '\0') + return 0; + (void)d; + return 1; +} + +static void json_string(FILE *out, const char *value) +{ + const unsigned char *p = (const unsigned char *)value; + + fputc('"', out); + for (; p != NULL && *p != '\0'; p++) { + switch (*p) { + case '"': + fputs("\\\"", out); + break; + case '\\': + fputs("\\\\", out); + break; + case '\n': + fputs("\\n", out); + break; + case '\r': + fputs("\\r", out); + break; + case '\t': + fputs("\\t", out); + break; + default: + if (*p < 0x20) + fprintf(out, "\\u%04x", *p); + else + fputc(*p, out); + break; + } + } + fputc('"', out); +} + +static void json_value(FILE *out, const char *value) +{ + if (value == NULL) { + fputs("null", out); + } else if (json_plain_number(value)) { + fputs(value, out); + } else { + json_string(out, value); + } +} + +static void csv_value(FILE *out, const char *value) +{ + const char *p; + int needs_quote = 0; + + if (value == NULL) + value = ""; + for (p = value; *p != '\0'; p++) { + if (*p == ',' || *p == '"' || *p == '\n' || *p == '\r') { + needs_quote = 1; + break; + } + } + if (!needs_quote) { + fputs(value, out); + return; + } + fputc('"', out); + for (p = value; *p != '\0'; p++) { + if (*p == '"') + fputc('"', out); + fputc(*p, out); + } + fputc('"', out); +} + +void rm_print_kv(const char *title, const struct rm_kv *kv, int n, + enum rm_format format) +{ + int i; + + if (format == RM_FMT_JSON) { + printf("{\"title\": "); + json_string(stdout, title); + printf(", \"values\": {"); + for (i = 0; i < n; i++) { + if (i) + fputs(", ", stdout); + json_string(stdout, kv[i].key); + fputs(": ", stdout); + json_value(stdout, kv[i].value); + } + printf("}}\n"); + return; + } + if (format == RM_FMT_CSV) { + for (i = 0; i < n; i++) { + csv_value(stdout, kv[i].key); + fputc(',', stdout); + csv_value(stdout, kv[i].value); + fputc('\n', stdout); + } + return; + } + printf("%s\n", title); + for (i = 0; i < n; i++) + printf(" %-28s %s\n", kv[i].key, + kv[i].value ? kv[i].value : "-"); +} + +static const char *cell_at(const char *cells, size_t stride, int row, + int col, int cols) +{ + return cells + (size_t)(row * cols + col) * stride; +} + +void rm_print_table(const char *title, const char *const *headers, + const char *cells, size_t stride, int rows, int cols, + enum rm_format format) +{ + int *width; + int r, c; + + if (format == RM_FMT_JSON) { + printf("["); + for (r = 0; r < rows; r++) { + if (r) + fputs(", ", stdout); + fputc('{', stdout); + for (c = 0; c < cols; c++) { + if (c) + fputs(", ", stdout); + json_string(stdout, headers[c]); + fputs(": ", stdout); + json_value(stdout, cell_at(cells, stride, r, + c, cols)); + } + fputc('}', stdout); + } + printf("]\n"); + return; + } + if (format == RM_FMT_CSV) { + for (c = 0; c < cols; c++) { + if (c) + fputc(',', stdout); + csv_value(stdout, headers[c]); + } + fputc('\n', stdout); + for (r = 0; r < rows; r++) { + for (c = 0; c < cols; c++) { + if (c) + fputc(',', stdout); + csv_value(stdout, cell_at(cells, stride, r, + c, cols)); + } + fputc('\n', stdout); + } + return; + } + width = calloc((size_t)cols, sizeof(*width)); + if (width == NULL) + return; + for (c = 0; c < cols; c++) + width[c] = (int)strlen(headers[c]); + for (r = 0; r < rows; r++) { + for (c = 0; c < cols; c++) { + const char *v = cell_at(cells, stride, r, c, cols); + int len = v ? (int)strlen(v) : 0; + + if (len > width[c]) + width[c] = len; + } + } + printf("%s\n", title); + for (c = 0; c < cols; c++) + printf("%-*s%s", width[c], headers[c], + c + 1 < cols ? " " : "\n"); + for (r = 0; r < rows; r++) { + for (c = 0; c < cols; c++) + printf("%-*s%s", width[c], + cell_at(cells, stride, r, c, cols), + c + 1 < cols ? " " : "\n"); + } + free(width); +} + +void rm_hexdump(const void *data, size_t len) +{ + const unsigned char *p = data; + size_t off; + + for (off = 0; off < len; off += 16) { + size_t i; + + printf(" %04zx ", off); + for (i = 0; i < 16; i++) { + if (off + i < len) + printf("%02x ", p[off + i]); + else + fputs(" ", stdout); + if (i == 7) + fputc(' ', stdout); + } + fputs(" |", stdout); + for (i = 0; i < 16 && off + i < len; i++) { + unsigned char ch = p[off + i]; + + fputc(isprint(ch) ? ch : '.', stdout); + } + puts("|"); + } +} |
