From bd008c51fea157e5e7f079c6e26f3c23784d7d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 27 Jul 2026 19:45:00 +0200 Subject: [PATCH] Ascii trim --- src/base_core.h | 1 + src/main.c | 36 ++++++++++++++++++++++++++++++---- src/string.c | 52 +++++++++++++++++++++++++++++++++++++++++++++---- src/string.h | 38 +++++++++++++++++++++++++++++++++--- 4 files changed, 116 insertions(+), 11 deletions(-) diff --git a/src/base_core.h b/src/base_core.h index f903913..4496069 100644 --- a/src/base_core.h +++ b/src/base_core.h @@ -250,6 +250,7 @@ typedef unsigned __int128 U128; #define MemMove(dst, src, len) memmove(dst, src, len) #define MemCopy(dst, src, len) memcpy(dst, src, len) #define MemAppend(dst, src, len) mempcpy(dst, src, len) +#define MemCompare(first, second, len) memcmp(first, second, len) // atomics #define Atomic(type) _Atomic(type) diff --git a/src/main.c b/src/main.c index 2e140e9..863126a 100644 --- a/src/main.c +++ b/src/main.c @@ -416,7 +416,7 @@ void string_test_1(void) { TRACEF("\n"); - Str str1 = S_("Hello"); + Str str1 = S("Hello"); printf("str1: %.*s len %d\n", str1.len, str1.str, str1.len); U64 str1_index_of_l = str_find_byte(str1, 'l'); U64 str1_index_of_g = str_find_byte(str1, 'g'); @@ -424,7 +424,7 @@ void string_test_1(void) MARENA_DEFINE(arena, 512, 1); Allocator alloc = marena_allocator(&arena); - Str str2 = str_dup(&alloc, S_(" World")); + Str str2 = str_dup(&alloc, S(" World")); Str str3 = str_concat(&alloc, str1, str2); printf("str3: %.*s len %d\n", str3.len, str3.str, str3.len); } @@ -433,8 +433,8 @@ void string_split_test_1(void) { TRACEF("\n"); - Str str1 = S_("a:bb|ccc"); - Str sep = S_("|:"); + Str str1 = S("a:bb|ccc"); + Str sep = S("|:"); STRVEC_DEFINE(strings, 16); str_split(str1, sep, &strings); @@ -443,7 +443,34 @@ void string_split_test_1(void) printf("split %u: '%.*s'\n", i, str->len, str->str); } } +void string_test_misc(void) +{ + TRACEF("\n"); + Str str1 = S("Hello World"); + bool prefix1 = str_starts_with(str1, S("He")); + bool prefix2 = str_starts_with(str1, S("")); + bool prefix3 = str_starts_with(str1, S("false")); + bool suffix1 = str_ends_with(str1, S("orld")); + bool suffix2 = str_ends_with(str1, S("")); + bool suffix3 = str_ends_with(str1, S("false")); + printf("matches: %d %d %d %d %d %d\n", prefix1, prefix2, prefix3, suffix1, suffix2, suffix3); + + Str str2 = S(" Hello World\t \n"); + Str str2_trim = str_ascii_trim(str2); + printf("str2_trim: '%.*s'\n", str2_trim.len, str2_trim.str); + printf("str2_trim == str1: %d\n", str_eq(str1, str2_trim)); + + Str str3 = str_empty(); + Str str3_trim = str_ascii_trim(str3); + printf("str3_trim: '%.*s'\n", str3_trim.len, str3_trim.str); + + + Str str4 = S(" \t\t "); + Str str4_trim = str_ascii_trim(str4); + printf("str4_trim: '%.*s'\n", str4_trim.len, str4_trim.str); + +} int main(int argc, char *argv[]) { arena_test_1(); @@ -458,6 +485,7 @@ int main(int argc, char *argv[]) apool_test_miniarena(); string_test_1(); string_split_test_1(); + string_test_misc(); } diff --git a/src/string.c b/src/string.c index 1bc3e13..9737253 100644 --- a/src/string.c +++ b/src/string.c @@ -7,7 +7,7 @@ Str str_empty(void) return str; } -Str str_substr(Str str, U32 start, U32 len) +Str str_slice(Str str, U32 start, U32 len) { Assert(start < str.len); Assert(len <= str.len); @@ -16,7 +16,6 @@ Str str_substr(Str str, U32 start, U32 len) return new_str; } - Str str_concat(Allocator *alloc, Str first, Str second) { Str str; @@ -43,6 +42,51 @@ Str str_push(Allocator *alloc, Str str) return *new_str; } +static INLINE bool char_is_ascii_whitespace(U8 byte) +{ + return byte == ' ' || byte == '\t' || byte == '\v' || byte == '\f' || byte == '\r' || byte == '\n'; + +} + +Str str_ascii_trim_left(Str str) +{ + U8 *start = str.str; + U8 *end = str.str + str.len; + while (start != end) { + if (!char_is_ascii_whitespace(*start)) { + break; + } + start++; + } + + return str_create(start, (U32)(end - start)); +} + +Str str_ascii_trim_right(Str str) +{ + U8 *start = str.str; + U8 *end = str.str + str.len; + while (start != end) { + if (!char_is_ascii_whitespace(*(end - 1))) { + break; + } + end--; + } + + return str_create(start, (U32)(end - start)); +} + +Str str_ascii_trim(Str str) +{ + Str new_str = str_ascii_trim_left(str); + new_str = str_ascii_trim_right(new_str); + return new_str; +} + +S64 str_substr(Str haystack, Str to_find) +{ +} + // split @str on any byte in @separators, place split strings in @vec void str_split(Str str, Str separators, StrVec *vec) { @@ -58,14 +102,14 @@ void str_split(Str str, Str separators, StrVec *vec) break; } - Str sub_str = str_substr(str, start_pos, i - start_pos); + Str sub_str = str_slice(str, start_pos, i - start_pos); vec->strings[vec->len] = sub_str; vec->len++; start_pos = i + 1; } } if (start_pos < str.len && vec->len < vec->max_len) { - Str sub_str = str_substr(str, start_pos, str.len - start_pos); + Str sub_str = str_slice(str, start_pos, str.len - start_pos); vec->strings[vec->len] = sub_str; vec->len++; } diff --git a/src/string.h b/src/string.h index 8dd10ba..33592c9 100644 --- a/src/string.h +++ b/src/string.h @@ -8,15 +8,29 @@ struct Str { }; Str str_empty(void); -Str str_substr(Str str, U32 start, U32 len); +Str str_slice(Str str, U32 start, U32 len); +S64 str_substr(Str haystack, Str to_find); + Str str_concat(Allocator *alloc, Str first, Str second); Str str_push(Allocator *alloc, Str str); +Str str_ascii_trim(Str str); +Str str_ascii_trim_left(Str str); +Str str_ascii_trim_right(Str str); + #define str_from_lit(str) str_create(((U8 *)str), sizeof(str) -1) -#define S_(str) str_from_lit(str) +#define S(str) str_from_lit(str) #define cstr_len(str) (U32)strlen(str) #define str_dup(alloc, str) str_push((alloc), (str)) +static INLINE bool str_eq(Str first, Str second) +{ + if (first.len != second.len) { + return false; + } + return MemCompare(first.str, second.str, first.len) == 0; +} + static INLINE bool str_is_empty(Str str) { return str.len == 0; @@ -51,10 +65,28 @@ static INLINE S64 str_find_byte(Str str, U8 byte) return -1; } +static INLINE bool str_starts_with(Str str, Str prefix) +{ + if (prefix.len > str.len) { + return false; + } + + return MemCompare(str.str, prefix.str, prefix.len) == 0; +} + +static INLINE bool str_ends_with(Str str, Str suffix) +{ + if (suffix.len > str.len) { + return false; + } + U32 start = str.len - suffix.len; + return MemCompare(&str.str[start], suffix.str, suffix.len) == 0; +} + static INLINE Str str_skip(Str str, U32 len) { U32 skip_len = Min(str.len, len); - Str new_str = str_substr(str, skip_len, str.len - skip_len); + Str new_str = str_slice(str, skip_len, str.len - skip_len); return new_str; }