More string stuff
This commit is contained in:
+35
@@ -3,6 +3,7 @@
|
||||
#include "mini_arena.h"
|
||||
#include "platform.h"
|
||||
#include "pool.h"
|
||||
#include "string.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -411,6 +412,38 @@ void apool_test_autogrow(void)
|
||||
|
||||
}
|
||||
|
||||
void string_test_1(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
|
||||
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');
|
||||
printf("str1: index of l %ld, index of g: %ld\n", str1_index_of_l, str1_index_of_g);
|
||||
|
||||
MARENA_DEFINE(arena, 512, 1);
|
||||
Allocator alloc = marena_allocator(&arena);
|
||||
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);
|
||||
}
|
||||
|
||||
void string_split_test_1(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
|
||||
Str str1 = S_("a:bb|ccc");
|
||||
Str sep = S_("|:");
|
||||
STRVEC_DEFINE(strings, 16);
|
||||
|
||||
str_split(str1, sep, &strings);
|
||||
for (U32 i = 0; i < strings.len; i++) {
|
||||
Str *str = &strings.strings[i];
|
||||
printf("split %u: '%.*s'\n", i, str->len, str->str);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
arena_test_1();
|
||||
@@ -423,6 +456,8 @@ int main(int argc, char *argv[])
|
||||
apool_test();
|
||||
apool_test_autogrow();
|
||||
apool_test_miniarena();
|
||||
string_test_1();
|
||||
string_split_test_1();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "string.h"
|
||||
|
||||
Str str_empty(void)
|
||||
{
|
||||
static const U8 empty_;
|
||||
static const Str str = {(U8 *)&empty_, 0};
|
||||
return str;
|
||||
}
|
||||
|
||||
Str str_substr(Str str, U32 start, U32 len)
|
||||
{
|
||||
Assert(start < str.len);
|
||||
Assert(len <= str.len);
|
||||
|
||||
Str new_str = str_create(&str.str[start], len);
|
||||
return new_str;
|
||||
}
|
||||
|
||||
|
||||
Str str_concat(Allocator *alloc, Str first, Str second)
|
||||
{
|
||||
Str str;
|
||||
|
||||
str.len = first.len + second.len;
|
||||
str.str = allocator_push(alloc, str.len, 1);;
|
||||
|
||||
MemCopy(str.str, first.str, first.len);
|
||||
MemCopy(&str.str[first.len], second.str, second.len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
Str str_push(Allocator *alloc, Str str)
|
||||
{
|
||||
U8 *mem = (U8 *)allocator_push(alloc, sizeof(Str) + str.len, alignof(Str));
|
||||
Str *new_str = (Str *)mem;
|
||||
new_str->len = str.len;
|
||||
new_str->str = &mem[sizeof(Str)];
|
||||
if (!str_is_empty(str)) {
|
||||
MemCopy(new_str->str, str.str, str.len);
|
||||
}
|
||||
|
||||
return *new_str;
|
||||
}
|
||||
|
||||
// split @str on any byte in @separators, place split strings in @vec
|
||||
void str_split(Str str, Str separators, StrVec *vec)
|
||||
{
|
||||
if (vec->max_len == 0 || str.len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
U32 start_pos = 0;
|
||||
for (U32 i = 0; i < str.len; i++) {
|
||||
U8 byte = str.str[i];
|
||||
if (str_find_byte(separators, byte) != -1) {
|
||||
if (vec->len >= vec->max_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
Str sub_str = str_substr(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);
|
||||
vec->strings[vec->len] = sub_str;
|
||||
vec->len++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include "base_core.h"
|
||||
|
||||
typedef struct Str Str;
|
||||
struct Str {
|
||||
U8 *str;
|
||||
U32 len;
|
||||
};
|
||||
|
||||
Str str_empty(void);
|
||||
Str str_substr(Str str, U32 start, U32 len);
|
||||
Str str_concat(Allocator *alloc, Str first, Str second);
|
||||
Str str_push(Allocator *alloc, Str str);
|
||||
|
||||
#define str_from_lit(str) str_create(((U8 *)str), sizeof(str) -1)
|
||||
#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_is_empty(Str str)
|
||||
{
|
||||
return str.len == 0;
|
||||
}
|
||||
|
||||
static INLINE Str str_create(U8 *start, U32 len)
|
||||
{
|
||||
Str str = {start, len};
|
||||
return str;
|
||||
}
|
||||
|
||||
static INLINE Str str_from_cstr(const char *cstr)
|
||||
{
|
||||
Str str = str_create((U8 *)cstr, cstr_len(cstr));
|
||||
return str;
|
||||
}
|
||||
|
||||
static INLINE Str str_push_cstr(Allocator *alloc, const char *cstr)
|
||||
{
|
||||
Str str = str_from_cstr(cstr);
|
||||
return str_push(alloc, str);
|
||||
}
|
||||
|
||||
static INLINE S64 str_find_byte(Str str, U8 byte)
|
||||
{
|
||||
for (U32 i = 0; i < str.len; i++) {
|
||||
if (str.str[i] == byte) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
|
||||
// String Vector
|
||||
typedef struct StrVec StrVec;
|
||||
struct StrVec {
|
||||
Str *strings;
|
||||
U32 len;
|
||||
U32 max_len;
|
||||
};
|
||||
#define STRVEC_STATIC_INITIALIZER(strings_) STRVEC_INITIALIZER((strings_), ArraySize(strings_))
|
||||
#define STRVEC_INITIALIZER(strings_, len_) {.strings = (strings_), .len = 0, .max_len = (len_)}
|
||||
#define STRVEC_DEFINE(var_name, len_) \
|
||||
struct { \
|
||||
Str strings[len_];\
|
||||
} var_name##_strvec_array; \
|
||||
StrVec var_name = STRVEC_STATIC_INITIALIZER(var_name##_strvec_array.strings)
|
||||
|
||||
void str_split(Str str, Str separators, StrVec *vec);
|
||||
Reference in New Issue
Block a user