#include #include #include #include "doc.h" #include "err.h" /* initialization / destruction */ void doc_init(struct doc *d) { buf_init(&d->txt, sizeof(struct doc_line)); buf_init(&d->lnk, 1); d->txt.sz = sizeof(struct doc_line); *(struct doc_line *)d->txt.buf = (struct doc_line) { .prev = 0, .link = DOC_LINK_NONE, .len = 0, }; d->latest = 0; d->linkc = 0; } void doc_fini(struct doc *d) { buf_free(&d->txt); buf_free(&d->lnk); } /* line creation */ void doc_new_line(struct doc *d) { buf_grow(&d->txt, sizeof(struct doc_line)); *(struct doc_line *)&d->txt.buf[d->txt.sz] = (struct doc_line) { .prev = ((struct doc_line *)&d->txt.buf[d->latest])->len, .link = DOC_LINK_NONE, .len = 0 }; d->latest = d->txt.sz; d->txt.sz += sizeof(struct doc_line); } void doc_add_line(struct doc *d, strv_t s) { doc_add_text(d, s); doc_new_line(d); } void doc_add_text(struct doc *d, strv_t s) { buf_grow(&d->txt, s.n); memcpy(&d->txt.buf[d->txt.sz], s.s, s.n); struct doc_line *dl = (struct doc_line *)&d->txt.buf[d->latest]; d->txt.sz += s.n; dl->len += s.n; } unsigned short doc_add_link(struct doc *d, const char *url) { buf_cat(&d->lnk, url, strlen(url) + 1); return d->linkc++; } void doc_set_link(struct doc *d, unsigned short lnk) { struct doc_line *l = doc_line_at(d, d->latest); l->link = lnk; } /* line navigation */ struct doc_line *doc_line_at(struct doc *d, size_t ofs) { return (struct doc_line *)&d->txt.buf[ofs]; } int doc_line_nextp(struct doc *d, size_t ofs) { return ofs + doc_line_at(d, ofs)->len + sizeof(struct doc_line) < d->txt.sz; } int doc_line_prevp(struct doc *d, size_t ofs) { return ofs >= doc_line_at(d, ofs)->prev + sizeof(struct doc_line); } int doc_line_prev(struct doc *d, size_t *ofs) { size_t n = doc_line_at(d, *ofs)->prev + sizeof(struct doc_line); if (*ofs >= n) { *ofs -= n; return 0; } else { return -1; } } int doc_line_next(struct doc *d, size_t *ofs) { size_t n = doc_line_at(d, *ofs)->len + sizeof(struct doc_line); if (*ofs + n < d->txt.sz) { *ofs += n; return 0; } else { return -1; } } const char *doc_get_link(struct doc *d, unsigned short lnk) { size_t l = 1; for (size_t i = 0; i < d->lnk.sz; i++) { if (l == lnk) return &d->lnk.buf[i]; if (d->lnk.buf[i] == 0) l++; } return NULL; }