diff options
Diffstat (limited to 'src/types.c')
-rw-r--r-- | src/types.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/src/types.c b/src/types.c new file mode 100644 index 0000000..d9253af --- /dev/null +++ b/src/types.c @@ -0,0 +1,299 @@ +#include <stdlib.h> + +#include "types.h" +#include "util.h" + +recipe * +new_recipe() +{ + recipe * r; + r = (recipe *) malloc(sizeof(recipe)); + if (!r) + die("Couldn't allocate memory for recipe"); + + r->n = 1; + r->i = NULL; + r->in = 0; + r->s = NULL; + r->sn = 0; + r->r = NULL; + r->rn = 0; + r->filename = NULL; + r->path = NULL; + r->title = NULL; + return r; +} + +void +new_subrecipe(recipe * r, recipe * src) +{ + r->r = (recipe **)realloc(r->r, (r->rn + 1) * sizeof(recipe *)); + if (!r->r) + die("Couldn't allocate memory for subricepie"); + + r->r[r->rn] = src; + r->rn++; +} + +void +new_item(recipe * r) +{ + r->i = (item **)realloc(r->i, (r->in + 1) * sizeof(item *)); + if (!r->i) + die("Couldn't allocate memory for item"); + + r->i[r->in] = (item *)malloc(sizeof(item)); + if (!r->i[r->in]) + die("Couldn't allocate memory for item"); + r->i[r->in]->name = NULL; + r->i[r->in]->qty = NULL; + r->in++; +} + +void +free_item(item * i) +{ + if (!i) + return; + if (i->name) + free(i->name); + if (i->qty) + free(i->qty); + free(i); +} + +void +new_step(recipe * r) +{ + r->s = (step **)realloc(r->s, (r->sn + 1) * sizeof(step *)); + if (!r->s) + die("Couldn't allocate memory for step"); + + r->s[r->sn] = (step *)malloc(sizeof(step)); + if (!r->s[r->sn]) + die("Couldn't allocate memory for item"); + r->s[r->sn]->inst = NULL; + r->s[r->sn]->duration = NULL; + r->s[r->sn]->result = NULL; + r->s[r->sn]->type = 0; + r->sn++; +} + +void +free_step(step * s) +{ + if (!s) + return; + if (s->inst) + free(s->inst); + if (s->duration) + free(s->duration); + if (s->result) + free(s->result); + free(s); +} + +void +free_recipe(recipe * r) +{ + if (!r) + return; + + if (r->i) { + for (int i = 0; i < r->in; i++) + free_item(r->i[i]); + free(r->i); + } + + if (r->s) { + for (int i = 0; i < r->sn; i++) + free_step(r->s[i]); + free(r->s); + } + + if (r->r) { + for (int i = 0; i < r->rn; i++) + free_recipe(r->r[i]); + free(r->r); + } + + if (r->filename) + free(r->filename); + if (r->path) + free(r->path); + if (r->title) + free(r->title); + + free(r); +} + +void +pprint_items(recipe * r) +{ + printf("Ingredients for %s:\n", r->title); + for (int i = 0; i < r->in; i++) + printf("%s: %s\n", r->i[i]->name, r->i[i]->qty); + printf("\n"); +} + +void +show(recipe * r) +{ + printf("Filename\t%s\n", r->filename); + printf("Dirname\t\t%s\n", r->path); + printf("Title\t\t%s\n\n", r->title); + + for (int i = 0; i < r->in; i++) + printf("I:%s\t%s\n", r->i[i]->name, r->i[i]->qty); + if (r->sn) { + printf("\nSteps:\n~~~~~~\n\n"); + for (int i = 0; i < r->sn; i++) + printf("%s: %s\n", r->s[i]->type == PREP ? "PREP" : "COOK", r->s[i]->inst); + } +} + +void +tojson(recipe * r) +{ + printf("{\"filename\":\"%s\",", r->filename); + printf("\"dirname\":\"%s\",", r->path); + printf("\"title\":\"%s\",", r->title); + printf("\"n\":\"%d\"", r->n); + if (r->rn) { + printf(",\"subrecipes\":["); + int i = 0; + for (; i < r->rn - 1; i++) { + tojson(r->r[i]); + printf(","); + } + tojson(r->r[i]); + printf("]"); + } + if (r->in) { + printf(",\"ingredients\":{"); + int i = 0; + for (; i < r->in - 1; i++) + printf("\"%s\":\"%s\",", r->i[i]->name, r->i[i]->qty); + printf("\"%s\":\"%s\"}", r->i[i]->name, r->i[i]->qty); + } + if (r->sn) { + printf(",\"steps\":["); + int i = 0; + for (; i < r->sn - 1; i++) + printf("\"%s\",", r->s[i]->inst); + printf("\"%s\"]", r->s[i]->inst); + } + printf("}"); +} + +void +tohtml(recipe * r) +{ + printf("todo\n"); +} + +void +torcp(recipe * r) +{ + printf("# %s/%s\n\n", r->path, r->filename); + printf("@%s\n\n", r->title); + for (int i = 0; i < r->rn; i++) { + printf("!%s/%s\n", r->r[i]->path, r->r[i]->filename); + } + for (int i = 0; i < r->in; i++) + printf("%s = %s\n", r->i[i]->name, r->i[i]->qty); + if (r->sn) { + printf("\n---\n\n"); + for (int i = 0; i < r->sn; i++) { + char c; + if (r->s[i]->type == PREP) + c = '-'; + else if (r->s[i]->type == COOK) + c = '>'; + else + c = '+'; + printf("%c %s\n", c, r->s[i]->inst); + } + } +} + +void +copy_metadata(recipe * dst, recipe * src) +{ + if (!dst || !src) return; + dst->filename = strdup(src->filename); + dst->path = strdup(src->path); + dst->title = strdup(src->title); +} + +void +copy_items(recipe * dst, recipe * src) +{ + if (!dst || !src) return; + for (int i = 0; i < src->in; i++) { + new_item(dst); + dst->i[dst->in - 1]->name = strdup(src->i[i]->name); + dst->i[dst->in - 1]->qty = strdup(src->i[i]->qty); + } +} + +static void +join_subrecipe_items(recipe * dst, recipe * src) +{ + if (!src || !dst) return; + for (int i = 0; i < src->rn; i++) { + join_subrecipe_items(dst, src->r[i]); + for (int j = 0; j < src->r[i]->in; j++) { + new_item(dst); + dst->i[dst->in - 1]->name = strdup(src->r[i]->i[j]->name); + if (src->r[i]->n > 1) { + char tmp[2048] = ""; + sprintf(tmp, "%d X ( %s )", src->r[i]->n, src->r[i]->i[j]->qty); + dst->i[dst->in - 1]->qty = strdup(tmp); + } + else { + dst->i[dst->in - 1]->qty = strdup(src->r[i]->i[j]->qty); + } + } + } +} + +void +merge_items(recipe * dst, recipe * src) +{ + /* Join all items in src's subrecipes to dst */ + join_subrecipe_items(dst, src); + /* Copy src items as well to dst */ + copy_items(dst, src); +} + +static int +item_exists(const char * name, const recipe * r) +{ + for (int i = 0; i < r->in; i++) + if (!strcmp(r->i[i]->name, name)) + return i; + return -1; +} + +void +distinct_sum_items(recipe * dst, recipe * src) +{ + if (!dst || !src) return; + for (int i = 0; i < src->in; i++) { + int n = item_exists(src->i[i]->name, dst); + if (n != -1) { + char tmp[2048] = ""; + strcat(tmp, dst->i[n]->qty); + strcat(tmp, " + "); + strcat(tmp, src->i[i]->qty); + free(dst->i[n]->qty); + dst->i[n]->qty = strdup(tmp); + } + else { + new_item(dst); + dst->i[dst->in - 1]->name = strdup(src->i[i]->name); + dst->i[dst->in - 1]->qty = strdup(src->i[i]->qty); + } + } +} |