From 434993ea34b1832d80d096f24188b61507d79702 Mon Sep 17 00:00:00 2001 From: Randy Jordan Date: Fri, 22 Nov 2024 18:10:58 -0600 Subject: [PATCH] Added packing/unpacking for vstr and vstr arrays --- include/vstr.h | 8 +++- src/vstr.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++- tests/01_vstr.c | 40 ++++++++++++++++- 3 files changed, 159 insertions(+), 4 deletions(-) diff --git a/include/vstr.h b/include/vstr.h index 969ead3..9c68d7e 100644 --- a/include/vstr.h +++ b/include/vstr.h @@ -6,8 +6,8 @@ #include struct Vstr { - char *buf; // String data size_t len; // String len + char *buf; // String data }; typedef struct Vstr Vstr; @@ -16,6 +16,10 @@ typedef struct Vstr Vstr; #define VSTR(cstr) vstr_n(cstr, sizeof(cstr) - 1) #define VSTR_NULL vstr_n(NULL, 0) +size_t pack_vstr(unsigned char *buffer, Vstr *vstr); +void unpack_vstr(unsigned char *buffer, Vstr *vstr); +size_t pack_vstr_array(unsigned char *buffer, Vstr *array, size_t count); +Vstr *unpack_vstr_array(unsigned char *buffer, size_t *count); Vstr vstr_s(const char *s); Vstr vstr_n(const char *s, size_t n); bool vstr_cmp(const Vstr v1, const Vstr v2); @@ -26,4 +30,6 @@ Vstr vstr_substr(Vstr v, size_t start, size_t stop); Vstr vstr_trim(Vstr v); Vstr vstr_trim_left(Vstr v); Vstr vstr_trim_right(Vstr v); + + #endif diff --git a/src/vstr.c b/src/vstr.c index 5c6f403..8d5bde2 100644 --- a/src/vstr.c +++ b/src/vstr.c @@ -1,11 +1,122 @@ #include "../include/vstr.h" #include + +size_t pack_vstr(unsigned char *buffer, Vstr *vstr) { + size_t offset = 0; + + // Pack the length of the string first (size_t) + buffer[offset++] = (vstr->len >> 56) & 0xFF; + buffer[offset++] = (vstr->len >> 48) & 0xFF; + buffer[offset++] = (vstr->len >> 40) & 0xFF; + buffer[offset++] = (vstr->len >> 32) & 0xFF; + buffer[offset++] = (vstr->len >> 24) & 0xFF; + buffer[offset++] = (vstr->len >> 16) & 0xFF; + buffer[offset++] = (vstr->len >> 8) & 0xFF; + buffer[offset++] = vstr->len & 0xFF; + + // Pack the string data + memcpy(&buffer[offset], vstr->buf, vstr->len); + offset += vstr->len; + + return offset; // Return the total packed size +} +void unpack_vstr(unsigned char *buffer, Vstr *vstr) { + unsigned int offset = 0; + + // Unpack the length of the string (size_t) + vstr->len = 0; + for (int i = 0; i < 8; i++) { + vstr->len = (vstr->len << 8) | buffer[offset++]; + } + + // Allocate memory for the string and copy it from the buffer + vstr->buf = (char *)malloc(vstr->len + 1); // +1 for null terminator + if (vstr->buf != NULL) { + memcpy(vstr->buf, &buffer[offset], vstr->len); + vstr->buf[vstr->len] = '\0'; // Null-terminate the string + } else { + vstr->len = 0; // If memory allocation fails, set len to 0 + } +} +size_t pack_vstr_array(unsigned char *buffer, Vstr *array, size_t count) { + size_t offset = 0; + + // Pack the number of elements in the array + buffer[offset++] = (count >> 56) & 0xFF; + buffer[offset++] = (count >> 48) & 0xFF; + buffer[offset++] = (count >> 40) & 0xFF; + buffer[offset++] = (count >> 32) & 0xFF; + buffer[offset++] = (count >> 24) & 0xFF; + buffer[offset++] = (count >> 16) & 0xFF; + buffer[offset++] = (count >> 8) & 0xFF; + buffer[offset++] = count & 0xFF; + + // Pack each Vstr in the array + for (size_t i = 0; i < count; i++) { + // Pack the length of the string + buffer[offset++] = (array[i].len >> 56) & 0xFF; + buffer[offset++] = (array[i].len >> 48) & 0xFF; + buffer[offset++] = (array[i].len >> 40) & 0xFF; + buffer[offset++] = (array[i].len >> 32) & 0xFF; + buffer[offset++] = (array[i].len >> 24) & 0xFF; + buffer[offset++] = (array[i].len >> 16) & 0xFF; + buffer[offset++] = (array[i].len >> 8) & 0xFF; + buffer[offset++] = array[i].len & 0xFF; + + // Pack the string data + memcpy(&buffer[offset], array[i].buf, array[i].len); + offset += array[i].len; + } + + return offset; // Return the total packed size +} +Vstr *unpack_vstr_array(unsigned char *buffer, size_t *count) { + size_t offset = 0; + + // Unpack the number of elements in the array + *count = 0; + for (int i = 0; i < 8; i++) { + *count = (*count << 8) | buffer[offset++]; + } + + // Allocate memory for the Vstr array + Vstr *array = malloc(*count * sizeof(Vstr)); + if (!array) return NULL; // Memory allocation failure + + // Unpack each Vstr in the array + for (size_t i = 0; i < *count; i++) { + // Unpack the length of the string + array[i].len = 0; + for (int j = 0; j < 8; j++) { + array[i].len = (array[i].len << 8) | buffer[offset++]; + } + + // Allocate memory for the string + array[i].buf = malloc(array[i].len + 1); // +1 for null terminator + if (!array[i].buf) { + // Free previously allocated memory in case of failure + for (size_t k = 0; k < i; k++) { + free(array[k].buf); + } + free(array); + return NULL; + } + + // Copy the string data + memcpy(array[i].buf, &buffer[offset], array[i].len); + array[i].buf[array[i].len] = '\0'; // Null-terminate the string + offset += array[i].len; + } + + return array; +} + Vstr vstr_s(const char *s){ - Vstr v = {(char *)s, s == NULL ? 0 : strlen(s)}; + Vstr v = {s == NULL ? 0 : strlen(s), (char *)s}; return v; } Vstr vstr_n(const char *s, size_t n){ - Vstr v = {(char *)s, n}; + Vstr v = {n,(char *)s}; return v; } bool vstr_cmp(const Vstr v1, const Vstr v2){ diff --git a/tests/01_vstr.c b/tests/01_vstr.c index 2bf320e..d2680c8 100644 --- a/tests/01_vstr.c +++ b/tests/01_vstr.c @@ -39,7 +39,45 @@ int main(void){ TEST(vstr_cmp(b,bc) == 0); TEST(vstr_cmp(a,ac) == 0); - + unsigned char buffer[256]; + + size_t packed_size = pack_vstr(buffer, &v); + printf("Packed size: %lu bytes\n", packed_size); + + Vstr unpacked_vstr; + unpack_vstr(buffer, &unpacked_vstr); + printf("Unpacked string: %s\n", unpacked_vstr.buf); + printf("Unpacked length: %zu\n", unpacked_vstr.len); + + free(unpacked_vstr.buf); + + + Vstr array[] = { + {5, "Hello"}, + {7, "World!"}, + {6, "Buffer"} + }; + size_t count = 3; + + unsigned char arr_buffer[1024]; + + size_t arr_packed_size = pack_vstr_array(arr_buffer, array, count); + printf("Packed size: %lu bytes\n", arr_packed_size); + + size_t unpacked_count; + Vstr *unpacked_array = unpack_vstr_array(arr_buffer, &unpacked_count); + if (!unpacked_array) { + printf("Failed to unpack the array.\n"); + return 1; + } + + printf("Unpacked %zu Vstr elements:\n", unpacked_count); + for (size_t i = 0; i < unpacked_count; i++) { + printf(" [%zu]: %s (len=%zu)\n", i, unpacked_array[i].buf, unpacked_array[i].len); + free(unpacked_array[i].buf); // Free the string data + } + + free(unpacked_array); return EXIT_SUCCESS; }