aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c109
1 files changed, 64 insertions, 45 deletions
diff --git a/main.c b/main.c
index 0441eff..8c35d4d 100644
--- a/main.c
+++ b/main.c
@@ -9,6 +9,7 @@
#include <limits.h>
#include <ncurses.h>
#include <stdbool.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -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;
}