diff options
| author | dam <dam@gudinoff> | 2022-09-28 22:37:22 +0000 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2022-09-28 22:37:22 +0000 |
| commit | 8d2f93fe0497c322f2243cad123b70543cab9eac (patch) | |
| tree | 2974e2a45e382042b8c6108f31509ae846b15980 | |
| parent | 47c212995981145cdf620144c8ce8de7b1e5d634 (diff) | |
| download | task-time-tracker-8d2f93fe0497c322f2243cad123b70543cab9eac.tar.zst task-time-tracker-8d2f93fe0497c322f2243cad123b70543cab9eac.zip | |
Preparing to store archive as CSV to allow appending to it.
| -rw-r--r-- | main.c | 73 |
1 files changed, 55 insertions, 18 deletions
@@ -17,14 +17,14 @@ #define MAX_TASK_NAME 58 // Maximum task name length, including null-terminator. #define FIRST_DAY_OF_WEEK 1 // (0-6, Sunday = 0) -#define WEEK_DAYS 7 // Why not? +#define WEEK_DAYS 7 // Just to avoid magic numbers. #define LOG_FILE_NAME "log.txt" #define DB_BIN_PATH_NAME "./database.bin" -#define AR_BIN_PATH_NAME "./archive.bin" +#define AR_CSV_PATH_NAME "./archive.csv" typedef struct /*__attribute__((__packed__))*/ { - int64_t times[7]; + int64_t times[WEEK_DAYS]; char name[MAX_TASK_NAME]; } task_t; // TODO Rename to task_st @@ -35,7 +35,7 @@ typedef struct /*__attribute__((__packed__))*/ { ptrdiff_t active_task; ptrdiff_t selected_task; int64_t modified_on; - int64_t total_times[7]; + int64_t total_times[WEEK_DAYS]; } database_t; // TODO Rename to database_st #define DB_FILE_SIGN_STR "TTT:B:01" @@ -52,6 +52,10 @@ database_t database; database_t archive; database_t *db; +char *string_buffer; +int size_x, size_y, pos_x, pos_y; + + // Given an UTF8 encoded string, truncate it to length without breaking any UTF8 character. // The string should have capacity for at least length number of items. // The terminating null byte ('\0') is included in length. @@ -254,7 +258,7 @@ bool add_task(database_t *db, task_t *task) { memcpy(new_task, task, SIZEOF_TASK_T); // Add task timer values to total timers. - for (int idx = 0; idx < 7; idx++) { + for (int idx = 0; idx < WEEK_DAYS; idx++) { // db->total_times[idx] += task->times[idx]; TODO db->total_times[idx] = add_time(db->total_times[idx], task->times[idx]); } @@ -270,7 +274,7 @@ bool delete_task(database_t *db, task_t *task) { assert(task >= db->tasks && task < &db->tasks[db->count]); // Remove task timer values from total timers. - for (int idx = 0; idx < 7; idx++) { + for (int idx = 0; idx < WEEK_DAYS; idx++) { // db->total_times[idx] -= task->times[idx]; TODO db->total_times[idx] = sub_time(db->total_times[idx], task->times[idx]); } @@ -470,7 +474,7 @@ bool import_from_csv(database_t *db, const char *path_name) { &task->times[4], &task->times[5], &task->times[6] - ) != 7) { + ) != WEEK_DAYS) { replace_char(csv_buffer, '\n', ' '); fprintf(stderr, "Discarding invalid line '%s' and continuing.\n", csv_buffer); delete_task(db, task); @@ -478,7 +482,7 @@ bool import_from_csv(database_t *db, const char *path_name) { } // Add task timer values to total timers. - for (int idx = 0; idx < 7; idx++) { + for (int idx = 0; idx < WEEK_DAYS; idx++) { // db->total_times[idx] += task->times[idx]; TODO db->total_times[idx] = add_time(db->total_times[idx], task->times[idx]); } @@ -490,6 +494,41 @@ bool import_from_csv(database_t *db, const char *path_name) { return true; } +bool append_to_csv(task_t *task, const char *path_name) { + assert(task != NULL); + assert(path_name != NULL); + + FILE *file = fopen(path_name, "a+"); + if (file == NULL) { + fprintf(stderr, "Failed to open file '%s' while appending to CSV: %s.\n", path_name, strerror(errno)); + return false; + } + + char last_char; + fseek(file, -1, SEEK_END); + fread(&last_char, sizeof(char), 1, file); + if (last_char != '\n') { + fprintf(file, "\n"); + } + + char name[MAX_TASK_NAME]; + memcpy(name, task->name, MAX_TASK_NAME); + replace_char(name, ',', ' '); + fprintf(file, "%s,%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 "\n", + name, + task->times[0], + task->times[1], + task->times[2], + task->times[3], + task->times[4], + task->times[5], + task->times[6] + ); + + fclose(file); + return true; +} + void update_timers(database_t *db) { // Get current UTC time. @@ -535,7 +574,7 @@ void update_total_timers(database_t *db) { int64_t *d4 = &db->total_times[4]; int64_t *d5 = &db->total_times[5]; int64_t *d6 = &db->total_times[6]; - memset(db->total_times, 7, sizeof(int64_t)); + memset(db->total_times, WEEK_DAYS, sizeof(int64_t)); for (size_t idx = 0; idx < db->count; idx++) { int64_t *times = db->tasks[idx].times; @@ -623,8 +662,6 @@ void prototype(test_et level) { } -char *string_buffer; -int size_x, size_y, pos_x, pos_y; #define NUM_OF_COLUMNS 9 @@ -1114,14 +1151,14 @@ int main(int argc, char *argv[]) { case KEY_BACKSPACE: if (db == &database) { - if (load_database(&archive, AR_BIN_PATH_NAME) == false) { - store_database(&archive, AR_BIN_PATH_NAME); + if (load_database(&archive, AR_CSV_PATH_NAME) == false) { + store_database(&archive, AR_CSV_PATH_NAME); } db = &archive; db->active_task = -1; // TODO This should not be necessary. } else { - store_database(&archive, AR_BIN_PATH_NAME); + store_database(&archive, AR_CSV_PATH_NAME); reset_database(&archive); db = &database; } @@ -1138,15 +1175,15 @@ int main(int argc, char *argv[]) { // instead of loading adding and storing every single time. // If the archive was in CSV, we could simply append to it. Let's do this! if (db == &database) { - if (load_database(&archive, AR_BIN_PATH_NAME) == false) { - store_database(&archive, AR_BIN_PATH_NAME); + if (load_database(&archive, AR_CSV_PATH_NAME) == false) { + store_database(&archive, AR_CSV_PATH_NAME); } } database_t *target = (db == &database ? &archive : &database); add_task(target, selected_task); delete_task(db, selected_task); if (db == &database) { - store_database(&archive, AR_BIN_PATH_NAME); + store_database(&archive, AR_CSV_PATH_NAME); reset_database(&archive); } break; @@ -1210,7 +1247,7 @@ int main(int argc, char *argv[]) { update_timers(&database); store_database(&database, DB_BIN_PATH_NAME); if (db == &archive) { - store_database(&archive, AR_BIN_PATH_NAME); + store_database(&archive, AR_CSV_PATH_NAME); } free_memory(); endwin(); |
