166 lines
4.0 KiB
C
166 lines
4.0 KiB
C
#include "string.h"
|
|
|
|
Str str_empty(void)
|
|
{
|
|
static const U8 empty_;
|
|
static const Str str = {(U8 *)&empty_, 0};
|
|
return str;
|
|
}
|
|
|
|
Str str_slice(Str str, U32 start, U32 len)
|
|
{
|
|
Assert(start <= str.len);
|
|
Assert(len <= str.len - start);
|
|
|
|
Str new_str = str_create(&str.str[start], len);
|
|
return new_str;
|
|
}
|
|
|
|
Str str_concat(Allocator *alloc, Str first, Str second)
|
|
{
|
|
Str str;
|
|
Assert(first.len <= U32_Max - second.len);
|
|
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, str.len, 1);
|
|
MemCopy(mem, str.str, str.len);
|
|
|
|
return str_create(mem, str.len);
|
|
}
|
|
|
|
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_index(Str haystack, Str needle)
|
|
{
|
|
if (needle.len == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (needle.len == 1) {
|
|
return str_find_byte(haystack, needle.str[0]);
|
|
}
|
|
if (needle.len > haystack.len) {
|
|
return -1;
|
|
}
|
|
|
|
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
|
|
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_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_slice(str, start_pos, str.len - start_pos);
|
|
vec->strings[vec->len] = sub_str;
|
|
vec->len++;
|
|
}
|
|
}
|
|
|
|
Str str_join(Allocator *allocator, StrVec strings, Str separator)
|
|
{
|
|
|
|
U32 joined_str_len = 0;
|
|
|
|
for (U32 i = 0; i < strings.len; i++) {
|
|
U32 part_len = strings.strings[i].len;
|
|
Assert(joined_str_len <= U32_Max - part_len); // overflow
|
|
joined_str_len += part_len;
|
|
}
|
|
if (strings.len > 1) {
|
|
U32 separator_count = strings.len - 1;
|
|
Assert(separator.len <= U32_Max / separator_count); // overflow
|
|
Assert(joined_str_len <= U32_Max - separator.len * separator_count); // overflow
|
|
joined_str_len += separator.len * separator_count;
|
|
}
|
|
|
|
U8 *joined_str = allocator_push(allocator, joined_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, joined_str_len);
|
|
}
|