From 3b7e2dabc9c00c001d3480a2f20abdba7a7fee68 Mon Sep 17 00:00:00 2001 From: Marco Cetica Date: Thu, 8 Jan 2026 15:22:47 +0100 Subject: [PATCH] Fixed various bugs and added usage for String data type --- Makefile | 2 +- src/string.c | 17 ++++----- src/string.h | 2 +- usage.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index e62292b..62d8911 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -Wall -Wextra -Werror -pedantic-errors -fstack-protector-strong \ -fsanitize=address -fsanitize=undefined -fstack-clash-protection \ - -Wwrite-strings -g -std=c99 + -fdiagnostics-color=always -Wwrite-strings -g -std=c99 BENCH_FLAGS = -Wall -Wextra -Werror -O3 diff --git a/src/string.c b/src/string.c index 854d3de..09d59fe 100644 --- a/src/string.c +++ b/src/string.c @@ -22,7 +22,7 @@ static inline int utf8_char_len(unsigned char byte) { if ((byte & 0x80) == 0x00) return 1; if ((byte & 0xE0) == 0xC0) return 2; if ((byte & 0xF0) == 0xE0) return 3; - if ((byte & 0xF0) == 0xE0) return 4; + if ((byte & 0xF8) == 0xF0) return 4; return -1; } @@ -59,7 +59,7 @@ static bool utf8_is_char_valid(const char *utf8_char, int *out_len) { static bool utf8_scan(const char *str, size_t *out_byte_size, size_t *out_char_count) { size_t b_size = 0; size_t c_count = 0; - const unsigned char *p = (const unsigned char*)str; + const unsigned char *p = (const unsigned char *)str; while (p[b_size] != '\0') { size_t len = utf8_char_len(p[b_size]); @@ -285,7 +285,7 @@ string_result_t string_concat(const string_t *x, const string_t *y) { return result; } - memcpy(buf, x->data, y->byte_size); + memcpy(buf, x->data, x->byte_size); memcpy(buf + x->byte_size, y->data, y->byte_size); buf[new_size] = '\0'; result = string_new(buf); @@ -400,7 +400,7 @@ string_result_t string_substring(const string_t *haystack, const string_t *needl * * Gets symbol indexed by @position from @str * - * Returns a string_result_t containing a the symbol as a C string + * Returns a string_result_t containing the symbol as a C string */ string_result_t string_get_at(const string_t *str, size_t position) { string_result_t result = {0}; @@ -418,17 +418,18 @@ string_result_t string_get_at(const string_t *str, size_t position) { } int char_len = utf8_char_len((unsigned char)*ptr); - char *symbol = malloc(char_len + 1); - if (symbol == NULL) { + char *utf8_char = malloc(char_len + 1); + if (utf8_char == NULL) { result.status = STRING_ERR_ALLOCATE; SET_MSG(result, "Cannot allocate memory"); return result; } - memcpy(symbol, ptr, char_len); - symbol[char_len] = '\0'; + memcpy(utf8_char, ptr, char_len); + utf8_char[char_len] = '\0'; + result.value.symbol = utf8_char; result.status = STRING_OK; SET_MSG(result, "Symbol successfully retrieved"); diff --git a/src/string.h b/src/string.h index 7641ea8..73ece18 100644 --- a/src/string.h +++ b/src/string.h @@ -27,7 +27,7 @@ typedef struct { uint8_t message[RESULT_MSG_SIZE]; union { string_t *string; // For new, reverse, trim - char *c_str; // For get_at + char *symbol; // For get_at int64_t idx; // For substring search bool is_equ; // For comparison struct { // For split diff --git a/usage.c b/usage.c index c643083..ec8a709 100644 --- a/usage.c +++ b/usage.c @@ -25,10 +25,12 @@ #include "src/vector.h" #include "src/map.h" #include "src/bigint.h" +#include "src/string.h" static int vector_usage(void); static int map_usage(void); static int bigint_usage(void); +static int string_usage(void); static vector_order_t cmp_int_asc(const void *x, const void *y); static vector_order_t cmp_int_desc(const void *x, const void *y); @@ -52,6 +54,11 @@ int main(void) { st = bigint_usage(); if (st) { return st; } + SEP(50); + + st = string_usage(); + if (st) { return st; } + return 0; } @@ -524,3 +531,94 @@ int bigint_usage(void) { return 0; } + +int string_usage(void) { + // Create a new string + string_result_t res = string_new("Hello, "); + if (res.status != STRING_OK) { + printf("Error: %s\n", res.message); + + return 1; + } + + string_t *str1 = res.value.string; + printf("Created string: \"%s\"\n", str1->data); + printf("Character count: %zu (%zu actual bytes)\n\n", string_len(str1), str1->byte_size); + + // Concatenation of strings + string_result_t res_suffix = string_new("World! 🦜"); + if (res_suffix.status != STRING_OK) { + printf("Error: %s\n", res.message); + + return 1; + } + + string_t *suffix = res_suffix.value.string; + printf("Created another string: \"%s\"\n", suffix->data); + printf("Character count: %zu (%zu actual bytes)\n\n", string_len(suffix), suffix->byte_size); + + string_result_t res_cat = string_concat(str1, suffix); + if (res_cat.status != STRING_OK) { + printf("Error: %s\n", res_cat.message); + + return 1; + } + string_destroy(suffix); + + string_t *concat_str = res_cat.value.string; + printf("Concatenation result: \"%s\"\n\n", concat_str->data); + + // Uppercase string + string_result_t res_upper = string_to_upper(concat_str); + if (res_upper.status != STRING_OK) { + printf("Error: %s\n", res_upper.message); + + return 1; + } + printf("Uppercase: \"%s\"\n", res_upper.value.string->data); + string_destroy(res_upper.value.string); + + // Lowercase string + string_result_t res_lower = string_to_lower(concat_str); + if (res_lower.status != STRING_OK) { + printf("Error: %s\n", res_lower.message); + + return 1; + } + printf("Lowercase: \"%s\"\n\n", res_lower.value.string->data); + string_destroy(res_lower.value.string); + + // Reverse string + string_result_t res_rev = string_reverse(concat_str); + if (res_rev.status != STRING_OK) { + printf("Error: %s\n", res_rev.message); + + return 1; + } + printf("Reversed: \"%s\"\n\n", res_rev.value.string->data); + string_destroy(res_rev.value.string); + + // Change first character of the string + string_result_t res_set = string_set_at(concat_str, 0, "J"); + if (res_set.status != STRING_OK) { + printf("Error: %s\n", res_set.message); + + return 1; + } + printf("Updated string: \"%s\"\n\n", concat_str->data); + + // Get character from string (the emoji) + string_result_t res_get = string_get_at(concat_str, 14); + if (res_get.status != STRING_OK) { + printf("Error: %s\n", res_get.message); + + return 1; + } + printf("Extracted symbol: \"%s\"\n", res_get.value.symbol); + free(res_get.value.symbol); + + string_destroy(concat_str); + string_destroy(str1); + + return 0; +}