Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions dstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ static inline void* _dstr_get_hdr_and_type(dstr s, enum dstrhd_type* t_out)
}
}

static inline size_t _dstr_grow_cap(size_t old_cap, size_t needed)
{
size_t grown = old_cap < 16 ? 16 : old_cap;
if (grown <= SIZE_MAX - grown / 2)
grown += grown / 2;
return grown > needed ? grown : needed;
}

// strfind
ssize_t dstrfind(dstr s, const char* needle)
{
Expand All @@ -164,10 +172,17 @@ ssize_t dstrfind(dstr s, const char* needle)
if (nlen > len)
return -1;

for (size_t i = 0; i <= len - nlen; i++) {
if (memcmp(&s[i], needle, nlen) == 0) {
return i;
}
size_t remaining = len - nlen + 1;
const char* cursor = s;

while (remaining > 0) {
const char* hit = memchr(cursor, needle[0], remaining);
if (!hit)
return -1;
if (memcmp(hit, needle, nlen) == 0)
return hit - s;
remaining -= (size_t)(hit - cursor) + 1;
cursor = hit + 1;
}

return -1;
Expand Down Expand Up @@ -351,11 +366,21 @@ static dstr _dstr_concat_impl(dstr s1,
size_t new_len = s1_len + s2_len;
if (cap < new_len + 1)
cap = new_len + 1;

uintptr_t s1_addr = (uintptr_t)s1;
uintptr_t s2_addr = (uintptr_t)s2;
size_t s1_cap = dstrcap(s1);
bool s2_aliases_s1 = s2_addr >= s1_addr && s2_addr - s1_addr < s1_cap;
size_t s2_offset = s2_aliases_s1 ? (size_t)(s2_addr - s1_addr) : 0;

dstr tmp = dstrreserve(s1, cap);
if (!tmp)
return NULL;
s1 = tmp;

if (s2_aliases_s1)
s2 = s1 + s2_offset;

uint8_t hdr_type = DSTRGETTYPE(s1);
void* hd = NULL;
switch (hdr_type) {
Expand Down Expand Up @@ -387,7 +412,8 @@ dstr dstrcat_base(dstr s1, const char* s2)
return s1;
size_t s1_len = dstrlen(s1);
size_t s2_len = strlen(s2);
return _dstr_concat_impl(s1, s1_len, s2, s2_len, s1_len + s2_len + 1);
size_t cap = _dstr_grow_cap(dstrcap(s1), s1_len + s2_len + 1);
return _dstr_concat_impl(s1, s1_len, s2, s2_len, cap);
}

dstr dstrcat_custom(dstr s1, const char* s2, size_t cap)
Expand Down Expand Up @@ -427,7 +453,8 @@ dstr dstrpush_custom(dstr s1, const char c, size_t cap)

dstr dstrpush_base(dstr s1, const char c)
{
return dstrpush_custom(s1, c, dstrcap(s1) + 1);
size_t cap = dstrcap(s1);
return dstrpush_custom(s1, c, _dstr_grow_cap(cap, cap + 1));
}

// strappend
Expand All @@ -437,7 +464,8 @@ dstr dstrappend_base(dstr s1, const dstr s2)
return s1;
size_t s1_len = dstrlen(s1);
size_t s2_len = dstrlen(s2);
return _dstr_concat_impl(s1, s1_len, s2, s2_len, s1_len + s2_len + 1);
size_t cap = _dstr_grow_cap(dstrcap(s1), s1_len + s2_len + 1);
return _dstr_concat_impl(s1, s1_len, s2, s2_len, cap);
}

dstr dstrappend_custom(dstr s1, const dstr s2, size_t cap)
Expand Down
Loading