aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--task_tracker.c368
1 files changed, 125 insertions, 243 deletions
diff --git a/task_tracker.c b/task_tracker.c
index 926d3c8..b21ad3c 100644
--- a/task_tracker.c
+++ b/task_tracker.c
@@ -19,10 +19,12 @@
#define FIRST_DAY_OF_WEEK 1 // (0-6, Sunday = 0)
#define LOG_FILE_NAME "log.txt"
-#define DB_FILE_NAME "database.bin"
+#define DB_BIN_PATH_NAME "./database.bin"
#define DB_CSV_PATH_NAME "./database.csv"
+// TODO The hash is overkill... right? And I could decouple it from the task_t.
+
struct task_event {
char* name;
time_t start;
@@ -30,18 +32,18 @@ struct task_event {
};
typedef struct {
+ char name[MAX_TASK_NAME+1]; // Allow space for null termination char.
+ uint32_t time[7];
uint32_t hash;
// uint32_t time[sizeof(DAYS_OF_WEEK)];
// #define DAYS_ON_WEEK sizeof(DAYS_OF_WEEK)
// uint32_t time[DAYS_ON_WEEK];
- uint32_t time[7];
- char name[MAX_TASK_NAME+1]; // Allow space for null termination char.
} task_t;
-const char* DB_FILE_SIGNATURE = "TTBF:1.0";
-const uint8_t FILE_SIGNATURE_SIZE = sizeof(DB_FILE_SIGNATURE);
-const size_t TASK_INFO_SIZE = sizeof(task_t);
+const char* DB_BIN_FILE_SIGNATURE = "TTBF:1.0";
+const uint8_t DB_BIN_FILE_SIGNATURE_SIZE = sizeof(DB_BIN_FILE_SIGNATURE);
+const size_t SIZEOF_TASK_T = sizeof(task_t);
const char* DAYS_OF_WEEK[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
const uint8_t DAYS_ON_WEEK = sizeof(DAYS_OF_WEEK)/sizeof(char*);
@@ -142,45 +144,41 @@ void print_task(const task_t* task) {
printf("t[6]: '%" PRIu32 "'\n", task->time[6]);
}
-void store_database(const task_t* database, uint32_t number_of_entries) {
+void store_database(const task_t* database, uint32_t number_of_entries, const char* path_name) {
- // TODO Maybe move this to global level?
- const char* DB_FILE_SIGNATURE = "TTBF:1.0";
- const uint8_t FILE_SIGNATURE_SIZE = sizeof(DB_FILE_SIGNATURE);
- const size_t TASK_INFO_SIZE = sizeof(task_t);
+ assert(database != NULL);
+ assert(path_name != NULL);
// Open file.
- FILE* file = fopen("./" DB_FILE_NAME, "w");
+ FILE* file = fopen(path_name, "w");
if (file == NULL) {
fprintf(stderr, "Failed to open database file: %s.\n", strerror(errno)); // TODO Fix message.
return;
}
- fwrite(DB_FILE_SIGNATURE, sizeof(char), FILE_SIGNATURE_SIZE, file);
+ fwrite(DB_BIN_FILE_SIGNATURE, sizeof(char), DB_BIN_FILE_SIGNATURE_SIZE, file);
fwrite(&number_of_entries, sizeof(number_of_entries), 1, file);
- fwrite(database, TASK_INFO_SIZE, number_of_entries, file);
+ fwrite(database, SIZEOF_TASK_T, number_of_entries, file);
fclose(file);
}
-uint32_t load_database(task_t** database) {
+uint32_t load_database(task_t** database, const char* path_name) {
- // TODO Maybe move this to global level?
- const char* DB_FILE_SIGNATURE = "TTBF:1.0";
- const uint8_t FILE_SIGNATURE_SIZE = sizeof(DB_FILE_SIGNATURE);
- const size_t TASK_INFO_SIZE = sizeof(task_t);
+ assert(database != NULL);
+ assert(path_name != NULL);
// Open file.
- FILE* file = fopen("./" DB_FILE_NAME, "r");
+ FILE* file = fopen(path_name, "r");
if (file == NULL) {
- fprintf(stderr, "Failed to open database file: %s.\n", strerror(errno)); // TODO Fix message.
+ fprintf(stderr, "Failed to open database file '%s': %s.\n", path_name, strerror(errno)); // TODO Fix message.
return 0;
}
// Validate file signature.
- char file_signature[FILE_SIGNATURE_SIZE];
- fread(&file_signature, sizeof(char), FILE_SIGNATURE_SIZE, file);
- if (strncmp(file_signature, DB_FILE_SIGNATURE, FILE_SIGNATURE_SIZE) != 0) {
+ char file_signature[DB_BIN_FILE_SIGNATURE_SIZE];
+ fread(&file_signature, sizeof(char), DB_BIN_FILE_SIGNATURE_SIZE, file);
+ if (strncmp(file_signature, DB_BIN_FILE_SIGNATURE, DB_BIN_FILE_SIGNATURE_SIZE) != 0) {
fprintf(stderr, "Invalid file signature.\n");
return 0;
}
@@ -190,8 +188,8 @@ uint32_t load_database(task_t** database) {
fread(&number_of_entries, sizeof(number_of_entries), 1, file);
// Read database entries.
- *database = calloc(number_of_entries, TASK_INFO_SIZE);
- fread(*database, TASK_INFO_SIZE, number_of_entries, file);
+ *database = calloc(number_of_entries, SIZEOF_TASK_T);
+ fread(*database, SIZEOF_TASK_T, number_of_entries, file);
// Make sure we are reading all the file.
assert(fgetc(file) == EOF);
@@ -207,6 +205,10 @@ void export_database(const task_t* database, uint32_t number_of_entries, const c
assert(path_name != NULL);
FILE* file = fopen(path_name, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open database file '%s': %s.\n", path_name, strerror(errno)); // TODO Fix message.
+ return;
+ }
fprintf(file, "%s,%s,%s,%s,%s,%s,%s,%s\n",
"task",
@@ -243,17 +245,17 @@ uint32_t import_database(task_t** database, const char* path_name) {
FILE* file = fopen(path_name, "r");
if (file == NULL) {
- fprintf(stderr, "Failed to open database file: %s.\n", strerror(errno)); // TODO Fix message.
+ fprintf(stderr, "Failed to open database file '%s': %s.\n", path_name, strerror(errno)); // TODO Fix message.
return 0;
}
uint32_t number_of_entries = 0;
+ uint32_t capacity = 0;
task_t task;
int error;
- fscanf(file, "%*[^\n]\n");
- do {
- // TODO prepare memory for database
+ fscanf(file, "%*[^\n]\n"); // Skip header line.
+ scan_csv: {
error = fscanf(file,
"%" STR(MAX_TASK_NAME) "[^,],%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 "\n",
@@ -267,14 +269,28 @@ uint32_t import_database(task_t** database, const char* path_name) {
&task.time[6]
);
- // TODO At this point we are reading one more... that's why we are reduccing the number_of_entries after the while.
- task.hash = hash_string(task.name);
- print_task(&task);
- number_of_entries++;
-
- } while(error > 0);
- assert(number_of_entries == 3);
+ if (error != EOF)
+ {
+ task.hash = hash_string(task.name);
+ number_of_entries++;
+
+ // Expand tasks capacity if required.
+ if (number_of_entries > capacity) {
+ capacity = capacity == 0 ? 16 : capacity << 1;
+ *database = reallocarray(*database, capacity, SIZEOF_TASK_T);
+ if (errno != 0 || errno == ENOMEM) {
+ ; // TODO reallocarray failed
+ }
+ }
+ memcpy(&((*database)[number_of_entries-1]), &task, SIZEOF_TASK_T);
+
+ goto scan_csv;
+ }
+ }
+ assert(number_of_entries == 3);
+ *database = reallocarray(*database, number_of_entries, SIZEOF_TASK_T);
+ // TODO check for allocation errors.
// if (error != EOF) {
// fprintf(stderr, "Failed to parse database file: %s.\n", strerror(errno));
// }
@@ -301,12 +317,12 @@ void add_task(char* name) {
if (tasks_count >= tasks_capacity)
{
tasks_capacity = tasks_capacity == 0 ? 16 : tasks_capacity << 1;
- tasks = realloc(tasks, sizeof(task_t) * tasks_capacity);
+ tasks = realloc(tasks, SIZEOF_TASK_T * tasks_capacity);
}
// Add new task entry.
task_t* new_task = &tasks[tasks_count];
- memset(new_task, '0', sizeof(task_t));
+ memset(new_task, '0', SIZEOF_TASK_T);
strncpy(new_task->name, name, MAX_TASK_NAME);
new_task->name[MAX_TASK_NAME] = '\0';
printf(">>> %s\n", new_task->name); // TODO debug
@@ -314,240 +330,106 @@ void add_task(char* name) {
tasks_count++;
}
-void add_task_event(char* name, uint64_t start, uint64_t end) {
- // TODO Missing the task_event array.
-}
-
void prototype() {
+ const char* done = "# -- done -- -- -- /\n";
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Get current UTC time.
+
+ fprintf(stderr, "# current UTC time --------------------------- \\\n");
+ time_t x = time(NULL);
+ printf("%s", ctime(&x));
+ fprintf(stderr, done);
+
+
///////////////////////////////////////////////////////////////////////////
// Get current day of the week.
- fprintf(stderr, "# current day of the week --------------------- |\n");
+
+ fprintf(stderr, "# current day of the week --------------------- \\\n");
time_t now_ut = time(NULL);
uint8_t week_day = localtime(&now_ut)->tm_wday;
- fprintf(stderr, "> %d\n", week_day);
+ fprintf(stderr, "%d\n", week_day);
+ fprintf(stderr, done);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Prepare some data for testing.
+
+ uint32_t tasks_count = 3;
+ task_t* tasks = calloc(SIZEOF_TASK_T, 3);
+
+ task_t tmp[3] = {
+ {
+ .name = "TASK-00 : Sample task name.",
+ .time = { 3,2,1,0,1,2,3 },
+ .hash = hash_string("TASK-00 : Sample task name.")
+ },
+ {
+ .name = "TASK-01 : A wild task appears",
+ .time = { 1,2,3,4,5,6,7 },
+ .hash = hash_string("TASK-01 : A wild task appears")
+ },
+ {
+ .name = "BAZINGA : Not a task!",
+ .time = { 11,22,33,44,55,66,77 },
+ .hash = hash_string("BAZINGA : Not a task!")
+ }
+ };
+ memcpy(tasks, &tmp, SIZEOF_TASK_T * 3);
///////////////////////////////////////////////////////////////////////////
// Store database from memory to binary file.
- /*
- fprintf(stderr, "# store database ------------------------------ |\n");
- task_t task;
- memset(&task, '0', TASK_INFO_SIZE);
- strncpy(task.name, "TASK-00 : Sample task name.", MAX_TASK_NAME+1);
- task.time[0] = 0;
- task.time[1] = 10;
- task.time[2] = 11;
- task.time[3] = 12;
- task.time[4] = 333;
- task.time[5] = 555;
- task.time[6] = 777;
- task.hash = hash_string(task.name);
- print_task(&task);
- store_database(&task, 1);
- */
+
+ fprintf(stderr, "# store database ------------------------------ \\\n");
+ store_database(tasks, tasks_count, DB_BIN_PATH_NAME);
+ fprintf(stderr, done);
+
///////////////////////////////////////////////////////////////////////////
// Load database from binary file to memory.
- fprintf(stderr, "# load database ------------------------------- |\n");
+
+ fprintf(stderr, "# load database ------------------------------- \\\n");
task_t* task_load = NULL;
- uint32_t number_of_entries_load = load_database(&task_load);
+ uint32_t number_of_entries_load = load_database(&task_load, DB_BIN_PATH_NAME);
- fprintf(stderr, "> loaded %" PRIu32 " entries.\n", number_of_entries_load);
- print_task(task_load);
+ fprintf(stderr, "loaded %" PRIu32 " entries.\n", number_of_entries_load);
+ for (uint32_t idx = 0; idx < number_of_entries_load; idx++) {
+ print_task(&task_load[idx]);
+ }
free(task_load);
+ fprintf(stderr, done);
///////////////////////////////////////////////////////////////////////////
// Export database to CSV file.
- /*
- fprintf(stderr, "# export to CSV ------------------------------- |\n");
- export_database(&task, 1);
- export_database(NULL, 1, "");
- */
- fprintf(stderr, "# import from CSV ----------------------------- |\n");
- task_t* task_import = NULL;
- uint32_t number_of_entries_import = import_database(&task_import, DB_CSV_PATH_NAME);
+ fprintf(stderr, "# export to CSV ------------------------------- \\\n");
+ export_database(tasks, tasks_count, DB_CSV_PATH_NAME);
+ fprintf(stderr, done);
- fprintf(stderr, "> imported %" PRIu32 " entries.\n", number_of_entries_import);
- print_task(task_import);
- free(task_import);
- return;
+ ///////////////////////////////////////////////////////////////////////////
+ // Import database from CSV file.
+ fprintf(stderr, "# import from CSV ----------------------------- \\\n");
+ task_t* task_import = NULL;
+ uint32_t number_of_entries_import = import_database(&task_import, DB_CSV_PATH_NAME);
- const char* csv_head = "task_name,start,end";
- const char* csv_line[] = {
- "PI-0000,1659479138,1659482738",
- "PI-0001,1659479127,1659482727",
- "XPTO-01 : testing long name,1659379138,1659382738",
- "XPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long name,123,124",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccc:ddddddddddddddddddddddddddddddddddddd:eeeeeeeeeeeeeeeeeeeeee:fffffffffffffffffff,123,456",
- "Olá vamos cantar uma canção.,1659279127,1659282727",
- "[ TST-00 á],1659579138,1659582738",
- "[ XPTO- 01,1659179127,1659182727",
- "[ TST-00 á],1659479138,1659482738",
- "[ XPTO- 01,1659429127,1659482727",
- "[ TST-00 á],1658479138,1658482738",
- "[ XPTO- 01,1659669127,1659672727",
- "[ TST-00 á],1658879138,1658882738",
- "[ XPTO- 01,1656579127,1656582727",
- "[ TST-00 á],1659439138,1659492738",
- "[ XPTO- 01,1655579127,1655682727",
- "[ TST-00 á],1657679138,1657782738",
- "[ XPTO- 01,1658179127,1658382727",
- "[ TST-00 á],1651479138,1651482738",
- "[ XPTO- 01,1659479127,1659482727",
- "[ TST-00 á],1659079138,1659082738",
- "[ XPTO- 01,1659379127,1659382727",
- };
-// const char* csv_line = "1659479138,1659482738";
-// const char* csv_line = "zZ[ ã ]Yy,123";
-
-// char name[] = { 'a', 'b', 'c', '\0' };
- char* name;
- uint64_t start;
- uint64_t end;
- printf("--- --- àè.ªãº.éá --- ---\n");
-
- //////////////////////////////////////////////////
- // TODO Use this to parse the tasks names. TODO //
- // TODO WIP TODO WIP TODO WIP TODO
- const char* task_info_A = "Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel turpis nunc eget lorem. Non pulvinar neque laoreet suspendisse interdum consectetur libero id,165147,14790,9138,1,2,3,4";
- const char* task_info_B = "Lorem,165147,14790,9138,1,2,3,4";
-
-#define COISA
-#define SPACER "%*[^,]"
-
- const char* format = "%" STR(MAX_TASK_NAME) "[^,]" SPACER ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32;
-
-// task_t task_A;
-// sscanf(task_info_A, format,
-// task_A.name,
-// &task_A.time[0],
-// &task_A.time[1],
-// &task_A.time[2],
-// &task_A.time[3],
-// &task_A.time[4],
-// &task_A.time[5],
-// &task_A.time[6]
-// ); // TODO WIP
-
- const char* format_X = "%" STR(MAX_TASK_NAME) "[^,]";
-
- task_t task_A;
- sscanf(task_info_A, format_X,
- task_A.name
- ); // TODO WIP
-
- const char* format_Y = "%*[^,],%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32;
-
- sscanf(task_info_A, format_Y,
- &task_A.time[0],
- &task_A.time[1],
- &task_A.time[2],
- &task_A.time[3],
- &task_A.time[4],
- &task_A.time[5],
- &task_A.time[6]
- ); // TODO WIP
-
-// task_t task_B;
-// sscanf(task_info_B,format,
-// task_B.name,
-// &task_B.time[0],
-// &task_B.time[1],
-// &task_B.time[2],
-// &task_B.time[3],
-// &task_B.time[4],
-// &task_B.time[5],
-// &task_B.time[6]
-// ); // TODO WIP
-
- task_t task_B;
- sscanf(task_info_B,format_X,
- task_B.name
- ); // TODO WIP
-
- sscanf(task_info_B,format_Y,
- &task_B.time[0],
- &task_B.time[1],
- &task_B.time[2],
- &task_B.time[3],
- &task_B.time[4],
- &task_B.time[5],
- &task_B.time[6]
- ); // TODO WIP
-
- printf("--------------------------------------------------\n");
- printf("name: '%s'\n", task_A.name);
- printf("t[0]: '%d'\n", task_A.time[0]);
- printf("t[1]: '%d'\n", task_A.time[1]);
- printf("t[2]: '%d'\n", task_A.time[2]);
- printf("t[3]: '%d'\n", task_A.time[3]);
- printf("t[4]: '%d'\n", task_A.time[4]);
- printf("t[5]: '%d'\n", task_A.time[5]);
- printf("t[6]: '%d'\n", task_A.time[6]);
-
- printf("name: '%s'\n", task_B.name);
- printf("t[0]: '%d'\n", task_B.time[0]);
- printf("t[1]: '%d'\n", task_B.time[1]);
- printf("t[2]: '%d'\n", task_B.time[2]);
- printf("t[3]: '%d'\n", task_B.time[3]);
- printf("t[4]: '%d'\n", task_B.time[4]);
- printf("t[5]: '%d'\n", task_B.time[5]);
- printf("t[6]: '%d'\n", task_B.time[6]);
- printf("--------------------------------------------------\n");
-
- ///////////////////////////////////////////////////////////////
-
- uint32_t lines_count = sizeof(csv_line)/sizeof(char*);
- for (uint32_t idx = 0; idx < lines_count; idx++)
- {
- // TODO The following sscanf is allocating memory for the name... we should remove it.
-// uint32_t max_task_name
-
- // TODO The m modifier requires us to free the memory returned.
- sscanf(csv_line[idx], "%" STR(MAX_TASK_NAME) "m[^,\n],%" SCNu64 ",%" SCNu64, &name, &start, &end); // TODO WIP
- add_task(name);
-// printf("bazinga: %s : %d : %d\n", name, start, end);
-// printf("bazinga: %s : %.19s : %.19s\n", name, ctime(&start), ctime(&end));
- printf("bazonga: %s\n", tasks[tasks_count-1].name);
+ fprintf(stderr, "imported %" PRIu32 " entries.\n", number_of_entries_import);
+ for (uint32_t idx = 0; idx < number_of_entries_import; idx++) {
+ print_task(&task_import[idx]);
}
-
- printf("### ### --------- ### ###\n");
-
-// tasks_names =
+ free(task_import);
+ fprintf(stderr, done);
- // Free tasks names.
- for (uint32_t idx = tasks_names_size; idx > 0; idx--)
- {
- printf("> %s\n", tasks_names[idx-1]); // @dam TODO debug
- free(tasks_names[idx-1]);
- }
- free(tasks_names);
+ ///////////////////////////////////////////////////////////////////////////
+ // Release memory and exit.
+ free(tasks);
return;
-
-// tasks_names = malloc( ...
-
- time_t x = time(NULL);
-// x = (time_t)((1U << 32) - 1);
- printf("%s\n", ctime(&x));
- x = x<<1;
- printf("%s\n", ctime(&x));
- x += 1;
- printf("%s\n", ctime(&x));
- x = x<<1;
- printf("%s\n", ctime(&x));
- x = x<<1;
- printf("%s\n", ctime(&x));
- x = x<<1;
- printf("%s\n", ctime(&x));
- x = x<<1;
- printf("%s\n", ctime(&x));
}