From 304a45362e47f73eff6ca49b5404e48c916ea136 Mon Sep 17 00:00:00 2001 From: dam Date: Tue, 30 Aug 2022 08:52:28 +0000 Subject: Reduced size of task_t by moving state and modified on control to database_t. Implemented add_task. On binary file, store and load entire database_t. --- main.c | 109 ++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 45 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 0441eff..8c35d4d 100644 --- a/main.c +++ b/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,25 +17,25 @@ #define STR_(X) #X // Convert to string. #define STR(X) STR_(X) // Force argument expansions before converting to string. -#define MAX_TASK_NAME 64 -#define FIRST_DAY_OF_WEEK 1 // (0-6, Sunday = 0) +#define MAX_TASK_NAME 64 // Maximum task name length, including null-terminator. +#define FIRST_DAY_OF_WEEK 1 // (0-6, Sunday = 0) #define LOG_FILE_NAME "log.txt" #define DB_BIN_PATH_NAME "./database.bin" #define DB_CSV_PATH_NAME "./database.csv" -typedef /*struct __attribute__((__packed__))*/ struct { - char name[MAX_TASK_NAME]; - uint64_t modified_on; +typedef struct /*__attribute__((__packed__))*/ { uint32_t time[7]; - uint8_t state; + char name[MAX_TASK_NAME]; } task_t; -typedef /*struct __attribute__((__packed__))*/ struct { - task_t* tasks; - uint32_t count; - uint32_t capacity; +typedef struct /*__attribute__((__packed__))*/ { + uint64_t modified_on; + uint32_t count; + uint32_t capacity; + task_t* active_task; + task_t* tasks; } database_t; const char* DB_BIN_FILE_SIGNATURE = "TTBF:1.0"; @@ -74,7 +75,7 @@ size_t truncate_string_utf8(char* string, size_t length) { // Uses strchr to replace all instances of find by replace. // Returns string. -char* replace_char(char* string, char find, char replace){ +char* replace_char(char* string, char find, char replace) { char* idx = string; while((idx = strchr(idx, find)) != NULL) { *idx = replace; @@ -94,31 +95,34 @@ void print_task(const task_t* task) { printf("t[6]: '%" PRIu32 "'\n", task->time[6]); } + // TODO Maybe inline? bool add_task(database_t* db, const task_t* task) { assert(db != NULL); assert(task != NULL); - - uint32_t db_capacity = db->capacity; - if (db->count + 1 > db_capacity) { - uint32_t new_database_capacity = db_capacity == 0 ? 16 : db_capacity << 1; - - // TODO Funcky way to calculate nex power of two. - new_database_capacity--; - new_database_capacity |= new_database_capacity >> 1; - new_database_capacity |= new_database_capacity >> 2; - new_database_capacity |= new_database_capacity >> 4; - new_database_capacity |= new_database_capacity >> 8; - new_database_capacity |= new_database_capacity >> 16; - new_database_capacity++; + + if (db->count == UINT32_MAX) { + fprintf(stderr, "Database reached maximum capacity, discarding task '%s'.\n", task->name); + return false; + } + + // If necessary, expand database capacity. + uint32_t current_capacity = db->capacity; + if(db->count + 1 > db->capacity) { + uint32_t new_capacity = current_capacity == 0 ? 2 : + current_capacity >= UINT32_MAX >> 2 ? UINT32_MAX : + current_capacity << 1; - task_t* new_database_tasks = realloc(db->tasks, new_database_capacity * SIZEOF_TASK_T); + task_t* new_database_tasks = realloc(db->tasks, new_capacity * SIZEOF_TASK_T); if (new_database_tasks == NULL) { - fprintf(stderr, "Failed to expand database memory.\n"); + fprintf(stderr, "Failed to expand database, discarding task '%s'.\n", task->name); return false; } + db->capacity = new_capacity; db->tasks = new_database_tasks; } + + // Store new task. memcpy(&(db->tasks[db->count]), task, SIZEOF_TASK_T); db->count++; @@ -177,7 +181,7 @@ bool store_database(const database_t* db, const char* path_name) { } fwrite(DB_BIN_FILE_SIGNATURE, sizeof(char), DB_BIN_FILE_SIGNATURE_SIZE, file); - fwrite(&db->count, sizeof(db->count), 1, file); + fwrite(db, SIZEOF_DATABASE_T, 1, file); fwrite(db->tasks, SIZEOF_TASK_T, db->count, file); fclose(file); @@ -206,21 +210,27 @@ bool load_database(database_t* db, const char* path_name) { return false; } - // Discard all previous data. - clear_database(&database); + // Read database structure. + fread(db, SIZEOF_DATABASE_T, 1, file); + + // Keep track of last active task. + ptrdiff_t active_task_index = db->active_task - db->tasks; + + // Restore database capacity. + db->tasks = calloc(db->capacity, SIZEOF_TASK_T); - // Read number of entries. - fread(&db->count, sizeof(db->count), 1, file); + // Restore last active task. + if (db->active_task != NULL) { + db->active_task = db->tasks + active_task_index; + } // Read database entries. - db->tasks = calloc(db->count, SIZEOF_TASK_T); fread(db->tasks, SIZEOF_TASK_T, db->count, file); // Make sure we are reading all the file. assert(fgetc(file) == EOF); fclose(file); - return true; } @@ -299,7 +309,7 @@ bool import_from_csv(database_t* db, const char* path_name) { } // Clear task struct. - memset(&task, '\0', SIZEOF_TASK_T); + memset(&task, 0, SIZEOF_TASK_T); // Find task name string limits. name_delimiter = strchr(line_buffer, ','); @@ -348,7 +358,7 @@ enum TEST { T_LBIN = 0x08, T_ECSV = 0x10, T_ICSV = 0x20, - T_TTS = 0x40, + T_SOS = 0x40, T_ALL = 0xFF, }; @@ -413,7 +423,7 @@ void prototype(int level) { if (level & T_LBIN) { fprintf(stderr, "# load database ------------------------------- \\\n"); database_t db_load; - memset(&db_load, '\0', SIZEOF_DATABASE_T); + memset(&db_load, 0, SIZEOF_DATABASE_T); load_database(&db_load, DB_BIN_PATH_NAME); fprintf(stderr, "loaded %" PRIu32 " entries.\n", db_load.count); @@ -438,7 +448,7 @@ void prototype(int level) { if (level & T_ICSV) { fprintf(stderr, "# import from CSV ----------------------------- \\\n"); database_t db_import; - memset(&db_import, '\0', SIZEOF_DATABASE_T); + memset(&db_import, 0, SIZEOF_DATABASE_T); import_from_csv(&db_import, DB_CSV_PATH_NAME); fprintf(stderr, "imported %" PRIu32 " entries.\n", db_import.count); @@ -451,11 +461,20 @@ void prototype(int level) { } /////////////////////////////////////////////////////////////////////////// - // Check task_t size - if (level & T_TTS) { - fprintf(stderr, "# check task_t size --------------------------- \\\n"); - size_t tts = sizeof(task_t); - fprintf(stderr, "sizeof(super_t) = %zu bytes (%zu bits : %6.3f W64b)\n", tts, tts*8, ((double)tts)*8.0/64.0); + // Check size of structs + if (level & T_SOS) { + size_t size; + char* name; + fprintf(stderr, "# check structs sizes ------------------------- \\\n"); + + name = "database_t"; + size = sizeof(database_t); + fprintf(stderr, "sizeof(%s) = %zu bytes (%zu bits : %6.3f W64b)\n", name, size, size*8, ((double)size)*8.0/64.0); + + name = "task_t"; + size = sizeof(task_t); + fprintf(stderr, "sizeof(%s) = %zu bytes (%zu bits : %6.3f W64b)\n", name, size, size*8, ((double)size)*8.0/64.0); + fprintf(stderr, done); } } @@ -520,7 +539,7 @@ void initialization() { // TODO May use the memset or set the properties during instancing. // Prepare memory. - memset(&database, '\0', SIZEOF_DATABASE_T); + memset(&database, 0, SIZEOF_DATABASE_T); } void free_memory() { @@ -679,10 +698,10 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - action = "--t_tts"; + action = "--t_sos"; do_action = strncmp(argv[idx], action, strlen(action)) == 0; if (do_action) { - prototype(T_TTS); + prototype(T_SOS); return EXIT_SUCCESS; } -- cgit v1.2.3