diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-13 08:37:01 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-13 08:37:01 +0300 |
| commit | eec660b7419aed7254aecf7318cd9b45b9a64853 (patch) | |
| tree | 5e9c1fb4e14b446729e4c3a20ecc665c6d2e80e1 /src | |
| parent | b46f12e185554e0ff63bf54d9491646be089a3ee (diff) | |
refactor(o2): extract history csv helpers into fastforge_csv
Diffstat (limited to 'src')
| -rw-r--r-- | src/c/fastforge_csv.c | 102 | ||||
| -rw-r--r-- | src/c/fastforge_csv.h | 15 | ||||
| -rw-r--r-- | src/c/fastforge_history.c | 97 |
3 files changed, 118 insertions, 96 deletions
diff --git a/src/c/fastforge_csv.c b/src/c/fastforge_csv.c new file mode 100644 index 0000000..7da9bd7 --- /dev/null +++ b/src/c/fastforge_csv.c @@ -0,0 +1,102 @@ +#include "fastforge_csv.h" + +#include <stdbool.h> +#include <stdio.h> + +size_t csv_append_text(char *buffer, size_t size, size_t offset, + const char *value) { + if (!buffer || size == 0 || offset >= size) { + return offset; + } + + bool needs_quotes = false; + if (value) { + for (const char *cursor = value; *cursor; cursor++) { + if (*cursor == ',' || *cursor == '"' || *cursor == '\n' || + *cursor == '\r') { + needs_quotes = true; + break; + } + } + } + + if (needs_quotes) { + if (offset + 1 < size) { + buffer[offset++] = '"'; + } + if (value) { + for (const char *cursor = value; *cursor && offset + 1 < size; cursor++) { + if (*cursor == '"') { + if (offset + 2 >= size) { + break; + } + buffer[offset++] = '"'; + buffer[offset++] = '"'; + } else { + buffer[offset++] = *cursor; + } + } + } + if (offset + 1 < size) { + buffer[offset++] = '"'; + } + } else if (value) { + for (const char *cursor = value; *cursor && offset + 1 < size; cursor++) { + buffer[offset++] = *cursor; + } + } + + if (offset < size) { + buffer[offset] = '\0'; + } + return offset; +} + +size_t csv_append_int(char *buffer, size_t size, size_t offset, long value) { + char number_text[16]; + snprintf(number_text, sizeof(number_text), "%ld", value); + return csv_append_text(buffer, size, offset, number_text); +} + +void format_history_csv_row(const FastEntry *entry, char *buffer, size_t size) { + if (!buffer || size == 0) { + return; + } + + buffer[0] = '\0'; + if (!entry) { + return; + } + + size_t offset = 0; + offset = csv_append_int(buffer, size, offset, (long)entry->start_time); + if (offset + 1 < size) { + buffer[offset++] = ','; + buffer[offset] = '\0'; + } + offset = csv_append_int(buffer, size, offset, (long)entry->end_time); + if (offset + 1 < size) { + buffer[offset++] = ','; + buffer[offset] = '\0'; + } + offset = csv_append_int(buffer, size, offset, (long)entry->target_minutes); + if (offset + 1 < size) { + buffer[offset++] = ','; + buffer[offset] = '\0'; + } + offset = csv_append_text(buffer, size, offset, entry->note); + if (offset + 1 < size) { + buffer[offset++] = ','; + buffer[offset] = '\0'; + } + (void)csv_append_int(buffer, size, offset, (long)entry->max_stage_reached); +} + +void format_history_csv_header(char *buffer, size_t size) { + if (!buffer || size == 0) { + return; + } + + snprintf(buffer, size, + "start_time,end_time,target_minutes,note,max_stage_reached"); +} diff --git a/src/c/fastforge_csv.h b/src/c/fastforge_csv.h new file mode 100644 index 0000000..abd2732 --- /dev/null +++ b/src/c/fastforge_csv.h @@ -0,0 +1,15 @@ +#ifndef FASTFORGE_CSV_H +#define FASTFORGE_CSV_H + +#include <stddef.h> + +#include "fastforge_types.h" + +size_t csv_append_text(char *buffer, size_t size, size_t offset, + const char *value); +size_t csv_append_int(char *buffer, size_t size, size_t offset, long value); + +void format_history_csv_row(const FastEntry *entry, char *buffer, size_t size); +void format_history_csv_header(char *buffer, size_t size); + +#endif diff --git a/src/c/fastforge_history.c b/src/c/fastforge_history.c index 8631162..9cf7711 100644 --- a/src/c/fastforge_history.c +++ b/src/c/fastforge_history.c @@ -1,4 +1,5 @@ #include "fastforge_internal.h" +#include "fastforge_csv.h" #include <stdlib.h> #include <string.h> @@ -271,102 +272,6 @@ static void stop_history_export(void) { memset(s_history_export.snapshot, 0, sizeof(s_history_export.snapshot)); } -static size_t csv_append_text(char *buffer, size_t size, size_t offset, const char *value) { - if (!buffer || size == 0 || offset >= size) { - return offset; - } - - bool needs_quotes = false; - if (value) { - for (const char *cursor = value; *cursor; cursor++) { - if (*cursor == ',' || *cursor == '"' || *cursor == '\n' || *cursor == '\r') { - needs_quotes = true; - break; - } - } - } - - if (needs_quotes) { - if (offset + 1 < size) { - buffer[offset++] = '"'; - } - if (value) { - for (const char *cursor = value; *cursor && offset + 1 < size; cursor++) { - if (*cursor == '"') { - if (offset + 2 >= size) { - break; - } - buffer[offset++] = '"'; - buffer[offset++] = '"'; - } else { - buffer[offset++] = *cursor; - } - } - } - if (offset + 1 < size) { - buffer[offset++] = '"'; - } - } else { - if (value) { - for (const char *cursor = value; *cursor && offset + 1 < size; cursor++) { - buffer[offset++] = *cursor; - } - } - } - - if (offset < size) { - buffer[offset] = '\0'; - } - return offset; -} - -static size_t csv_append_int(char *buffer, size_t size, size_t offset, long value) { - char number_text[16]; - snprintf(number_text, sizeof(number_text), "%ld", value); - return csv_append_text(buffer, size, offset, number_text); -} - -static void format_history_csv_row(const FastEntry *entry, char *buffer, size_t size) { - if (!buffer || size == 0) { - return; - } - - buffer[0] = '\0'; - if (!entry) { - return; - } - - size_t offset = 0; - offset = csv_append_int(buffer, size, offset, (long)entry->start_time); - if (offset + 1 < size) { - buffer[offset++] = ','; - buffer[offset] = '\0'; - } - offset = csv_append_int(buffer, size, offset, (long)entry->end_time); - if (offset + 1 < size) { - buffer[offset++] = ','; - buffer[offset] = '\0'; - } - offset = csv_append_int(buffer, size, offset, (long)entry->target_minutes); - if (offset + 1 < size) { - buffer[offset++] = ','; - buffer[offset] = '\0'; - } - offset = csv_append_text(buffer, size, offset, entry->note); - if (offset + 1 < size) { - buffer[offset++] = ','; - buffer[offset] = '\0'; - } - (void)csv_append_int(buffer, size, offset, (long)entry->max_stage_reached); -} - -static void format_history_csv_header(char *buffer, size_t size) { - if (!buffer || size == 0) { - return; - } - snprintf(buffer, size, "start_time,end_time,target_minutes,note,max_stage_reached"); -} - static const char *history_export_status_for_row(void) { if (s_history_export.next_row == 0) { return s_history_export.snapshot_count == 0 ? "EXPORT_COMPLETE" : "EXPORT_STARTED"; |
