#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);
free(text);
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;
}