diff --git a/ctl/string.cc b/ctl/string.cc index ff864c306..2a2b22eb1 100644 --- a/ctl/string.cc +++ b/ctl/string.cc @@ -99,7 +99,8 @@ string::reserve(size_t c2) noexcept if (!isbig()) { if (!(p2 = (char*)malloc(c2))) __builtin_trap(); - memcpy(p2, data(), size() + 1); + memcpy(p2, data(), size()); + p2[size()] = 0; } else { if (!(p2 = (char*)realloc(big()->p, c2))) __builtin_trap(); @@ -134,18 +135,18 @@ string::append(char ch) noexcept if (ckd_add(&n2, size(), 2)) __builtin_trap(); if (n2 > capacity()) { - size_t c2 = capacity() + 2; + size_t c2 = capacity(); if (ckd_add(&c2, c2, c2 >> 1)) __builtin_trap(); reserve(c2); } data()[size()] = ch; - data()[size() + 1] = 0; if (isbig()) { ++big()->n; } else { --small()->rem; } + data()[size()] = 0; } void diff --git a/ctl/string.h b/ctl/string.h index 858b7a224..c830fdf12 100644 --- a/ctl/string.h +++ b/ctl/string.h @@ -151,7 +151,7 @@ class string if (isbig() && big()->c <= __::sso_max) __builtin_trap(); #endif - return isbig() ? __::big_mask & big()->c : __::sso_max; + return isbig() ? __::big_mask & big()->c : __::string_size; } iterator begin() noexcept diff --git a/test/ctl/string_test.cc b/test/ctl/string_test.cc index 1a35cfda3..81464b571 100644 --- a/test/ctl/string_test.cc +++ b/test/ctl/string_test.cc @@ -18,6 +18,7 @@ #include "ctl/string.h" +#include <__type_traits/is_same.h> #include <__utility/move.h> #include "libc/runtime/runtime.h" @@ -312,7 +313,7 @@ main() s.append(" world"); } if (s != "hello world world world world world world world world world " - "world world") { + "world world") { return 64; } } @@ -353,6 +354,33 @@ main() return 78; } + { + ctl::string s; +#undef ctl + if constexpr (std::is_same_v) { + // tests the small-string optimization on ctl::string + char* d = s.data(); + for (int i = 0; i < 23; ++i) { + s.append("a"); + if (s.data() != d) { + return 79 + i; + } + } + s.append("a"); + if (s.data() == d) { + return 103; + } + } else { + // just check that append in a loop works + for (int i = 0; i < 24; ++i) { + s.append("a"); + } + } + if (s != "aaaaaaaaaaaaaaaaaaaaaaaa") { + return 104; + } + } + CheckForMemoryLeaks(); return 0; }