diff --git a/ctl/string.cc b/ctl/string.cc index 2879d2fcd..9732bd3a2 100644 --- a/ctl/string.cc +++ b/ctl/string.cc @@ -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* diff --git a/ctl/string.h b/ctl/string.h index 4776568dd..61d5a07c2 100644 --- a/ctl/string.h +++ b/ctl/string.h @@ -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 {