From 0d10bc8b4d828dc451037e2a124912376e651293 Mon Sep 17 00:00:00 2001 From: Matteo Bini Date: Fri, 16 Aug 2024 23:55:28 +0200 Subject: [PATCH] Dynamic array type for array-like types --- srohtml.c | 662 +++++++++++++++++++++++++++--------------------------- 1 file changed, 328 insertions(+), 334 deletions(-) diff --git a/srohtml.c b/srohtml.c index 6a1b165..959948e 100644 --- a/srohtml.c +++ b/srohtml.c @@ -17,54 +17,44 @@ #define NOTES_START 8 #define NOTES_MAX_DIGITS 3 +typedef struct { + void *data; + size_t length; + size_t size; + size_t unit_size; +} array; + typedef struct { int indentation; char *name; } closure; -typedef struct { - int index; - int size; - closure *tags; -} closures; - typedef enum { tag_content = 0, tag_attribute = 1 } html_val_type; -typedef struct { - size_t size; - char *str; -} string; - typedef struct { char *desc; char *id; char heading; } index_title; -typedef struct { - int index; - int size; - index_title *titles; -} index; - typedef struct { char *desc; char *href; } note; -typedef struct { - int index; - note *notes; - int size; -} references; - /* function declarations */ -static void add_closure(closures *dst, const char *tag, const int ind); +static void add_closure(closure *tag, const char *name, const int ind); static void add_h_to_index(const char heading, const char *id); static int add_note(const char *href, const char *desc); +static void *array_at(array *a, const size_t i); +static void array_init(array *a, const size_t size, size_t num); +static void *array_pop(array *a); +static void *array_push(array *a); +static char *array_strcat(array *dst, const char *src); +static char *array_strcat_html(array *dst, const char *src, const html_val_type t); static void cmd(char *line); static void cmd_close(void); static void cmd_a(const char *line); @@ -92,60 +82,45 @@ static void footer(void); static void footnotes(void); static int fputs_html(const char *str, FILE *f, const html_val_type t); static size_t fread_line(FILE *file, char **str, size_t *len); -static void free_closures(closures *dst); static void indent_str(char **str, const int ind); static void nav_index(FILE *f); static void page_head(void); -static void pop_closure(closures *dst); +static void pop_closure(array *a); static void print_help(void); static void print_usage(void); static void print_version(void); static void *safe_malloc(const size_t size); static void *safe_realloc(void *ptr, const size_t size); static size_t stread_param(const char *src, char **str); -static char *string_cat(string *dst, const char *src); -static char *string_cat_html(string *dst, const char *src, const html_val_type t); -static void string_enlarge(string *old, const size_t size); -static int string_putc(string *dst, const char c); /* variables */ char *author = NULL; -string body; +array body; char *description = NULL; int figcaption_presence = 0; -string head; +array head; size_t heading_position = 0; int img_presence = 0; int indentation = 2; +array index; char *index_heading = NULL; char *index_heading_id = NULL; size_t index_position = 0; char *language = NULL; int licence_container = 0; -index page_index; char *pub_date = NULL; -references sitography; +array sitography; int space = 0; char tag_closure[CLS_MAX]; char *title = NULL; /* function implementations */ void -add_closure(closures *dst, const char *name, const int ind) +add_closure(closure *tag, const char *name, const int ind) { - closure *tag; - - if (dst->index == dst->size) { - dst->size *= 2; - dst->tags = safe_realloc(dst->tags, sizeof(closure) * dst->size); - } - - tag = dst->tags + dst->index; - tag->indentation = ind; tag->name = safe_malloc(sizeof(char) * (strlen(name) + 1)); strcpy(tag->name, name); - dst->index++; } void @@ -153,19 +128,14 @@ add_h_to_index(const char heading, const char *id) { index_title *new; - if (page_index.index == page_index.size) { - page_index.size *= 2; - page_index.titles = safe_realloc(page_index.titles, sizeof(index_title) * page_index.size); - } - - new = page_index.titles + page_index.index; + new = array_push(&index); new->desc = NULL; new->heading = heading; new->id = safe_malloc(sizeof(char) * (strlen(id) + 1)); strcpy(new->id, id); - heading_position = strlen(body.str); + heading_position = strlen(body.data); } int @@ -173,19 +143,45 @@ add_note(const char *href, const char *desc) { note *new; - if (sitography.index == sitography.size) { - sitography.size *= 2; - sitography.notes = safe_realloc(sitography.notes, sizeof(note) * sitography.size); - } + new = array_push(&sitography); - new = sitography.notes + sitography.index; new->href = safe_malloc(sizeof(char) * (strlen(href) + 1)); strcpy(new->href, href); new->desc = safe_malloc(sizeof(char) * (strlen(desc) + 1)); strcpy(new->desc, desc); - sitography.index++; - return sitography.index; + return sitography.length; +} + +void * +array_at(array *a, const size_t i) +{ + if (i >= a->length) + return NULL; + + return (char *) a->data + i * a->unit_size; +} + +void * +array_pop(array *a) +{ + if (a->length == 0) + return NULL; + + a->length--; + + return (char *) a->data + a->length * a->unit_size; +} + +void * +array_push(array *a) +{ + if (a->length == a->size) { + a->size *= 2; + a->data = safe_realloc(a->data, a->unit_size * a->size); + } + + return (char *) a->data + a->length++ * a->unit_size; } void @@ -271,23 +267,23 @@ cmd_a(const char *line) line += stread_param(line, &title); if (space) - string_cat(&body, " "); - string_cat(&body, ""); - string_cat_html(&body, in, tag_attribute); - string_cat(&body, ""); + array_strcat(&body, ">"); + array_strcat_html(&body, in, tag_attribute); + array_strcat(&body, ""); free(href); free(in); @@ -313,34 +309,34 @@ cmd_au_de_ti(char **str, const char *line) void cmd_br(void) { - string_cat(&body, "
"); + array_strcat(&body, "
"); space = 0; } void cmd_close(void) { + char *bodystr; char *ind, *line; index_title *title; - size_t len; - ind = NULL; - len = 0; - line = NULL; - title = NULL; + bodystr = body.data; + ind = NULL; + line = NULL; + title = NULL; if (!strcmp(tag_closure, "")) { - len = strlen(body.str); - if (len >= FIGCAPTION_TAG_LEN + indentation) - line = body.str + len - FIGCAPTION_TAG_LEN; + if (body.length >= FIGCAPTION_TAG_LEN + indentation) + line = bodystr + body.length - FIGCAPTION_TAG_LEN; if (line != NULL && !strcmp(line, "
")) { *(line - indentation) = '\0'; + body.length = strlen(bodystr); } else { figcaption_presence = 1; - string_cat(&body, "
\n"); + array_strcat(&body, "\n"); } indent_str(&ind, --indentation); - string_cat(&body, ind); + array_strcat(&body, ind); free(ind); } @@ -350,16 +346,19 @@ cmd_close(void) !strcmp(tag_closure, "")) && index_position && heading_position) { - title = page_index.titles + page_index.index; + title = array_at(&index, index.length - 1); + if (title == NULL) { + fprintf(stderr, BIN ": Can't find title at position %i, in index array.\n", index.length - 1); + exit(1); + } - title->desc = safe_malloc(sizeof(char) * (strlen(body.str + heading_position) + 1)); - strcpy(title->desc, body.str + heading_position); - page_index.index++; + title->desc = safe_malloc(sizeof(char) * (strlen(bodystr + heading_position) + 1)); + strcpy(title->desc, bodystr + heading_position); heading_position = 0; } - string_cat(&body, tag_closure); - string_cat(&body, "\n"); + array_strcat(&body, tag_closure); + array_strcat(&body, "\n"); strcpy(tag_closure, ""); space = 0; @@ -380,15 +379,15 @@ cmd_dt(const char *line) line += stread_param(line, &in); if (space) - string_cat(&body, " "); - string_cat(&body, ""); free(datetime); free(in); @@ -404,10 +403,10 @@ cmd_em(const char *line) line++; if (space) - string_cat(&body, " "); - string_cat(&body, ""); - string_cat(&body, line); - string_cat(&body, ""); + array_strcat(&body, " "); + array_strcat(&body, ""); + array_strcat(&body, line); + array_strcat(&body, ""); } void @@ -425,17 +424,17 @@ cmd_fi(const char *line) indent_str(&ind, indentation); - string_cat(&body, ind); - string_cat(&body, "
\n"); + array_strcat(&body, ind); + array_strcat(&body, "
\n"); indent_str(&ind, ++indentation); - string_cat(&body, ind); - string_cat(&body, "\"\"\n"); + array_strcat(&body, ind); + array_strcat(&body, "\"\"\n"); img_presence = 1; - string_cat(&body, ind); - string_cat(&body, "
"); + array_strcat(&body, ind); + array_strcat(&body, "
"); strcpy(tag_closure, "
"); @@ -447,19 +446,22 @@ void cmd_h(const char *line) { const char *id; + char h[2]; + h[0] = line[1]; + h[1] = '\0'; id = NULL; - string_cat(&body, "\t\t 4 && line[2] == ' ' && line[3] != '\0') { id = line + 3; - string_cat(&body, " id=\""); - string_cat_html(&body, id, tag_attribute); - string_cat(&body, "\""); + array_strcat(&body, " id=\""); + array_strcat_html(&body, id, tag_attribute); + array_strcat(&body, "\""); } - string_cat(&body, ">"); + array_strcat(&body, ">"); strcpy(tag_closure, ""); + array_strcat(&body, "\t\t
"); } void @@ -486,10 +488,10 @@ cmd_i(const char *line) line++; if (space) - string_cat(&body, " "); - string_cat(&body, ""); - string_cat(&body, line); - string_cat(&body, ""); + array_strcat(&body, " "); + array_strcat(&body, ""); + array_strcat(&body, line); + array_strcat(&body, ""); space = 1; } @@ -512,7 +514,7 @@ cmd_in(const char *line) index_heading_id = NULL; } - index_position = strlen(body.str); + index_position = body.length; } void @@ -544,8 +546,8 @@ cmd_le(void) indentation--; indent_str(&ind, indentation); - string_cat(&body, ind); - string_cat(&body, "\n"); + array_strcat(&body, ind); + array_strcat(&body, "\n"); free(ind); } @@ -559,15 +561,15 @@ cmd_ls(void) licence_container = 1; indent_str(&ind, indentation); - string_cat(&body, ind); - string_cat(&body, "
\n"); + array_strcat(&body, ind); + array_strcat(&body, "
\n"); indentation++; free(ind); ind = NULL; indent_str(&ind, indentation); - string_cat(&body, ind); - string_cat(&body, "
\n"); + array_strcat(&body, ind); + array_strcat(&body, "
\n"); free(ind); } @@ -590,21 +592,21 @@ cmd_no(const char *line) line += stread_param(line, &title); if (space) - string_cat(&body, " "); + array_strcat(&body, " "); sprintf(index, "%u", add_note(href, desc)); - string_cat(&body, "["); - string_cat(&body, index); - string_cat(&body, "]"); + array_strcat(&body, ">["); + array_strcat(&body, index); + array_strcat(&body, "]"); free(desc); free(href); @@ -620,8 +622,8 @@ cmd_p(void) indent_str(&ind, indentation); - string_cat(&body, ind); - string_cat(&body, "

"); + array_strcat(&body, ind); + array_strcat(&body, "

"); strcpy(tag_closure, "

"); free(ind); @@ -660,14 +662,14 @@ cmd_q(const char *line) line += stread_param(line, &cite); if (space) - string_cat(&body, " "); - string_cat(&body, ""); + array_strcat(&body, ">"); space = 0; strcpy(tag_closure, "

"); @@ -678,9 +680,9 @@ cmd_q(const char *line) void cmd_st(const char *line) { - size_t len; + char *bodystr; - len = strlen(body.str); + bodystr = body.data; /* move past "ST" */ line += 2; @@ -688,11 +690,11 @@ cmd_st(const char *line) if (line[0] == ' ') line++; - if (space && len > 0 && body.str[len - 1] != '\'') - string_cat(&body, " "); - string_cat(&body, ""); - string_cat(&body, line); - string_cat(&body, ""); + if (space && body.length > 0 && bodystr[body.length - 1] != '\'') + array_strcat(&body, " "); + array_strcat(&body, ""); + array_strcat(&body, line); + array_strcat(&body, ""); } void @@ -708,16 +710,16 @@ cmd_tm(const char *line) line += stread_param(line, &in); if (space) - string_cat(&body, " "); - string_cat(&body, ""); + array_strcat(&body, "\">"); + array_strcat_html(&body, in, tag_content); + array_strcat(&body, ""); free(date); free(hours); @@ -734,12 +736,12 @@ cmd_ur(const char *line) line++; if (space) - string_cat(&body, " "); - string_cat(&body, "<"); - string_cat_html(&body, line, tag_content); - string_cat(&body, ">"); + array_strcat(&body, " "); + array_strcat(&body, "<"); + array_strcat_html(&body, line, tag_content); + array_strcat(&body, ">"); } void @@ -766,20 +768,20 @@ footer(void) max = 16; - string_cat(&body, "\t\t
\n"); + array_strcat(&body, "\t\t
\n"); if (pub_date != NULL) { - string_cat(&body, "\t\t\t

Pubblicazione:

Pubblicazione:

\n"); + array_strcat(&body, str); + array_strcat(&body, "

\n"); free(pub_date); } @@ -787,26 +789,26 @@ footer(void) s = time(NULL); now = localtime(&s); - string_cat(&body, "\t\t\t

Revisione:

\n"); + array_strcat_html(&body, str, tag_content); + array_strcat(&body, "

\n"); - string_cat(&body, "\t\t
\n"); + array_strcat(&body, "\t\t
\n"); } void @@ -818,46 +820,47 @@ footnotes(void) char id[NOTES_MAX_DIGITS + 1]; char pad[6 * (NOTES_MAX_DIGITS - 1) + 1]; - if (sitography.index == 0) + if (sitography.length == 0) return; - string_cat(&body, "\t\t
\n"); - string_cat(&body, "\t\t
\n"); - string_cat(&body, "\t\t\t

Sitografia

\n"); + array_strcat(&body, "\t\t
\n"); + array_strcat(&body, "\t\t
\n"); + array_strcat(&body, "\t\t\t

Sitografia

\n"); - sprintf(id, "%u", sitography.index); + cur = sitography.data; + sprintf(id, "%u", sitography.length); dig_num = strlen(id); - for (i = 0; i < sitography.index; i++) { - cur = sitography.notes + i; + for (i = 0; i < sitography.length; i++) { sprintf(id, "%u", i + 1); - string_cat(&body, "\t\t\t

"); + array_strcat(&body, "\t\t\t

"); strcpy(pad, ""); for (x = strlen(id); x < dig_num; x++) strcat(pad, " "); - string_cat(&body, pad); - string_cat(&body, ""); - string_cat(&body, id); - string_cat(&body, " "); + array_strcat(&body, pad); + array_strcat(&body, ""); + array_strcat(&body, id); + array_strcat(&body, " "); if (strcmp(cur->desc, "")) { - string_cat_html(&body, cur->desc, tag_content); - string_cat(&body, " "); + array_strcat_html(&body, cur->desc, tag_content); + array_strcat(&body, " "); } - string_cat(&body, "<href); - string_cat(&body, "\">"); - string_cat_html(&body, cur->href, tag_content); - string_cat(&body, ">

\n"); + array_strcat(&body, "<href); + array_strcat(&body, "\">"); + array_strcat_html(&body, cur->href, tag_content); + array_strcat(&body, ">

\n"); free(cur->desc); free(cur->href); + cur++; } - free(sitography.notes); + free(sitography.data); - string_cat(&body, "\t\t
\n"); + array_strcat(&body, "\t\t
\n"); } int @@ -914,15 +917,6 @@ fread_line(FILE *file, char **str, size_t *len) return c == EOF ? EOF : i; } -void -free_closures(closures *dst) -{ - int i; - - for (i = 0; i < dst->index; i++) - free(dst->tags[i].name); -} - void indent_str(char **str, const int ind) { @@ -938,6 +932,17 @@ indent_str(char **str, const int ind) (*str)[ind] = '\0'; } +void +array_init(array *a, const size_t size, size_t num) +{ + num = num == 0 ? 1 : num; + + a->data = safe_malloc(size * num); + a->length = 0; + a->size = num; + a->unit_size = size; +} + int main (int argc, char *argv[]) { @@ -968,23 +973,12 @@ main (int argc, char *argv[]) return 1; } - head.size = BODY_START_SIZE / 4; - head.str = safe_malloc(sizeof(char) * head.size); - strcpy(head.str, ""); + array_init(&head, sizeof(char), BODY_START_SIZE / 4); + array_init(&body, sizeof(char), BODY_START_SIZE); + array_init(&index, sizeof(index_title), INDEX_START); + array_init(&sitography, sizeof(note), NOTES_START); - body.size = BODY_START_SIZE; - body.str = safe_malloc(sizeof(char) * body.size); - strcpy(body.str, ""); - - page_index.index = 0; - page_index.size = INDEX_START; - page_index.titles = safe_malloc(sizeof(index_title) * page_index.size); - - sitography.index = 0; - sitography.size = NOTES_START; - sitography.notes = malloc(sizeof(note) * sitography.size); - - string_cat(&body, "\t\n"); + array_strcat(&body, "\t\n"); len = 0; line = NULL; @@ -1004,8 +998,8 @@ main (int argc, char *argv[]) line[0] != '.' && line[0] != ';' && line[0] != '?') - string_cat(&body, " "); - string_cat_html(&body, line, tag_content); + array_strcat(&body, " "); + array_strcat_html(&body, line, tag_content); space = 1; } free(line); @@ -1023,7 +1017,7 @@ main (int argc, char *argv[]) footnotes(); footer(); - string_cat(&body, "\t\n\n"); + array_strcat(&body, "\t\n\n"); if (argc == 3) out = fopen(argv[2], "w"); @@ -1034,21 +1028,28 @@ main (int argc, char *argv[]) return 1; } - fputs(head.str, out); + fputs(head.data, out); { + char *bodystr; char c; - c = body.str[index_position]; - body.str[index_position] = '\0'; - fputs(body.str, out); + + bodystr = body.data; + c = bodystr[index_position]; + + bodystr[index_position] = '\0'; + fputs(bodystr, out); if (index_position) nav_index(out); - body.str[index_position] = c; - fputs(body.str + index_position, out); + bodystr[index_position] = c; + fputs(bodystr + index_position, out); } fclose(out); + free(head.data); + free(body.data); + return 0; } @@ -1058,13 +1059,11 @@ nav_index(FILE *f) int i, n; int ind; closure *tag; - closures nav_cls; + array nav_cls; index_title *next_title, *title; ind = 2; - nav_cls.index = 0; - nav_cls.size = 4; - nav_cls.tags = safe_malloc(sizeof(closure) * nav_cls.size); + array_init(&nav_cls, sizeof(closure), 4); tag = NULL; findent(ind++, f); @@ -1085,14 +1084,14 @@ nav_index(FILE *f) fputs("\n", f); free(index_heading); } - for (i = 0; i < page_index.index; i++) { - title = page_index.titles + i; - next_title = i == page_index.index - 1 ? NULL : title + 1; + title = index.data; + for (i = 0; i < index.length; i++) { + next_title = i == index.length - 1 ? NULL : title + 1; if (i == 0) { findent(ind, f); fputs("
    \n", f); - add_closure(&nav_cls, "ul", ind); + add_closure(array_push(&nav_cls), "ul", ind); ind++; } @@ -1100,16 +1099,20 @@ nav_index(FILE *f) fputs("
  • id, f, tag_attribute); fprintf(f, "\">%s", title->desc); - add_closure(&nav_cls, "li", ind); + add_closure(array_push(&nav_cls), "li", ind); - if (i == page_index.index - 1) { + if (i == index.length - 1) { fputs("
  • \n", f); ind--; pop_closure(&nav_cls); - for (n = nav_cls.index - 1; n >= 0; n--) { - tag = nav_cls.tags + n; + n = nav_cls.length - 1; + for (n = nav_cls.length - 1; n < nav_cls.length; n--) { + tag = (closure *) nav_cls.data + n; findent(tag->indentation, f); fprintf(f, "\n", tag->name); + free(tag->name); + if (n == 0) + break; } findent(tag->indentation, f); fputs("
    \n", f); @@ -1127,7 +1130,7 @@ nav_index(FILE *f) fputs("\n", f); findent(++ind, f); fputs("
      \n", f); - add_closure(&nav_cls, "ul", ind); + add_closure(array_push(&nav_cls), "ul", ind); ind++; } else if ((title + 1)->heading == title->heading) { fputs("\n", f); @@ -1136,55 +1139,55 @@ nav_index(FILE *f) free(title->desc); free(title->id); + title++; } findent(--tag->indentation, f); fputs("\n", f); - free_closures(&nav_cls); - free(nav_cls.tags); - free(page_index.titles); + free(nav_cls.data); + free(index.data); } void page_head(void) { - string_cat(&head, "\n"); + array_strcat(&head, "\n"); - string_cat(&head, "\n"); + array_strcat(&head, ">\n"); - string_cat(&head, "\t\n"); + array_strcat(&head, "\t\n"); - string_cat(&head, "\t\t\n"); + array_strcat(&head, "\t\t\n"); - string_cat(&head, "\t\t\n"); + array_strcat(&head, "\t\t\n"); if (author != NULL) { - string_cat(&head, "\t\t\n"); + array_strcat(&head, "\t\t\n"); free(author); } if (description != NULL) { - string_cat(&head, "\t\t\n"); + array_strcat(&head, "\t\t\n"); free(description); } - string_cat(&head, "\t\t\n"); + array_strcat(&head, "\t\t\n"); - string_cat(&head, "\t\t\n"); + array_strcat(&head, "\t\t\n"); if (title != NULL) { - string_cat(&head, "\t\t"); - string_cat_html(&head, title, tag_content); - string_cat(&head, "\n"); + array_strcat(&head, "\t\t"); + array_strcat_html(&head, title, tag_content); + array_strcat(&head, "\n"); free(title); } - string_cat(&head, "\t\n"); + array_strcat(&head, "\t\n"); } void @@ -1347,16 +1350,20 @@ print_version(void) } void -pop_closure(closures *dst) +pop_closure(array *a) { closure *tag; - if (dst->index <= 0) + if (a->length <= 0) return; - tag = dst->tags + (dst->index - 1); + tag = array_at(a, a->length - 1); + if (tag == NULL) { + fprintf(stderr, BIN ": Can't find tag closure at position %i, in array type.\n", a->length - 1); + exit(1); + } free(tag->name); - dst->index--; + array_pop(a); } void * @@ -1421,62 +1428,49 @@ stread_param(const char *src, char **str) } char * -string_cat(string *dst, const char *src) +array_strcat(array *dst, const char *src) { - size_t len; + char *c; + size_t i, len; len = strlen(src); - if (len >= (dst->size - strlen(dst->str))) - string_enlarge(dst, (dst->size + len) * 2 + 1); + for (i = 0; i < len; i++) { + c = array_push(dst); + *c = src[i]; + } + c = array_push(dst); + *c = '\0'; + dst->length--; - strcat(dst->str, src); - - return dst->str; + return dst->data; } char * -string_cat_html(string *dst, const char *src, const html_val_type t) +array_strcat_html(array *dst, const char *src, const html_val_type t) { + char *c; size_t i, len; len = strlen(src); for (i = 0; i < len; i++) { if (t == tag_attribute && src[i] == '"') - string_cat(dst, """); + array_strcat(dst, """); else if (src[i] == '&') - string_cat(dst, "&"); + array_strcat(dst, "&"); else if (src[i] == '<') - string_cat(dst, "<"); + array_strcat(dst, "<"); else if (src[i] == '>') - string_cat(dst, ">"); - else - string_putc(dst, src[i]); + array_strcat(dst, ">"); + else { + c = array_push(dst); + *c = src[i]; + } } + c = array_push(dst); + *c = '\0'; + dst->length--; - return dst->str; -} - -void -string_enlarge(string *old, const size_t size) -{ - old->str = safe_realloc(old->str, sizeof(char) * size); - old->size = size; -} - -int -string_putc(string *dst, const char c) -{ - size_t len; - - len = strlen(dst->str); - - if ((dst->size - len) <= 1) - string_enlarge(dst, (dst->size + 1) * 2 + 1); - - dst->str[len] = c; - dst->str[len + 1] = '\0'; - - return (int) c; + return dst->data; }