Add all core functions for minion module

This commit is contained in:
2019-06-28 15:59:02 +02:00
parent 45b4f6bee0
commit b9e247b88f
5 changed files with 693 additions and 71 deletions
+182 -41
View File
@@ -18,6 +18,7 @@
#include <uuid.h>
#include <errno.h>
#include <cStuff/string.h>
#include <cStuff/file.h>
#include <components/log.h>
#include "todo.h"
@@ -25,19 +26,12 @@
AislStatus
ax_todo_init(AxTodo self, const char *file)
{
FILE *f;
uuid_generate(self->id);
uuid_generate(self->list_id);
if (!(f = fopen(file, "a+"))) {
return AISL_SYSCALL_ERROR;
}
self->file = file;
if (cstuff_list_init(&self->list, 16) != CSTUFF_SUCCESS) {
fclose(f);
if (cstuff_sprintf(&self->swap, "%s.swap", file) == -1)
return AISL_MALLOC_ERROR;
}
self->fd = f;
return AISL_SUCCESS;
}
@@ -46,32 +40,126 @@ ax_todo_init(AxTodo self, const char *file)
void
ax_todo_release(AxTodo self)
{
if (self->fd)
fclose(self->fd);
if (self->swap)
free(self->swap);
}
cstuff_list_release(&self->list, (CStuffListFree)ax_todo_task_free);
static AislStatus
ax_todo_add_project(CStuffList list, time_t completed, char *key, size_t k_len)
{
int i;
AxTodoProject proj;
for (i = 0; i < list->length; i++) {
proj = list->items[i];
if (strncmp(proj->name, key, k_len) == 0 && !proj->name[k_len]) {
proj->ref_count++;
if (proj->last_completed < completed) {
proj->last_completed = completed;
}
return true;
}
}
if (!(proj = calloc(1, sizeof (*proj))))
return false;
if (cstuff_strncpy(&proj->name, key, k_len) != -1) {
proj->ref_count = 1;
proj->last_completed = completed;
uuid_generate(proj->project_id);
if (cstuff_list_append(list, proj) != -1)
return true;
}
ax_todo_project_free(proj);
return false;
}
static AislStatus
ax_todo_add_tag(CStuffList list, char *key, size_t k_len)
{
int i;
AxTodoTag tag;
for (i = 0; i < list->length; i++) {
tag = list->items[i];
if (strncmp(tag->name, key, k_len) == 0 && !tag->name[k_len]) {
tag->ref_count++;
return true;
}
}
if (!(tag = calloc(1, sizeof (*tag))))
return false;
if (cstuff_strncpy(&tag->name, key, k_len) != -1) {
tag->ref_count = 1;
uuid_generate(tag->tag_id);
if (cstuff_list_append(list, tag) != -1)
return true;
}
ax_todo_tag_free(tag);
return false;
}
static AislStatus
ax_todo_read_keys(AxTodoTask task, CStuffList projs, CStuffList tags)
{
const char tokens[] = "+@";
char *s = task->description;
size_t offset = 0;
for (;;) {
char t;
offset = strcspn(s, tokens);
s += offset;
if ((t = *(s++)) == 0)
break;
offset = strcspn(s, " ");
if (offset) {
if ((t == '+' && !ax_todo_add_project(projs, task->completed, s, offset))
|| (t == '@' && !ax_todo_add_tag(tags, s, offset))) {
return AISL_MALLOC_ERROR;
}
s += offset;
}
}
return AISL_SUCCESS;
}
AislStatus
ax_todo_read(AxTodo self)
ax_todo_read(AxTodo self, CStuffList tasks, CStuffList projs, CStuffList tags)
{
FILE *f = self->fd;
FILE *f = NULL;
size_t sz = 256;
char *buf;
ssize_t rs;
AislStatus result = AISL_SUCCESS;
if ((fseek(f, 0L, SEEK_SET) != 0))
return AISL_SYSCALL_ERROR;
if (!(buf = malloc(sz)))
return AISL_MALLOC_ERROR;
if (!(f = fopen(self->file, "r")))
goto e_syscall;
while ((rs = getdelim(&buf, &sz, '\n', f)) != -1) {
AxTodoTask task;
if (!(task = ax_todo_task_new()))
if (!(task = ax_todo_task_new(self->list_id)))
goto e_malloc;
if (ax_todo_task_set(task, buf, rs) != 0) {
@@ -79,10 +167,14 @@ ax_todo_read(AxTodo self)
goto e_input;
}
if (cstuff_list_append(&self->list, task) == -1) {
if (cstuff_list_append(tasks, task) == -1) {
ax_todo_task_free(task);
goto e_malloc;
}
if ((result = ax_todo_read_keys(task, projs, tags)) != AISL_SUCCESS) {
goto e_malloc;
}
}
switch(errno) {
@@ -109,6 +201,8 @@ e_syscall:
finally:
free(buf);
if (f)
fclose(f);
return result;
}
@@ -124,52 +218,60 @@ ax_todo__write_dt(FILE *f, time_t dt)
AislStatus
ax_todo_write(AxTodo self)
ax_todo_write(AxTodo self, CStuffList list)
{
FILE *f = self->fd;
FILE *f;
int i;
if ((fseek(f, 0L, SEEK_SET) != 0))
if (!(f = fopen(self->swap, "w")))
return AISL_SYSCALL_ERROR;
f = self->fd;
for (i = 0; i < list->length; i++) {
AxTodoTask task = (AxTodoTask) list->items[i];
for (i = 0; i < self->list.length; i++) {
AxTodoTask task = (AxTodoTask) self->list.items[i];
if (uuid_compare(task->list_id, self->list_id) != 0)
continue;
if (task->is_done) {
fwrite("x ", 1, 2, f);
}
if (task->priority) {
if (task->priority && task->priority != AX_TODO_ZERO_PRIORITY) {
fprintf(f, "(%c) ", task->priority);
}
if (task->is_done) {
if (task->completion) {
ax_todo__write_dt(f, task->completion);
if (task->creation) {
ax_todo__write_dt(f, task->creation);
if (task->completed) {
ax_todo__write_dt(f, task->completed);
if (task->created) {
ax_todo__write_dt(f, task->created);
}
}
} else if (task->creation) {
ax_todo__write_dt(f, task->creation);
} else if (task->created) {
ax_todo__write_dt(f, task->created);
}
fprintf(f, "%s\n", task->description);
}
return (fflush(f) == 0) ? AISL_SUCCESS : AISL_SYSCALL_ERROR;
fclose(f);
if (cstuff_file_move(self->swap, self->file) != 0)
return AISL_SYSCALL_ERROR;
return AISL_SUCCESS;
}
AxTodoTask
ax_todo_task_new(void)
ax_todo_task_new(uuid_t list_id)
{
AxTodoTask result;
if ((result = calloc(1, sizeof (struct ax_todo_task))) != NULL) {
if ((result = calloc(1, sizeof (*result))) != NULL) {
uuid_copy(result->list_id, list_id);
uuid_generate(result->task_id);
result->priority = AX_TODO_ZERO_PRIORITY;
}
return result;
@@ -220,7 +322,7 @@ ax_todo__get_priority(char *buf, char *p_priority)
}
static int
int
ax_todo__get_dt(char *buf, time_t *p_dt)
{
struct tm stm = {0};
@@ -228,6 +330,8 @@ ax_todo__get_dt(char *buf, time_t *p_dt)
const char fmt[] = "Y-M-DTH:m:s.uZB:b ", *f = fmt;
char *ptr = NULL;
setenv("TZ", "UTC", 1);
for (result = 0; *f != 0; result++, f++) {
switch(*f) {
case 'Y':
@@ -329,7 +433,6 @@ ax_todo__get_dt(char *buf, time_t *p_dt)
stm.tm_min += (b_min * z_bias);
}
setenv("TZ", "UTC", 1);
*p_dt = mktime(&stm);
unsetenv("TZ");
@@ -337,12 +440,33 @@ ax_todo__get_dt(char *buf, time_t *p_dt)
}
e_input:
AX_LOG_DEBUG("Parse error: %c(%d) at %d", *f, (int) (f - fmt), result);
/* AX_LOG_DEBUG("Parse error: %c(%d) at %d", *f, (int) (f - fmt), result); */
return 0;
(void) usec;
}
void
ax_todo__remove_line_break(char *description)
{
int move = 0;
char c;
do {
c = *description;
if (c == '\r' || c == '\n') {
move++;
continue;
}
*(description - move) = c;
} while (c != '\0');
}
AislStatus
ax_todo_task_set(AxTodoTask task, char *buf, ssize_t length)
{
@@ -362,11 +486,11 @@ ax_todo_task_set(AxTodoTask task, char *buf, ssize_t length)
buf += l;
}
l = ax_todo__get_dt(buf, (is_done) ? &task->completion : &task->creation);
l = ax_todo__get_dt(buf, (is_done) ? &task->completed : &task->created);
if (l != 0) {
buf += l;
if (is_done && (l = ax_todo__get_dt(buf, &task->creation)) != 0) {
if (is_done && (l = ax_todo__get_dt(buf, &task->created)) != 0) {
buf += l;
}
}
@@ -381,3 +505,20 @@ ax_todo_task_set(AxTodoTask task, char *buf, ssize_t length)
return AISL_SUCCESS;
}
void
ax_todo_project_free(AxTodoProject project)
{
if (project->name)
free(project->name);
free(project);
}
void
ax_todo_tag_free(AxTodoTag tag)
{
if (tag->name)
free(tag->name);
free(tag);
}
+47 -10
View File
@@ -22,28 +22,49 @@
#include <aisl/aisl.h>
#include <cStuff/list.h>
#define AX_TODO_ZERO_PRIORITY '_'
struct ax_todo {
uuid_t id;
FILE *fd;
struct cstuff_list list;
uuid_t list_id;
const char *file;
char *swap;
/* todo: add file timestamp */
};
typedef struct ax_todo * AxTodo;
struct ax_todo_task {
uuid_t list_id;
uuid_t task_id;
char priority;
time_t completion;
time_t creation;
time_t completed;
time_t created;
char *description;
bool is_done;
bool is_done;
char priority;
};
typedef struct ax_todo_task * AxTodoTask;
struct ax_todo_project {
uuid_t project_id;
time_t last_completed;
char *name;
uint32_t ref_count;
};
typedef struct ax_todo_project * AxTodoProject;
struct ax_todo_tag {
uuid_t tag_id;
char *name;
uint32_t ref_count;
};
typedef struct ax_todo_tag * AxTodoTag;
AislStatus
ax_todo_init(AxTodo self, const char *file);
@@ -53,15 +74,15 @@ ax_todo_release(AxTodo self);
AislStatus
ax_todo_read(AxTodo self);
ax_todo_read(AxTodo self, CStuffList tasks, CStuffList projs, CStuffList tags);
AislStatus
ax_todo_write(AxTodo self);
ax_todo_write(AxTodo self, CStuffList list);
AxTodoTask
ax_todo_task_new(void);
ax_todo_task_new(uuid_t list_id);
void
@@ -72,8 +93,24 @@ void
ax_todo_task_free(AxTodoTask task);
int
ax_todo__get_dt(char *buf, time_t *p_dt);
void
ax_todo__remove_line_break(char *description);
AislStatus
ax_todo_task_set(AxTodoTask task, char *buf, ssize_t length);
void
ax_todo_project_free(AxTodoProject project);
void
ax_todo_tag_free(AxTodoTag tag);
#endif /* !TODO_H */