From a21f759d2344b8de28faa36fe7ca8689689df3e8 Mon Sep 17 00:00:00 2001 From: Francesco Date: Mon, 8 Sep 2025 02:48:47 +0200 Subject: [PATCH] feat: string find --- string/mystring.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- string/mystring.h | 2 -- test/string/str2.c | 4 ++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/string/mystring.c b/string/mystring.c index 4a89832..89dd82d 100644 --- a/string/mystring.c +++ b/string/mystring.c @@ -239,7 +239,7 @@ char *mcl_string_cstr(mcl_string_s *string) { tl_buffer_s *tb = (tl_buffer_s *)tss_get(buffer_key); if (tb == NULL) { /* Not found, make a new one */ - tb = malloc(sizeof(*tb)); + tb = malloc(sizeof(tl_buffer_s)); if (tb == NULL) { mtx_unlock(&string->lock); @@ -352,3 +352,57 @@ void mcl_string_tolower(mcl_string_s *string) { mtx_unlock(&string->lock); } + +/* Build Longest Prefix Suffix array */ +static void build_lsp(int *lps, const char *substring, size_t sub_len) { + int len = 0; + int i = 1; + + while (i < sub_len) { + if (substring[i] == substring[len]) { + lps[i++] = ++len; + } else { + if (len != 0) { + len = lps[len - 1]; + } else { + lps[i++] = 0; + } + } + } +} + +int mcl_string_find(mcl_string_s *string, const char *substring) { + if (string == NULL || substring == NULL) { + return -1; + } + + /* Handle empty case */ + if (strcmp(string->data, "") == 0) { + return -1; + } + + size_t sub_len = strlen(substring); + int lps[sub_len]; + memset(lps, 0, sizeof(lps)); + build_lsp(lps, substring, sub_len); + + size_t i = 0; /* string iterator */ + size_t j = 0; /* substring iterator */ + while (i < string->size) { + if (string->data[i] == substring[j]) { + i++; + j++; + if (j == sub_len) { + return i - j; + } + } else { + if (j != 0) { + j = lps[j - 1]; + } else { + i++; + } + } + } + + return -1; +} diff --git a/string/mystring.h b/string/mystring.h index 3dbbce5..1851249 100644 --- a/string/mystring.h +++ b/string/mystring.h @@ -111,8 +111,6 @@ void mcl_string_tolower(mcl_string_s *string); * @param string String where to search. * @param substring Substring to search. * @return Index of the first occurrence, -1 on failure. - * - * @note TODO */ int mcl_string_find(mcl_string_s *string, const char *substring); diff --git a/test/string/str2.c b/test/string/str2.c index 564cfae..183d292 100644 --- a/test/string/str2.c +++ b/test/string/str2.c @@ -28,6 +28,10 @@ void test_str2(void) { assert(mcl_string_length(s1) == 50); assert(mcl_string_capacity(s1) == 64); + /* Find substring in string */ + int pos = mcl_string_find(s1, "is"); + assert(pos == 2); + mcl_string_free(s1); mcl_string_free(s2); mcl_string_free(extend_me);