More string stuff
This commit is contained in:
+35
@@ -3,6 +3,7 @@
|
|||||||
#include "mini_arena.h"
|
#include "mini_arena.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
|
#include "string.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
arena_test_1();
|
arena_test_1();
|
||||||
@@ -423,6 +456,8 @@ int main(int argc, char *argv[])
|
|||||||
apool_test();
|
apool_test();
|
||||||
apool_test_autogrow();
|
apool_test_autogrow();
|
||||||
apool_test_miniarena();
|
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