More small-string optimizations

This commit is contained in:
Steven Dee (Jōshin) 2024-06-18 17:27:32 -07:00
parent be005b63e3
commit d1b6715018
No known key found for this signature in database
2 changed files with 84 additions and 29 deletions

View file

@ -38,29 +38,47 @@ string::destroy_big() noexcept
free(b->p);
}
string::string(const char* s) noexcept : string()
void
string::init_big(const string& s) noexcept
{
append(s, strlen(s));
char* p2;
if (s.size() >= s.capacity() >> 1) {
if (!(p2 = (char*)malloc(s.capacity())))
__builtin_trap();
set_big_string(p2, s.size(), s.capacity());
} else {
init_big(string_view(s));
}
}
string::string(const string& s) noexcept : string()
void
string::init_big(const string_view s) noexcept
{
append(s.data(), s.size());
size_t need;
char* p2;
if (ckd_add(&need, s.n, 1 /* nul */ + 15))
__builtin_trap();
need &= -16;
if (!(p2 = (char*)malloc(need)))
__builtin_trap();
memcpy(p2, s.p, s.n);
p2[s.n] = 0;
set_big_string(p2, s.n, need);
}
string::string(const string_view s) noexcept : string()
void
string::init_big(const size_t n, const char ch) noexcept
{
append(s.p, s.n);
}
string::string(const size_t size, const char ch) noexcept : string()
{
resize(size, ch);
}
string::string(const char* s, const size_t size) noexcept : string()
{
append(s, size);
size_t need;
char* p2;
if (ckd_add(&need, n, 1 /* nul */ + 15))
__builtin_trap();
need &= -16;
if (!(p2 = (char*)malloc(need)))
__builtin_trap();
memset(p2, ch, n);
p2[n] = 0;
set_big_string(p2, n, need);
}
const char*

View file

@ -48,18 +48,59 @@ class string
using const_iterator = const char*;
static constexpr size_t npos = -1;
string() noexcept
{
__builtin_memset(blob, 0, sizeof(size_t) * 2);
// equivalent to set_small_size(0) but also zeroes memory
*(((size_t*)blob) + 2) = __::sso_max << (sizeof(size_t) - 1) * 8;
}
string(const string_view s) noexcept
{
if (s.n <= __::sso_max) {
__builtin_memcpy(blob, s.p, s.n);
__builtin_memset(blob + s.n, 0, __::sso_max - s.n);
set_small_size(s.n);
} else {
init_big(s);
}
}
explicit string(const size_t n, const char ch = 0) noexcept
{
if (n <= __::sso_max) {
__builtin_memset(blob, ch, n);
__builtin_memset(blob + n, 0, __::sso_max - n);
set_small_size(n);
} else {
init_big(n, ch);
}
}
string(const char* const p) noexcept
: string(string_view(p, __builtin_strlen(p)))
{
}
string(const string& r) noexcept
{
if (r.isbig())
init_big(r);
else
__builtin_memcpy(blob, r.blob, __::string_size);
}
string(const char* const p, const size_t n) noexcept
: string(string_view(p, n))
{
}
~string() /* noexcept */
{
if (isbig())
destroy_big();
}
string(string_view) noexcept;
string(const char*) noexcept;
string(const string&) noexcept;
string(const char*, size_t) noexcept;
explicit string(size_t, char = 0) noexcept;
string& operator=(string) noexcept;
const char* c_str() const noexcept;
@ -83,13 +124,6 @@ class string
size_t find(char, size_t = 0) const noexcept;
size_t find(string_view, size_t = 0) const noexcept;
string() noexcept
{
__builtin_memset(blob, 0, sizeof(size_t) * 2);
// equivalent to set_small_size(0) but also zeroes memory
*(((size_t*)blob) + 2) = __::sso_max << (sizeof(size_t) - 1) * 8;
}
void swap(string& s) noexcept
{
ctl::swap(blob, s.blob);
@ -283,6 +317,9 @@ class string
private:
void destroy_big() noexcept;
void init_big(const string&) noexcept;
void init_big(string_view) noexcept;
void init_big(size_t, char) noexcept;
inline bool isbig() const noexcept
{