Compare commits
3
Commits
8534075307
...
7f2713eeff
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f2713eeff | ||
|
|
a94640e71d | ||
|
|
bd008c51fe |
@@ -250,7 +250,20 @@ typedef unsigned __int128 U128;
|
|||||||
#define MemMove(dst, src, len) memmove(dst, src, len)
|
#define MemMove(dst, src, len) memmove(dst, src, len)
|
||||||
#define MemCopy(dst, src, len) memcpy(dst, src, len)
|
#define MemCopy(dst, src, len) memcpy(dst, src, len)
|
||||||
#define MemAppend(dst, src, len) mempcpy(dst, src, len)
|
#define MemAppend(dst, src, len) mempcpy(dst, src, len)
|
||||||
|
#define MemCompare(first, second, len) memcmp(first, second, len)
|
||||||
|
|
||||||
|
static INLINE U8 *MemFind(U8 *mem, U64 mem_len, U8 *needle, U64 needle_len)
|
||||||
|
{
|
||||||
|
if (needle_len > mem_len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (U64 i = 0 ; i + needle_len <= mem_len; i++) {
|
||||||
|
if (MemCompare(&mem[i], needle, needle_len) == 0) {
|
||||||
|
return &mem[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
// atomics
|
// atomics
|
||||||
#define Atomic(type) _Atomic(type)
|
#define Atomic(type) _Atomic(type)
|
||||||
#define AtomicSub(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST)
|
#define AtomicSub(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST)
|
||||||
|
|||||||
+61
-4
@@ -416,7 +416,7 @@ void string_test_1(void)
|
|||||||
{
|
{
|
||||||
TRACEF("\n");
|
TRACEF("\n");
|
||||||
|
|
||||||
Str str1 = S_("Hello");
|
Str str1 = S("Hello");
|
||||||
printf("str1: %.*s len %d\n", str1.len, str1.str, str1.len);
|
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_l = str_find_byte(str1, 'l');
|
||||||
U64 str1_index_of_g = str_find_byte(str1, 'g');
|
U64 str1_index_of_g = str_find_byte(str1, 'g');
|
||||||
@@ -424,7 +424,7 @@ void string_test_1(void)
|
|||||||
|
|
||||||
MARENA_DEFINE(arena, 512, 1);
|
MARENA_DEFINE(arena, 512, 1);
|
||||||
Allocator alloc = marena_allocator(&arena);
|
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);
|
Str str3 = str_concat(&alloc, str1, str2);
|
||||||
printf("str3: %.*s len %d\n", str3.len, str3.str, str3.len);
|
printf("str3: %.*s len %d\n", str3.len, str3.str, str3.len);
|
||||||
}
|
}
|
||||||
@@ -433,8 +433,8 @@ void string_split_test_1(void)
|
|||||||
{
|
{
|
||||||
TRACEF("\n");
|
TRACEF("\n");
|
||||||
|
|
||||||
Str str1 = S_("a:bb|ccc");
|
Str str1 = S("a:bb|ccc");
|
||||||
Str sep = S_("|:");
|
Str sep = S("|:");
|
||||||
STRVEC_DEFINE(strings, 16);
|
STRVEC_DEFINE(strings, 16);
|
||||||
|
|
||||||
str_split(str1, sep, &strings);
|
str_split(str1, sep, &strings);
|
||||||
@@ -443,6 +443,61 @@ void string_split_test_1(void)
|
|||||||
printf("split %u: '%.*s'\n", i, str->len, str->str);
|
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);
|
||||||
|
|
||||||
|
S64 found = str_substr(str1, S("World"));
|
||||||
|
printf("1. found %ld\n", found);
|
||||||
|
found = str_substr(str_empty(), S("World"));
|
||||||
|
printf("2. found %ld\n", found);
|
||||||
|
found = str_substr(str_empty(), S(""));
|
||||||
|
printf("3. found %ld\n", found);
|
||||||
|
found = str_substr(str1, S(" "));
|
||||||
|
printf("4. found %ld\n", found);
|
||||||
|
|
||||||
|
}
|
||||||
|
void string_test_join(void)
|
||||||
|
{
|
||||||
|
TRACEF("\n");
|
||||||
|
Arena arena;
|
||||||
|
arena_init(&arena, &ArenaOptions_Default);
|
||||||
|
Allocator allocator = arena_allocator(&arena);
|
||||||
|
Str strs[3] = {S("1"), S("two"), S("3-3")};
|
||||||
|
StrVec vec = STRVEC_STATIC_INITIALIZER(strs);
|
||||||
|
|
||||||
|
Str str = str_join(&allocator, vec, S("/"));
|
||||||
|
printf("str_join 1 '%.*s'\n", str.len, str.str);
|
||||||
|
str = str_join(&allocator, vec, S(""));
|
||||||
|
printf("str_join 2 '%.*s'\n", str.len, str.str);
|
||||||
|
vec.len = 0;
|
||||||
|
str = str_join(&allocator, vec, S("/"));
|
||||||
|
printf("str_join 2 '%.*s'\n", str.len, str.str);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -458,6 +513,8 @@ int main(int argc, char *argv[])
|
|||||||
apool_test_miniarena();
|
apool_test_miniarena();
|
||||||
string_test_1();
|
string_test_1();
|
||||||
string_split_test_1();
|
string_split_test_1();
|
||||||
|
string_test_misc();
|
||||||
|
string_test_join();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+94
-11
@@ -7,7 +7,7 @@ Str str_empty(void)
|
|||||||
return str;
|
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(start < str.len);
|
||||||
Assert(len <= str.len);
|
Assert(len <= str.len);
|
||||||
@@ -16,7 +16,6 @@ Str str_substr(Str str, U32 start, U32 len)
|
|||||||
return new_str;
|
return new_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Str str_concat(Allocator *alloc, Str first, Str second)
|
Str str_concat(Allocator *alloc, Str first, Str second)
|
||||||
{
|
{
|
||||||
Str str;
|
Str str;
|
||||||
@@ -32,15 +31,69 @@ Str str_concat(Allocator *alloc, Str first, Str second)
|
|||||||
|
|
||||||
Str str_push(Allocator *alloc, Str str)
|
Str str_push(Allocator *alloc, Str str)
|
||||||
{
|
{
|
||||||
U8 *mem = (U8 *)allocator_push(alloc, sizeof(Str) + str.len, alignof(Str));
|
U8 *mem = (U8 *)allocator_push(alloc, str.len, 1);
|
||||||
Str *new_str = (Str *)mem;
|
MemCopy(mem, str.str, str.len);
|
||||||
new_str->len = str.len;
|
|
||||||
new_str->str = &mem[sizeof(Str)];
|
return str_create(mem, str.len);
|
||||||
if (!str_is_empty(str)) {
|
|
||||||
MemCopy(new_str->str, str.str, str.len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 needle)
|
||||||
|
{
|
||||||
|
if (needle.len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needle.len == 0) {
|
||||||
|
return str_find_byte(haystack, needle.str[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 *found = MemFind(haystack.str, haystack.len, needle.str, needle.len);
|
||||||
|
if (found != NULL) {
|
||||||
|
return (S64)(found - haystack.str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// split @str on any byte in @separators, place split strings in @vec
|
// split @str on any byte in @separators, place split strings in @vec
|
||||||
@@ -58,15 +111,45 @@ void str_split(Str str, Str separators, StrVec *vec)
|
|||||||
break;
|
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->strings[vec->len] = sub_str;
|
||||||
vec->len++;
|
vec->len++;
|
||||||
start_pos = i + 1;
|
start_pos = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (start_pos < str.len && vec->len < vec->max_len) {
|
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->strings[vec->len] = sub_str;
|
||||||
vec->len++;
|
vec->len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Str str_join(Allocator *allocator, StrVec strings, Str separator)
|
||||||
|
{
|
||||||
|
|
||||||
|
U32 str_len = 0;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < strings.len; i++) {
|
||||||
|
str_len += strings.strings[i].len;
|
||||||
|
}
|
||||||
|
if (strings.len > 0) {
|
||||||
|
str_len += separator.len * (strings.len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 *joined_str = allocator_push(allocator, str_len, 1);
|
||||||
|
if (strings.len > 0) {
|
||||||
|
U32 pos = 0;
|
||||||
|
Str *str = &strings.strings[0];
|
||||||
|
MemCopy(&joined_str[pos], str->str, str->len);
|
||||||
|
pos += str->len;
|
||||||
|
for (U32 i = 1; i < strings.len; i++) {
|
||||||
|
str = &strings.strings[i];
|
||||||
|
MemCopy(&joined_str[pos], separator.str, separator.len);
|
||||||
|
pos += separator.len;
|
||||||
|
MemCopy(&joined_str[pos], str->str, str->len);
|
||||||
|
pos += str->len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_create(joined_str, str_len);
|
||||||
|
}
|
||||||
|
|||||||
+41
-6
@@ -8,15 +8,29 @@ struct Str {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Str str_empty(void);
|
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 needle);
|
||||||
|
|
||||||
Str str_concat(Allocator *alloc, Str first, Str second);
|
Str str_concat(Allocator *alloc, Str first, Str second);
|
||||||
Str str_push(Allocator *alloc, Str str);
|
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 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 cstr_len(str) (U32)strlen(str)
|
||||||
#define str_dup(alloc, str) str_push((alloc), (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)
|
static INLINE bool str_is_empty(Str str)
|
||||||
{
|
{
|
||||||
return str.len == 0;
|
return str.len == 0;
|
||||||
@@ -51,10 +65,28 @@ static INLINE S64 str_find_byte(Str str, U8 byte)
|
|||||||
return -1;
|
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)
|
static INLINE Str str_skip(Str str, U32 len)
|
||||||
{
|
{
|
||||||
U32 skip_len = Min(str.len, 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;
|
return new_str;
|
||||||
}
|
}
|
||||||
@@ -67,12 +99,15 @@ struct StrVec {
|
|||||||
U32 len;
|
U32 len;
|
||||||
U32 max_len;
|
U32 max_len;
|
||||||
};
|
};
|
||||||
#define STRVEC_STATIC_INITIALIZER(strings_) STRVEC_INITIALIZER((strings_), ArraySize(strings_))
|
#define STRVEC_STATIC_INITIALIZER(strings_) STRVEC_INITIALIZER((strings_), ArraySize(strings_), ArraySize(strings_))
|
||||||
#define STRVEC_INITIALIZER(strings_, len_) {.strings = (strings_), .len = 0, .max_len = (len_)}
|
#define STRVEC_STATIC_INITIALIZER_EMPTY(strings_) STRVEC_INITIALIZER((strings_), 0, ArraySize(strings_))
|
||||||
|
#define STRVEC_INITIALIZER(strings_, len_, max_len_) {.strings = (strings_), .len = (len_), .max_len = (max_len_)}
|
||||||
|
|
||||||
#define STRVEC_DEFINE(var_name, len_) \
|
#define STRVEC_DEFINE(var_name, len_) \
|
||||||
struct { \
|
struct { \
|
||||||
Str strings[len_];\
|
Str strings[len_];\
|
||||||
} var_name##_strvec_array; \
|
} var_name##_strvec_array; \
|
||||||
StrVec var_name = STRVEC_STATIC_INITIALIZER(var_name##_strvec_array.strings)
|
StrVec var_name = STRVEC_STATIC_INITIALIZER_EMPTY(var_name##_strvec_array.strings)
|
||||||
|
|
||||||
void str_split(Str str, Str separators, StrVec *vec);
|
void str_split(Str str, Str separators, StrVec *vec);
|
||||||
|
Str str_join(Allocator *allocator, StrVec strings, Str separator);
|
||||||
|
|||||||
Reference in New Issue
Block a user