mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-30 19:17:36 +00:00
Add ctl string find_first_of and find_last_of
This commit is contained in:
parent
107d335c0d
commit
beb090b83f
6 changed files with 244 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue