diff options
author | Ali Fardan <raiz@stellarbound.info> | 2020-10-22 13:31:28 +0300 |
---|---|---|
committer | Ali Fardan <raiz@stellarbound.info> | 2020-10-22 13:31:28 +0300 |
commit | de22e0ae21c46fc9eb1cc6717832bfb5fa0600e1 (patch) | |
tree | 1db412a2eb4974aeda045947db284dd806f021b1 /encode.c | |
parent | a77f42d3c2d19dfa13e0f98935de8f9b59502a6a (diff) | |
download | libgemtext-de22e0ae21c46fc9eb1cc6717832bfb5fa0600e1.tar.gz |
- implement the rest of decode.c functions: gemtext_decode_fd() and gemtext_decode_file()
- introduce gemtext_encode() with helper functions gemtext_encode_fd() and gemtext_encode_file() - simplify handling of unordered lists in decode.c - add test.c rule to makefile
Diffstat (limited to 'encode.c')
-rw-r--r-- | encode.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/encode.c b/encode.c new file mode 100644 index 0000000..efe8aaa --- /dev/null +++ b/encode.c @@ -0,0 +1,365 @@ +#include <sys/types.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "gemtext.h" + +static char * +_case_text(struct gemtext *t) +{ + struct gemtext_text *text; + + text = (struct gemtext_text *)t; + + return strdup(text->text); +} + +static char * +_case_link(struct gemtext *t) +{ + struct gemtext_link *link; + char *ret; + int retlen; + + retlen = 0; + link = (struct gemtext_link *)t; + + retlen += strlen(link->link); + if (link->name) + retlen += strlen(link->name); + retlen += 3; /* three characters for "=> " */ + retlen += 1; /* \0 */ + if (link->name) + retlen += 1; /* additional whitespace separator */ + + ret = malloc(retlen+1); + if (ret == NULL) + return NULL; + + strlcpy(ret, "=> ", retlen); + strlcat(ret, link->link, retlen); + if (link->name) { + strlcat(ret, " ", retlen); + strlcat(ret, link->name, retlen); + } + + return ret; +} + +static char * +_case_pre(struct gemtext *t) +{ + struct gemtext_pre *pre; + + pre = (struct gemtext_pre *)t; + + return strdup(pre->text); +} + +static char * +_case_h1(struct gemtext *t) +{ + struct gemtext_h1 *h1; + char *ret; + int retlen; + + retlen = 0; + h1 = (struct gemtext_h1 *)t; + + retlen += strlen(h1->text); + retlen += 2; /* two characters for "# " */ + retlen += 1; /* \0 */ + + ret = malloc(retlen+1); + if (ret == NULL) + return NULL; + + strlcpy(ret, "# ", retlen); + strlcat(ret, h1->text, retlen); + + return ret; +} + +static char * +_case_h2(struct gemtext *t) +{ + struct gemtext_h2 *h2; + char *ret; + int retlen; + + retlen = 0; + h2 = (struct gemtext_h2 *)t; + + retlen += strlen(h2->text); + retlen += 3; /* three characters for "## " */ + retlen += 1; /* \0 */ + + ret = malloc(retlen+1); + if (ret == NULL) + return NULL; + + strlcpy(ret, "## ", retlen); + strlcat(ret, h2->text, retlen); + + return ret; +} + +static char * +_case_h3(struct gemtext *t) +{ + struct gemtext_h3 *h3; + char *ret; + int retlen; + + retlen = 0; + h3 = (struct gemtext_h3 *)t; + + retlen += strlen(h3->text); + retlen += 4; /* four characters for "### " */ + retlen += 1; /* \0 */ + + ret = malloc(retlen+1); + if (ret == NULL) + return NULL; + + strlcpy(ret, "### ", retlen); + strlcat(ret, h3->text, retlen); + + return ret; +} + + +static char * +_case_ul(struct gemtext *t) +{ + struct gemtext_ul *ul; + char *ret; + int retlen; + + retlen = 0; + ul = (struct gemtext_ul *)t; + + retlen += strlen(ul->text); + retlen += 2; /* two characters for "* " */ + retlen += 1; /* \0 */ + + ret = malloc(retlen+1); + if (ret == NULL) + return NULL; + + strlcpy(ret, "* ", retlen); + strlcat(ret, ul->text, retlen); + + return ret; +} + +static char * +_case_qt(struct gemtext *t) +{ + struct gemtext_qt *qt; + char *ret; + int retlen; + + retlen = 0; + qt = (struct gemtext_qt *)t; + + retlen += strlen(qt->text); + retlen += 2; /* two characters for *> " */ + retlen += 1; /* \0 */ + + ret = malloc(retlen+1); + if (ret == NULL) + return NULL; + + strlcpy(ret, "> ", retlen); + strlcat(ret, qt->text, retlen); + + return ret; +} + +static char * +_line_append(char *dst, const char *src, int *len) +{ + int rlen; + char *ret; + + rlen = *len; + rlen += strlen(src); + rlen += 1; /* \n */ + + ret = realloc(dst, rlen+1); + if (ret == NULL) + return NULL; + + strlcat(ret, src, rlen+1); + strlcat(ret, "\n", rlen+1); + + *len = rlen; + return ret; +} + +int +gemtext_encode(struct gemtext **list, char **text, int *len) +{ + int i; + int rtextlen; + char *rtext; + char *retbuf; + + rtextlen = 0; + rtext = NULL; + + for (i = 0; list[i] != NULL; i++) { + switch (list[i]->type) { + case GEMTEXT_TEXT: + retbuf = _case_text(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_LINK: + retbuf = _case_link(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_PRE: + retbuf = _case_pre(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_H1: + retbuf = _case_h1(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_H2: + retbuf = _case_h2(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_H3: + retbuf = _case_h3(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_UL: + retbuf = _case_ul(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + case GEMTEXT_QT: + retbuf = _case_qt(list[i]); + if (retbuf == NULL) { + free(rtext); + return -1; + } + rtext = _line_append(rtext, retbuf, &rtextlen); + free(retbuf); + if (rtext == NULL) { + free(rtext); + return -1; + } + break; + } + } + + *text = rtext; + *len = rtextlen; + + return 0; +} + + +int +gemtext_encode_fd(struct gemtext **list, int fd) +{ + char *text; + int len; + int ecode; + + if (gemtext_encode(list, &text, &len) == -1) + return -1; + + ecode = write(fd, text, len); + if (ecode == -1) + return -1; + + return 0; +} + +int +gemtext_encode_file(struct gemtext **list, const char *path) +{ + int fd; + int ecode; + + fd = open(path, O_WRONLY); + if (fd == -1) + return -1; + + ecode = gemtext_encode_fd(list, fd); + close(fd); + if (ecode == -1) + return -1; + + return 0; +} |