From 6f845a7185c98a069cbfd30759ad928cf4ffe3ea Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sun, 22 Sep 2024 15:39:35 +0900 Subject: [PATCH] Add helper to create string parts and combine them --- src/helpers.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/helpers.h | 21 +++++++++++++ src/test.c | 18 ++++++++++- 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/src/helpers.c b/src/helpers.c index c8e49d2..df77357 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -18,6 +18,93 @@ // Standard library includes. #include +#include +#include + +int c_simple_http_internal_get_string_part_full_size(void *data, void *ud) { + C_SIMPLE_HTTP_String_Part *part = data; + size_t *count = ud; + + *count += part->size - 1; + + return 0; +} + +int c_simple_http_internal_combine_string_parts_from_list(void *data, void *ud) { + C_SIMPLE_HTTP_String_Part *part = data; + void **ptrs = ud; + char *buf = ptrs[0]; + size_t *current_count = ptrs[1]; + const size_t *total_count = ptrs[2]; + + if (*current_count + part->size - 1 > *total_count) { + fprintf(stderr, "ERROR Invalid state combining string parts!\n"); + return 1; + } + + memcpy(buf + *current_count, part->buf, part->size - 1); + + *current_count += part->size - 1; + + return 0; +} + +void c_simple_http_cleanup_string_part(void *data) { + C_SIMPLE_HTTP_String_Part *part = data; + if (part) { + if (part->buf) { + free(part->buf); + part->buf = NULL; + } + free(part); + } +} + +void c_simple_http_add_string_part( + SDArchiverLinkedList *list, const char *c_string, size_t extra) { + C_SIMPLE_HTTP_String_Part *string_part = + malloc(sizeof(C_SIMPLE_HTTP_String_Part)); + + string_part->size = strlen(c_string) + 1; + string_part->buf = malloc(string_part->size); + memcpy(string_part->buf, c_string, string_part->size); + + string_part->extra = extra; + + simple_archiver_list_add( + list, string_part, c_simple_http_cleanup_string_part); +} + +char *c_simple_http_combine_string_parts(const SDArchiverLinkedList *list) { + if (!list || list->count == 0) { + return NULL; + } + + size_t count = 0; + + simple_archiver_list_get( + list, c_simple_http_internal_get_string_part_full_size, &count); + + char *buf = malloc(count + 1); + size_t current_count = 0; + + void **ptrs = malloc(sizeof(void*) * 3); + ptrs[0] = buf; + ptrs[1] = ¤t_count; + ptrs[2] = &count; + + if (simple_archiver_list_get( + list, c_simple_http_internal_combine_string_parts_from_list, ptrs)) { + free(buf); + return NULL; + } + + free(ptrs); + + buf[count] = 0; + + return buf; +} void c_simple_http_helper_to_lowercase_in_place(char *buf, size_t size) { for (size_t idx = 0; idx < size; ++idx) { diff --git a/src/helpers.h b/src/helpers.h index c6743fb..a53a947 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -20,6 +20,27 @@ // Standard library includes. #include +// Third-party includes. +#include + +typedef struct C_SIMPLE_HTTP_String_Part { + char *buf; + size_t size; + size_t extra; +} C_SIMPLE_HTTP_String_Part; + +/// Assumes "data" is a C_SIMPLE_HTTP_String_Part, "data" was malloced, and +/// "data->buf" was malloced. +void c_simple_http_cleanup_string_part(void *data); + +/// Puts a malloced instance of String_Part into the list. +/// The given c_string will be copied into a newly malloced buffer. +void c_simple_http_add_string_part( + SDArchiverLinkedList *list, const char *c_string, size_t extra); + +/// Combines all String_Parts in the list and returns it as a single buffer. +char *c_simple_http_combine_string_parts(const SDArchiverLinkedList *list); + /// Modifies "buf" in-place to change all uppercase to lowercase alpha chars. void c_simple_http_helper_to_lowercase_in_place(char *buf, size_t size); diff --git a/src/test.c b/src/test.c index 241b62e..afcc0c9 100644 --- a/src/test.c +++ b/src/test.c @@ -5,14 +5,15 @@ #include // Local includes. -#include "SimpleArchiver/src/data_structures/linked_list.h" #include "config.h" +#include "helpers.h" #include "http_template.h" #include "http.h" // Third party includes. #include #include +#include static int32_t checks_checked = 0; static int32_t checks_passed = 0; @@ -542,6 +543,21 @@ int main(void) { free(stripped_path_buf); } + // Test helpers. + { + __attribute__((cleanup(simple_archiver_list_free))) + SDArchiverLinkedList *list = simple_archiver_list_init(); + + c_simple_http_add_string_part(list, "one\n", 0); + c_simple_http_add_string_part(list, "two\n", 0); + c_simple_http_add_string_part(list, "three\n", 0); + + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *buf = c_simple_http_combine_string_parts(list); + ASSERT_TRUE(buf); + ASSERT_TRUE(strcmp(buf, "one\ntwo\nthree\n") == 0); + } + RETURN() }