Refactor http_template to use String_Part
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 9s

This commit is contained in:
Stephen Seo 2024-09-23 14:09:25 +09:00
parent f8b2f63554
commit 0956ae165e
3 changed files with 77 additions and 129 deletions

View file

@ -30,13 +30,19 @@ int c_simple_http_internal_get_string_part_full_size(void *data, void *ud) {
return 0; return 0;
} }
int c_simple_http_internal_combine_string_parts_from_list(void *data, void *ud) { int c_simple_http_internal_combine_string_parts_from_list(void *data,
void *ud) {
C_SIMPLE_HTTP_String_Part *part = data; C_SIMPLE_HTTP_String_Part *part = data;
void **ptrs = ud; void **ptrs = ud;
char *buf = ptrs[0]; char *buf = ptrs[0];
size_t *current_count = ptrs[1]; size_t *current_count = ptrs[1];
const size_t *total_count = ptrs[2]; const size_t *total_count = ptrs[2];
if (!part->buf || part->size == 0) {
// Empty string part, just continue.
return 0;
}
if (*current_count + part->size - 1 > *total_count) { if (*current_count + part->size - 1 > *total_count) {
fprintf(stderr, "ERROR Invalid state combining string parts!\n"); fprintf(stderr, "ERROR Invalid state combining string parts!\n");
return 1; return 1;
@ -49,12 +55,21 @@ int c_simple_http_internal_combine_string_parts_from_list(void *data, void *ud)
return 0; return 0;
} }
void c_simple_http_cleanup_attr_string_part(C_SIMPLE_HTTP_String_Part **part) {
if (part && *part) {
if ((*part)->buf) {
free((*part)->buf);
}
free(*part);
}
*part = NULL;
}
void c_simple_http_cleanup_string_part(void *data) { void c_simple_http_cleanup_string_part(void *data) {
C_SIMPLE_HTTP_String_Part *part = data; C_SIMPLE_HTTP_String_Part *part = data;
if (part) { if (part) {
if (part->buf) { if (part->buf) {
free(part->buf); free(part->buf);
part->buf = NULL;
} }
free(part); free(part);
} }

View file

@ -29,6 +29,8 @@ typedef struct C_SIMPLE_HTTP_String_Part {
size_t extra; size_t extra;
} C_SIMPLE_HTTP_String_Part; } C_SIMPLE_HTTP_String_Part;
void c_simple_http_cleanup_attr_string_part(C_SIMPLE_HTTP_String_Part **);
/// Assumes "data" is a C_SIMPLE_HTTP_String_Part, "data" was malloced, and /// Assumes "data" is a C_SIMPLE_HTTP_String_Part, "data" was malloced, and
/// "data->buf" was malloced. /// "data->buf" was malloced.
void c_simple_http_cleanup_string_part(void *data); void c_simple_http_cleanup_string_part(void *data);

View file

@ -25,53 +25,8 @@
#include <SimpleArchiver/src/data_structures/linked_list.h> #include <SimpleArchiver/src/data_structures/linked_list.h>
#include <SimpleArchiver/src/helpers.h> #include <SimpleArchiver/src/helpers.h>
typedef struct C_SIMPLE_HTTP_INTERNAL_Template_Node { // Local includes.
char *html; #include "helpers.h"
size_t html_size;
union {
size_t orig_end_idx;
size_t html_capacity;
};
} C_SIMPLE_HTTP_INTERNAL_Template_Node;
void c_simple_http_internal_free_template_node(void *data) {
C_SIMPLE_HTTP_INTERNAL_Template_Node *node = data;
if (node) {
if (node->html) {
free(node->html);
}
free(node);
}
}
void c_simple_http_internal_cleanup_template_node(
C_SIMPLE_HTTP_INTERNAL_Template_Node **node) {
if (node && *node) {
c_simple_http_internal_free_template_node(*node);
*node = NULL;
}
}
int c_simple_http_internal_get_final_size_fn(void *data, void *ud) {
size_t *final_size = ud;
C_SIMPLE_HTTP_INTERNAL_Template_Node *node = data;
*final_size += node->html_size;
return 0;
}
int c_simple_http_internal_fill_buf_fn(void *data, void *ud) {
C_SIMPLE_HTTP_INTERNAL_Template_Node *node = data;
C_SIMPLE_HTTP_INTERNAL_Template_Node *to_fill = ud;
if (to_fill->html_capacity < to_fill->html_size + node->html_size) {
return 1;
}
memcpy(
to_fill->html + to_fill->html_size,
node->html,
node->html_size);
to_fill->html_size += node->html_size;
return 0;
}
/// Returns 0 if "c_string" ends with "_FILE". /// Returns 0 if "c_string" ends with "_FILE".
int c_simple_http_internal_ends_with_FILE(const char *c_string) { int c_simple_http_internal_ends_with_FILE(const char *c_string) {
@ -162,13 +117,12 @@ char *c_simple_http_path_to_generated(
// At this point, html_buf contains the raw HTML as a C-string. // At this point, html_buf contains the raw HTML as a C-string.
__attribute__((cleanup(simple_archiver_list_free))) __attribute__((cleanup(simple_archiver_list_free)))
SDArchiverLinkedList *template_html_list = simple_archiver_list_init(); SDArchiverLinkedList *string_part_list = simple_archiver_list_init();
size_t idx = 0; size_t idx = 0;
size_t last_template_idx = 0; size_t last_template_idx = 0;
__attribute__((cleanup(c_simple_http_internal_cleanup_template_node))) C_SIMPLE_HTTP_String_Part string_part;
C_SIMPLE_HTTP_INTERNAL_Template_Node *template_node = NULL;
size_t delimeter_count = 0; size_t delimeter_count = 0;
@ -184,22 +138,23 @@ char *c_simple_http_path_to_generated(
if (delimeter_count >= 3) { if (delimeter_count >= 3) {
delimeter_count = 0; delimeter_count = 0;
state |= 1; state |= 1;
if (template_html_list->count != 0) { if (string_part_list->count != 0) {
C_SIMPLE_HTTP_INTERNAL_Template_Node *last_node = C_SIMPLE_HTTP_String_Part *last_part =
template_html_list->tail->prev->data; string_part_list->tail->prev->data;
last_template_idx = last_node->orig_end_idx; last_template_idx = last_part->extra;
} }
template_node = malloc(sizeof(C_SIMPLE_HTTP_INTERNAL_Template_Node)); string_part.size = idx - last_template_idx - 1;
template_node->html_size = idx - last_template_idx - 2; string_part.buf = malloc(string_part.size);
template_node->html = malloc(template_node->html_size);
memcpy( memcpy(
template_node->html, string_part.buf,
html_buf + last_template_idx, html_buf + last_template_idx,
template_node->html_size); string_part.size);
template_node->orig_end_idx = idx + 1; string_part.buf[string_part.size - 1] = 0;
simple_archiver_list_add(template_html_list, template_node, string_part.extra = idx + 1;
c_simple_http_internal_free_template_node); c_simple_http_add_string_part(string_part_list,
template_node = NULL; string_part.buf,
string_part.extra);
free(string_part.buf);
} }
} else { } else {
delimeter_count = 0; delimeter_count = 0;
@ -212,14 +167,14 @@ char *c_simple_http_path_to_generated(
if (delimeter_count >= 3) { if (delimeter_count >= 3) {
delimeter_count = 0; delimeter_count = 0;
state &= 0xFFFFFFFE; state &= 0xFFFFFFFE;
C_SIMPLE_HTTP_INTERNAL_Template_Node *last_node = C_SIMPLE_HTTP_String_Part *last_part =
template_html_list->tail->prev->data; string_part_list->tail->prev->data;
size_t var_size = idx - 2 - last_node->orig_end_idx; size_t var_size = idx - 2 - last_part->extra;
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
char *var = malloc(var_size + 1); char *var = malloc(var_size + 1);
memcpy( memcpy(
var, var,
html_buf + last_node->orig_end_idx, html_buf + last_part->extra,
var_size); var_size);
var[var_size] = 0; var[var_size] = 0;
const char *value_c_str = const char *value_c_str =
@ -252,14 +207,12 @@ char *c_simple_http_path_to_generated(
value_c_str); value_c_str);
return NULL; return NULL;
} }
template_node = string_part.size = (size_t)file_size + 1;
malloc(sizeof(C_SIMPLE_HTTP_INTERNAL_Template_Node)); string_part.buf = malloc(string_part.size);
template_node->html_size = (size_t)file_size; string_part.extra = idx + 1;
template_node->html = malloc(template_node->html_size);
template_node->orig_end_idx = idx + 1;
if (fread(template_node->html, if (fread(string_part.buf,
template_node->html_size, string_part.size - 1,
1, 1,
f) f)
!= 1) { != 1) {
@ -267,6 +220,7 @@ char *c_simple_http_path_to_generated(
value_c_str); value_c_str);
return NULL; return NULL;
} }
string_part.buf[string_part.size - 1] = 0;
if (files_list_out) { if (files_list_out) {
char *variable_filename = malloc(strlen(value_c_str) + 1); char *variable_filename = malloc(strlen(value_c_str) + 1);
strcpy(variable_filename, value_c_str); strcpy(variable_filename, value_c_str);
@ -275,24 +229,21 @@ char *c_simple_http_path_to_generated(
} }
} else { } else {
// Variable data is "value_c_str". // Variable data is "value_c_str".
template_node = string_part.size = strlen(value_c_str) + 1;
malloc(sizeof(C_SIMPLE_HTTP_INTERNAL_Template_Node)); string_part.buf = malloc(string_part.size);
size_t size = strlen(value_c_str); memcpy(string_part.buf, value_c_str, string_part.size);
template_node->html = malloc(size); string_part.buf[string_part.size - 1] = 0;
memcpy(template_node->html, value_c_str, size); string_part.extra = idx + 1;
template_node->html_size = size;
template_node->orig_end_idx = idx + 1;
} }
} else { } else {
template_node = string_part.buf = NULL;
malloc(sizeof(C_SIMPLE_HTTP_INTERNAL_Template_Node)); string_part.size = 0;
template_node->html = NULL; string_part.extra = idx + 1;
template_node->html_size = 0;
template_node->orig_end_idx = idx + 1;
} }
simple_archiver_list_add(template_html_list, template_node, c_simple_http_add_string_part(string_part_list,
c_simple_http_internal_free_template_node); string_part.buf,
template_node = NULL; string_part.extra);
free(string_part.buf);
} }
} else { } else {
delimeter_count = 0; delimeter_count = 0;
@ -300,48 +251,28 @@ char *c_simple_http_path_to_generated(
} }
} }
if (template_html_list->count != 0) { if (string_part_list->count != 0) {
C_SIMPLE_HTTP_INTERNAL_Template_Node *last_node = C_SIMPLE_HTTP_String_Part *last_part =
template_html_list->tail->prev->data; string_part_list->tail->prev->data;
if (idx > last_node->orig_end_idx) { if (idx > last_part->extra) {
template_node = malloc(sizeof(C_SIMPLE_HTTP_INTERNAL_Template_Node)); string_part.size = idx - last_part->extra + 1;
size_t size = idx - last_node->orig_end_idx; string_part.buf = malloc(string_part.size);
template_node->html = malloc(size); memcpy(string_part.buf, html_buf + last_part->extra, string_part.size);
memcpy(template_node->html, html_buf + last_node->orig_end_idx, size); string_part.buf[string_part.size - 1] = 0;
template_node->html_size = size; string_part.extra = idx + 1;
template_node->orig_end_idx = idx + 1; c_simple_http_add_string_part(string_part_list,
simple_archiver_list_add(template_html_list, template_node, string_part.buf,
c_simple_http_internal_free_template_node); string_part.extra);
template_node = NULL; free(string_part.buf);
last_node = template_html_list->tail->prev->data; last_part = string_part_list->tail->prev->data;
} }
size_t final_size = 0;
simple_archiver_list_get( char *combined_buf = c_simple_http_combine_string_parts(string_part_list);
template_html_list,
c_simple_http_internal_get_final_size_fn,
&final_size);
if (final_size == 0) {
fprintf(stderr, "ERROR final_size calculated as ZERO from templates!\n");
return NULL;
}
C_SIMPLE_HTTP_INTERNAL_Template_Node to_fill;
to_fill.html = malloc(final_size + 1);
to_fill.html_size = 0;
to_fill.html_capacity = final_size;
if (simple_archiver_list_get(
template_html_list,
c_simple_http_internal_fill_buf_fn,
&to_fill) != NULL) {
fprintf(stderr, "ERROR internal issue processing final html buffer!\n");
free(to_fill.html);
return NULL;
}
to_fill.html[final_size] = 0;
if (output_buf_size) { if (output_buf_size) {
*output_buf_size = final_size; *output_buf_size = strlen(combined_buf);
} }
return to_fill.html; return combined_buf;
} else { } else {
// Prevent cleanup fn from "free"ing html_buf and return it verbatim. // Prevent cleanup fn from "free"ing html_buf and return it verbatim.
char *buf = html_buf; char *buf = html_buf;