diff options
author | Ariadna Vigo <arivigodr@gmail.com> | 2020-08-08 20:22:28 +0200 |
---|---|---|
committer | Ariadna Vigo <arivigodr@gmail.com> | 2020-08-08 20:46:19 +0200 |
commit | a72a5c9685b0c45d8b45c94bb4ec069ecc22f9a5 (patch) | |
tree | 141f659acd6ee2adca8f9ef6d6f9cf0535223d24 | |
parent | 95704a9cf40e456d882cf369f63851f4d29efb61 (diff) |
Number of tasks is no longer limited
-rw-r--r-- | cras.c | 139 | ||||
-rw-r--r-- | tasklst.c | 143 | ||||
-rw-r--r-- | tasklst.h | 32 |
3 files changed, 193 insertions, 121 deletions
@@ -29,17 +29,17 @@ enum { static void die(const char *fmt, ...); static void printf_color(const char *ansi_color, const char *fmt, ...); -static void print_task(TaskLst tasks, int i); -static void print_short_output(TaskLst tasks); -static void print_output(TaskLst tasks); -static int read_crasfile(TaskLst *tasks, const char *crasfile); -static void write_crasfile(const char *crasfile, TaskLst tasks); -static int store_input(TaskLst *tasks, FILE *fp); +static void print_task(Task task, int i); +static void print_short_output(TaskLst list); +static void print_output(TaskLst list); +static int read_crasfile(TaskLst *list, const char *crasfile); +static void write_crasfile(const char *crasfile, TaskLst list); +static int store_input(TaskLst *list, FILE *fp); static void usage(void); static void new_mode(const char *crasfile); static void output_mode(const char *crasfile, int mode); -static void mark_tasks_mode(const char *crasfile, const char *id, int value); +static void mark_list_mode(const char *crasfile, const char *id, int value); static void die(const char *fmt, ...) @@ -70,7 +70,7 @@ printf_color(const char *ansi_color, const char *fmt, ...) } static void -print_task(TaskLst tasks, int i) +print_task(Task task, int i) { const char *todo_color, *done_color; @@ -83,46 +83,45 @@ print_task(TaskLst tasks, int i) done_color = task_done_color; } - /* Null tasks are never printed */ - if (tasks.status[i] == TASK_VOID) - return; - printf("#%02d ", i + 1); - if (tasks.status[i] == TASK_TODO) + if (task.status == TASK_TODO) printf_color(todo_color, "%s ", task_todo_str); else /* TASK_DONE */ printf_color(done_color, "%s ", task_done_str); - printf("%s\n", tasks.tdesc[i]); + printf("%s\n", task.tdesc); } static void -print_short_output(TaskLst tasks) +print_short_output(TaskLst list) { - printf("%d/%d/%d", tasklst_tasks_todo(tasks), - tasklst_tasks_done(tasks), tasklst_tasks_total(tasks)); + printf("%d/%d/%d", task_lst_count_todo(list), + task_lst_count_done(list), task_lst_get_size(list)); } static void -print_output(TaskLst tasks) +print_output(TaskLst list) { int i; + Task *ptr; - printf("Due date: %s\n", ctime(&tasks.expiry)); + printf("Due date: %s\n", ctime(&list.expiry)); - for(i = 0; i < TASK_LST_MAX_NUM; ++i) - print_task(tasks, i); + for(i = 0, ptr = list.first; ptr != NULL; ptr = ptr->next) { + print_task(*ptr, i); + ++i; + } if (i > 0) putchar('\n'); - print_short_output(tasks); + print_short_output(list); printf(" to do/done/total"); } static int -read_crasfile(TaskLst *tasks, const char *crasfile) +read_crasfile(TaskLst *list, const char *crasfile) { int read_stat; FILE *fp; @@ -131,47 +130,52 @@ read_crasfile(TaskLst *tasks, const char *crasfile) if (errno == ENOENT) return -1; /* We give the chance to create the file later. */ - if (fp == NULL) + if (fp == NULL) { + task_lst_cleanup(list); die("Could not read from %s: %s", crasfile, strerror(errno)); + } - read_stat = tasklst_read_from_file(tasks, fp); + read_stat = task_lst_read_from_file(list, fp); fclose(fp); - if (read_stat < 0) + if (read_stat < 0) { + task_lst_cleanup(list); die("Parsing error: task file corrupted."); + } - if (tasklst_expired(*tasks) > 0) - die("Due date passed (%d tasks overdue).", - tasklst_tasks_todo(*tasks)); + if (task_lst_expired(*list) > 0) { + task_lst_cleanup(list); + die("Due date passed (%d list overdue).", + task_lst_count_todo(*list)); + } return 0; } static void -write_crasfile(const char *crasfile, TaskLst tasks) +write_crasfile(const char *crasfile, TaskLst list) { FILE *fp; - if ((fp = fopen(crasfile, "w")) == NULL) + if ((fp = fopen(crasfile, "w")) == NULL) { + task_lst_cleanup(&list); die("Could not write to %s: %s", crasfile, strerror(errno)); + } - tasklst_write_to_file(fp, tasks); + task_lst_write_to_file(fp, list); fclose(fp); } static int -store_input(TaskLst *tasks, FILE *fp) +store_input(TaskLst *list, FILE *fp) { char linebuf[TASK_LST_DESC_MAX_SIZE]; - int i; - - for (i = 0; i < TASK_LST_MAX_NUM; ++i) { + + while (feof(fp) == 0) { fgets(linebuf, TASK_LST_DESC_MAX_SIZE, fp); - if (feof(fp) != 0) - return 0; linebuf[strlen(linebuf) - 1] = '\0'; /* Chomp '\n' */ - if (tasklst_add_task(tasks, TASK_TODO, linebuf) < 0) + if (task_lst_add_task(list, TASK_TODO, linebuf) < 0) return -1; } @@ -188,60 +192,73 @@ static void new_mode(const char *crasfile) { int file_exists; - TaskLst tasks; + TaskLst list; - tasklst_init(&tasks); - file_exists = read_crasfile(&tasks, crasfile); + task_lst_init(&list); + file_exists = read_crasfile(&list, crasfile); - if (store_input(&tasks, stdin) < 0) + if (store_input(&list, stdin) < 0) fprintf(stderr, "Warning: Task file already full.\n"); if (file_exists < 0) /* Only set if this is a new file */ - tasklst_set_expiration(&tasks, crasfile_expiry); - write_crasfile(crasfile, tasks); + task_lst_set_expiration(&list, crasfile_expiry); + write_crasfile(crasfile, list); + + task_lst_cleanup(&list); } static void output_mode(const char *crasfile, int mode) { - TaskLst tasks; + TaskLst list; - tasklst_init(&tasks); - read_crasfile(&tasks, crasfile); + task_lst_init(&list); + read_crasfile(&list, crasfile); if (mode == SHORT_OUTPUT) - print_short_output(tasks); + print_short_output(list); else - print_output(tasks); + print_output(list); putchar('\n'); + + task_lst_cleanup(&list); } static void -mark_tasks_mode(const char *crasfile, const char *id, int value) +mark_list_mode(const char *crasfile, const char *id, int value) { int tasknum; char *endptr; - TaskLst tasks; + TaskLst list; + Task *task; tasknum = strtol(id, &endptr, 10); if (endptr[0] != '\0') die("'%s' not a number.", id); - tasklst_init(&tasks); - read_crasfile(&tasks, crasfile); + task_lst_init(&list); + read_crasfile(&list, crasfile); - if (tasknum <= 0) + if (tasknum <= 0) { + task_lst_cleanup(&list); die("Task number must be greater than zero."); + } - if (tasknum <= tasklst_tasks_total(tasks)) - tasks.status[tasknum - 1] = value; - else + if (tasknum <= task_lst_get_size(list)) + task = task_lst_get_task(list, tasknum - 1); + + if (task == NULL) { + task_lst_cleanup(&list); die("Task #%d does not exist.", tasknum); + } + + task->status = value; + write_crasfile(crasfile, list); - write_crasfile(crasfile, tasks); + print_task(*task, tasknum - 1); - print_task(tasks, tasknum - 1); + task_lst_cleanup(&list); } int @@ -295,7 +312,7 @@ main(int argc, char *argv[]) output_mode(argv[0], SHORT_OUTPUT); return 0; case MARK_MODE: - mark_tasks_mode(argv[0], numarg, task_value); + mark_list_mode(argv[0], numarg, task_value); return 0; } @@ -8,91 +8,144 @@ #include "tasklst.h" -static int tasklst_tasks_status(TaskLst tasks, int status); +static int task_lst_count_status(TaskLst list, int status); +static Task *task_lst_get_last_task(TaskLst list); static int -tasklst_tasks_status(TaskLst tasks, int status) +task_lst_count_status(TaskLst list, int status) { - int i, total; + int total; + Task *ptr; - for (i = 0, total = 0; i < TASK_LST_MAX_NUM; ++i) { - if (tasks.status[i] == status) + for (ptr = list.first, total = 0; ptr != NULL; ptr = ptr->next) { + if (ptr->status == status) ++total; } return total; } -void -tasklst_init(TaskLst *tasks) +static Task * +task_lst_get_last_task(TaskLst list) { - int i; + Task *ptr, *next; - tasks->expiry = 0; + ptr = list.first; + while (ptr != NULL) { + next = ptr->next; + if (next == NULL) + return ptr; - for (i = 0; i < TASK_LST_MAX_NUM; ++i) { - memset(&tasks->status[i], TASK_VOID, sizeof(int)); - memset(tasks->tdesc[i], 0, TASK_LST_DESC_MAX_SIZE); + ptr = next; } + + return ptr; +} + +void +task_lst_init(TaskLst *list) +{ + list->expiry = 0; + list->first = NULL; } void -tasklst_set_expiration(TaskLst *tasks, int64_t delta) +task_lst_cleanup(TaskLst *list) { - tasks->expiry = time(NULL) + delta; + Task *ptr, *next; + + ptr = list->first; + while (ptr != NULL) { + next = ptr->next; + free(ptr); + ptr = next; + } } int -tasklst_expired(TaskLst tasks) +task_lst_get_size(TaskLst list) { - return (time(NULL) > tasks.expiry) ? 1 : 0; + Task *ptr; + int count; + + for (count = 0, ptr = list.first; ptr != NULL; ptr = ptr->next) + ++count; + + return count; +} + +void +task_lst_set_expiration(TaskLst *list, int64_t delta) +{ + list->expiry = time(NULL) + delta; } int -tasklst_tasks_total(TaskLst tasks) +task_lst_expired(TaskLst list) { - return tasklst_tasks_todo(tasks) + tasklst_tasks_done(tasks); + return (time(NULL) > list.expiry) ? 1 : 0; } int -tasklst_tasks_todo(TaskLst tasks) +task_lst_count_todo(TaskLst list) { - return tasklst_tasks_status(tasks, TASK_TODO); + return task_lst_count_status(list, TASK_TODO); } int -tasklst_tasks_done(TaskLst tasks) +task_lst_count_done(TaskLst list) { - return tasklst_tasks_status(tasks, TASK_DONE); + return task_lst_count_status(list, TASK_DONE); } int -tasklst_add_task(TaskLst *tasks, int status, const char *str) +task_lst_add_task(TaskLst *list, int status, const char *str) { - int i; - - for (i = 0; i < TASK_LST_MAX_NUM; ++i) { - if (tasks->status[i] == TASK_VOID) { - strncpy(tasks->tdesc[i], str, TASK_LST_DESC_MAX_SIZE); - tasks->status[i] = status; - return i; - } - } + Task *last, *newtask; - return -1; /* We couldn't add any new task, because tasks is full */ + newtask = malloc(sizeof(Task)); + if (newtask == NULL) + return -1; + + newtask->status = status; + newtask->next = NULL; + strncpy(newtask->tdesc, str, TASK_LST_DESC_MAX_SIZE); + + last = task_lst_get_last_task(*list); + if (last == NULL) + list->first = newtask; + else + last->next = newtask; + + return 0; } +Task * +task_lst_get_task(TaskLst list, int i) +{ + Task *ptr; + + for (ptr = list.first; i > 0; ptr = ptr->next) { + if (ptr == NULL) /* We're out of bounds */ + return NULL; + + --i; + } + + return ptr; +} + int -tasklst_read_from_file(TaskLst *tasks, FILE *fp) +task_lst_read_from_file(TaskLst *list, FILE *fp) { - int i, stat_buf; + int stat_buf; char *ptr, *endptr; char linebuf[TASK_LST_DESC_MAX_SIZE]; - if (fscanf(fp, "%" SCNd64 "\n", &tasks->expiry) <= 0) + if (fscanf(fp, "%" SCNd64 "\n", &list->expiry) <= 0) return -1; - for (i = 0; i < TASK_LST_MAX_NUM && feof(fp) == 0; ++i) { + while (feof(fp) == 0) { if (fgets(linebuf, sizeof(linebuf), fp) == NULL) break; @@ -108,23 +161,19 @@ tasklst_read_from_file(TaskLst *tasks, FILE *fp) if (ptr == NULL) return -1; - tasklst_add_task(tasks, stat_buf, ptr); + task_lst_add_task(list, stat_buf, ptr); } return 0; } void -tasklst_write_to_file(FILE *fp, TaskLst tasks) +task_lst_write_to_file(FILE *fp, TaskLst list) { - int i; + Task *ptr; - fprintf(fp, "%" PRId64 "\n", tasks.expiry); + fprintf(fp, "%" PRId64 "\n", list.expiry); - for (i = 0; i < TASK_LST_MAX_NUM; ++i) { - if (tasks.status[i] == TASK_VOID) - break; - - fprintf(fp, "%d\t%s\n", tasks.status[i], tasks.tdesc[i]); - } + for (ptr = list.first; ptr != NULL; ptr = ptr->next) + fprintf(fp, "%d\t%s\n", ptr->status, ptr->tdesc); } @@ -1,27 +1,33 @@ /* See LICENSE file for copyright and license details. */ -#define TASK_LST_MAX_NUM 11 #define TASK_LST_DESC_MAX_SIZE 64 enum { - TASK_VOID, TASK_TODO, TASK_DONE }; +typedef struct TASK_ Task; +struct TASK_ { + int status; + Task *next; + char tdesc[TASK_LST_DESC_MAX_SIZE]; +}; + typedef struct { int64_t expiry; - int status[TASK_LST_MAX_NUM]; - char tdesc[TASK_LST_MAX_NUM][TASK_LST_DESC_MAX_SIZE]; + Task *first; } TaskLst; -void tasklst_init(TaskLst *tasks); -void tasklst_set_expiration(TaskLst *tasks, int64_t delta); -int tasklst_expired(TaskLst tasks); -int tasklst_tasks_total(TaskLst tasks); -int tasklst_tasks_todo(TaskLst tasks); -int tasklst_tasks_done(TaskLst tasks); -int tasklst_add_task(TaskLst *tasks, int status, const char *str); -int tasklst_read_from_file(TaskLst *tasks, FILE *fp); -void tasklst_write_to_file(FILE *fp, TaskLst tasks); +void task_lst_init(TaskLst *list); +void task_lst_cleanup(TaskLst *list); +int task_lst_get_size(TaskLst list); +void task_lst_set_expiration(TaskLst *list, int64_t delta); +int task_lst_expired(TaskLst list); +int task_lst_count_todo(TaskLst list); +int task_lst_count_done(TaskLst list); +Task *task_lst_get_task(TaskLst list, int i); +int task_lst_add_task(TaskLst *list, int status, const char *str); +int task_lst_read_from_file(TaskLst *list, FILE *fp); +void task_lst_write_to_file(FILE *fp, TaskLst list); |