Skip to content

Commit

Permalink
Copy constructor makes small strings when it can
Browse files Browse the repository at this point in the history
We create a small string whenever it will fit, instead of only when r is
small. This is safe because we always memcpy the whole blob when we call
reserve, and optimizes the case when r has been truncated.

This also reworks the test to follow the idiom adopted elsewhere re stl,
and adds a helper function to tell if a string is small based on data().
  • Loading branch information
mrdomino committed Jun 19, 2024
1 parent d1b6715 commit e2f19d5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 8 deletions.
4 changes: 4 additions & 0 deletions ctl/string.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ void
string::init_big(const string& s) noexcept
{
char* p2;
#ifndef NDEBUG
if (!s.isbig())
__builtin_trap();
#endif
if (s.size() >= s.capacity() >> 1) {
if (!(p2 = (char*)malloc(s.capacity())))
__builtin_trap();
Expand Down
8 changes: 5 additions & 3 deletions ctl/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@ class string

string(const string& r) noexcept
{
if (r.isbig())
if (r.size() <= __::sso_max) {
__builtin_memcpy(blob, r.data(), __::string_size);
set_small_size(r.size());
} else {
init_big(r);
else
__builtin_memcpy(blob, r.blob, __::string_size);
}
}

string(const char* const p, const size_t n) noexcept
Expand Down
34 changes: 29 additions & 5 deletions test/ctl/string_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,19 @@
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"

using String = ctl::string;
// #include <string>
// using String = std::string;
// #define ctl std

using String = ctl::string;

#undef ctl

inline bool
issmall(const String& s)
{
return s.capacity() == sizeof(s) &&
s.data() == reinterpret_cast<const char*>(&s);
}

int
main()
Expand Down Expand Up @@ -358,15 +368,14 @@ main()
String s;
if constexpr (std::is_same_v<ctl::string, decltype(s)>) {
// 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) {
if (!issmall(s)) {
return 79 + i;
}
}
s.append("a");
if (s.data() == d) {
if (issmall(s)) {
return 103;
}
} else {
Expand All @@ -380,6 +389,21 @@ main()
}
}

{
String s("arst", 4);
for (int i = 0; i < 30; ++i) {
s.append("a");
}
s.resize(4);
if (s != "arst")
return 105;
if constexpr (std::is_same_v<ctl::string, decltype(s)>) {
String r(s);
if (issmall(s) || !issmall(r))
return 106;
}
}

CheckForMemoryLeaks();
return 0;
}

0 comments on commit e2f19d5

Please sign in to comment.