Skip to content

Commit

Permalink
Add ctl string find_first_of and find_last_of
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Nov 1, 2024
1 parent 107d335 commit beb090b
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 0 deletions.
62 changes: 62 additions & 0 deletions ctl/string.cc
Original file line number Diff line number Diff line change
Expand Up @@ -389,4 +389,66 @@ string::append(const ctl::string_view& s, size_t pos, size_t count) noexcept
append(s.substr(pos, count));
}

size_t
string::find_last_of(char c, size_t pos) const noexcept
{
const char* b = data();
size_t n = size();
if (pos > n)
pos = n;
const char* p = (const char*)memrchr(b, c, pos);
return p ? p - b : npos;
}

size_t
string::find_last_of(ctl::string_view set, size_t pos) const noexcept
{
if (empty() || set.empty())
return npos;
bool lut[256] = {};
for (char c : set)
lut[c & 255] = true;
const char* b = data();
size_t last = size() - 1;
if (pos > last)
pos = last;
for (;;) {
if (lut[b[pos] & 255])
return pos;
if (!pos)
return npos;
--pos;
}
}

size_t
string::find_first_of(char c, size_t pos) const noexcept
{
size_t n = size();
if (pos >= n)
return npos;
const char* b = data();
const char* p = (const char*)memchr(b + pos, c, n - pos);
return p ? p - b : npos;
}

size_t
string::find_first_of(ctl::string_view set, size_t pos) const noexcept
{
if (set.empty())
return npos;
bool lut[256] = {};
for (char c : set)
lut[c & 255] = true;
const char* b = data();
size_t n = size();
for (;;) {
if (pos >= n)
return npos;
if (lut[b[pos] & 255])
return pos;
++pos;
}
}

} // namespace ctl
4 changes: 4 additions & 0 deletions ctl/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ class string
bool starts_with(ctl::string_view) const noexcept;
size_t find(char, size_t = 0) const noexcept;
size_t find(ctl::string_view, size_t = 0) const noexcept;
size_t find_first_of(char, size_t = 0) const noexcept;
size_t find_first_of(ctl::string_view, size_t = 0) const noexcept;
size_t find_last_of(char, size_t = npos) const noexcept;
size_t find_last_of(ctl::string_view, size_t = npos) const noexcept;

void swap(string& s) noexcept
{
Expand Down
62 changes: 62 additions & 0 deletions ctl/string_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,66 @@ string_view::starts_with(const string_view s) const noexcept
return !memcmp(p, s.p, s.n);
}

size_t
string_view::find_last_of(char c, size_t pos) const noexcept
{
const char* b = data();
size_t n = size();
if (pos > n)
pos = n;
const char* p = (const char*)memrchr(b, c, pos);
return p ? p - b : npos;
}

size_t
string_view::find_last_of(ctl::string_view set, size_t pos) const noexcept
{
if (empty() || set.empty())
return npos;
bool lut[256] = {};
for (char c : set)
lut[c & 255] = true;
const char* b = data();
size_t last = size() - 1;
if (pos > last)
pos = last;
for (;;) {
if (lut[b[pos] & 255])
return pos;
if (!pos)
return npos;
--pos;
}
}

size_t
string_view::find_first_of(char c, size_t pos) const noexcept
{
size_t n = size();
if (pos >= n)
return npos;
const char* b = data();
const char* p = (const char*)memchr(b + pos, c, n - pos);
return p ? p - b : npos;
}

size_t
string_view::find_first_of(ctl::string_view set, size_t pos) const noexcept
{
if (set.empty())
return npos;
bool lut[256] = {};
for (char c : set)
lut[c & 255] = true;
const char* b = data();
size_t n = size();
for (;;) {
if (pos >= n)
return npos;
if (lut[b[pos] & 255])
return pos;
++pos;
}
}

} // namespace ctl
4 changes: 4 additions & 0 deletions ctl/string_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ struct string_view
string_view substr(size_t = 0, size_t = npos) const noexcept;
size_t find(char, size_t = 0) const noexcept;
size_t find(string_view, size_t = 0) const noexcept;
size_t find_first_of(char, size_t = 0) const noexcept;
size_t find_first_of(ctl::string_view, size_t = 0) const noexcept;
size_t find_last_of(char, size_t = npos) const noexcept;
size_t find_last_of(ctl::string_view, size_t = npos) const noexcept;

constexpr string_view& operator=(const string_view s) noexcept
{
Expand Down
56 changes: 56 additions & 0 deletions test/ctl/string_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -412,5 +412,61 @@ main()
return 107;
}

{
String s = "ee";
if (s.find_last_of('E') != String::npos)
return 108;
if (s.find_last_of('e') != 1)
return 109;
}

{
String e = "";
String s = "ee";
if (e.find_last_of("") != String::npos)
return 110;
if (s.find_last_of("") != String::npos)
return 111;
if (s.find_last_of("AE") != String::npos)
return 112;
if (s.find_last_of("ae") != 1)
return 113;
if (s.find_last_of("ae", 1) != 1)
return 114;
if (s.find_last_of("ae", 0) != 0)
return 115;
if (s.find_last_of("ae", 10) != 1)
return 116;
}

{
String s = "ee";
if (s.find_first_of('E') != String::npos)
return 117;
if (s.find_first_of('e') != 0)
return 118;
if (s.find_first_of('e', 1) != 1)
return 119;
}

{
String e = "";
String s = "ee";
if (e.find_first_of("") != String::npos)
return 120;
if (s.find_first_of("") != String::npos)
return 121;
if (s.find_first_of("AE") != String::npos)
return 122;
if (s.find_first_of("ae") != 0)
return 123;
if (s.find_first_of("ae", 1) != 1)
return 124;
if (s.find_first_of("ae", 0) != 0)
return 125;
if (s.find_first_of("ae", 10) != String::npos)
return 126;
}

CheckForMemoryLeaks();
}
56 changes: 56 additions & 0 deletions test/ctl/string_view_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,61 @@ main(int argc, char* argv[])
return 2;
}

{
ctl::string_view s = "ee";
if (s.find_last_of('E') != ctl::string_view::npos)
return 108;
if (s.find_last_of('e') != 1)
return 109;
}

{
ctl::string_view e = "";
ctl::string_view s = "ee";
if (e.find_last_of("") != ctl::string_view::npos)
return 110;
if (s.find_last_of("") != ctl::string_view::npos)
return 111;
if (s.find_last_of("AE") != ctl::string_view::npos)
return 112;
if (s.find_last_of("ae") != 1)
return 113;
if (s.find_last_of("ae", 1) != 1)
return 114;
if (s.find_last_of("ae", 0) != 0)
return 115;
if (s.find_last_of("ae", 10) != 1)
return 116;
}

{
ctl::string_view s = "ee";
if (s.find_first_of('E') != ctl::string_view::npos)
return 117;
if (s.find_first_of('e') != 0)
return 118;
if (s.find_first_of('e', 1) != 1)
return 119;
}

{
ctl::string_view e = "";
ctl::string_view s = "ee";
if (e.find_first_of("") != ctl::string_view::npos)
return 120;
if (s.find_first_of("") != ctl::string_view::npos)
return 121;
if (s.find_first_of("AE") != ctl::string_view::npos)
return 122;
if (s.find_first_of("ae") != 0)
return 123;
if (s.find_first_of("ae", 1) != 1)
return 124;
if (s.find_first_of("ae", 0) != 0)
return 125;
if (s.find_first_of("ae", 10) != ctl::string_view::npos)
return 126;
}

CheckForMemoryLeaks();
}

0 comments on commit beb090b

Please sign in to comment.