Skip to content

Commit beb090b

Browse files
committed
Add ctl string find_first_of and find_last_of
1 parent 107d335 commit beb090b

File tree

6 files changed

+244
-0
lines changed

6 files changed

+244
-0
lines changed

ctl/string.cc

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,4 +389,66 @@ string::append(const ctl::string_view& s, size_t pos, size_t count) noexcept
389389
append(s.substr(pos, count));
390390
}
391391

392+
size_t
393+
string::find_last_of(char c, size_t pos) const noexcept
394+
{
395+
const char* b = data();
396+
size_t n = size();
397+
if (pos > n)
398+
pos = n;
399+
const char* p = (const char*)memrchr(b, c, pos);
400+
return p ? p - b : npos;
401+
}
402+
403+
size_t
404+
string::find_last_of(ctl::string_view set, size_t pos) const noexcept
405+
{
406+
if (empty() || set.empty())
407+
return npos;
408+
bool lut[256] = {};
409+
for (char c : set)
410+
lut[c & 255] = true;
411+
const char* b = data();
412+
size_t last = size() - 1;
413+
if (pos > last)
414+
pos = last;
415+
for (;;) {
416+
if (lut[b[pos] & 255])
417+
return pos;
418+
if (!pos)
419+
return npos;
420+
--pos;
421+
}
422+
}
423+
424+
size_t
425+
string::find_first_of(char c, size_t pos) const noexcept
426+
{
427+
size_t n = size();
428+
if (pos >= n)
429+
return npos;
430+
const char* b = data();
431+
const char* p = (const char*)memchr(b + pos, c, n - pos);
432+
return p ? p - b : npos;
433+
}
434+
435+
size_t
436+
string::find_first_of(ctl::string_view set, size_t pos) const noexcept
437+
{
438+
if (set.empty())
439+
return npos;
440+
bool lut[256] = {};
441+
for (char c : set)
442+
lut[c & 255] = true;
443+
const char* b = data();
444+
size_t n = size();
445+
for (;;) {
446+
if (pos >= n)
447+
return npos;
448+
if (lut[b[pos] & 255])
449+
return pos;
450+
++pos;
451+
}
452+
}
453+
392454
} // namespace ctl

ctl/string.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ class string
137137
bool starts_with(ctl::string_view) const noexcept;
138138
size_t find(char, size_t = 0) const noexcept;
139139
size_t find(ctl::string_view, size_t = 0) const noexcept;
140+
size_t find_first_of(char, size_t = 0) const noexcept;
141+
size_t find_first_of(ctl::string_view, size_t = 0) const noexcept;
142+
size_t find_last_of(char, size_t = npos) const noexcept;
143+
size_t find_last_of(ctl::string_view, size_t = npos) const noexcept;
140144

141145
void swap(string& s) noexcept
142146
{

ctl/string_view.cc

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,66 @@ string_view::starts_with(const string_view s) const noexcept
108108
return !memcmp(p, s.p, s.n);
109109
}
110110

111+
size_t
112+
string_view::find_last_of(char c, size_t pos) const noexcept
113+
{
114+
const char* b = data();
115+
size_t n = size();
116+
if (pos > n)
117+
pos = n;
118+
const char* p = (const char*)memrchr(b, c, pos);
119+
return p ? p - b : npos;
120+
}
121+
122+
size_t
123+
string_view::find_last_of(ctl::string_view set, size_t pos) const noexcept
124+
{
125+
if (empty() || set.empty())
126+
return npos;
127+
bool lut[256] = {};
128+
for (char c : set)
129+
lut[c & 255] = true;
130+
const char* b = data();
131+
size_t last = size() - 1;
132+
if (pos > last)
133+
pos = last;
134+
for (;;) {
135+
if (lut[b[pos] & 255])
136+
return pos;
137+
if (!pos)
138+
return npos;
139+
--pos;
140+
}
141+
}
142+
143+
size_t
144+
string_view::find_first_of(char c, size_t pos) const noexcept
145+
{
146+
size_t n = size();
147+
if (pos >= n)
148+
return npos;
149+
const char* b = data();
150+
const char* p = (const char*)memchr(b + pos, c, n - pos);
151+
return p ? p - b : npos;
152+
}
153+
154+
size_t
155+
string_view::find_first_of(ctl::string_view set, size_t pos) const noexcept
156+
{
157+
if (set.empty())
158+
return npos;
159+
bool lut[256] = {};
160+
for (char c : set)
161+
lut[c & 255] = true;
162+
const char* b = data();
163+
size_t n = size();
164+
for (;;) {
165+
if (pos >= n)
166+
return npos;
167+
if (lut[b[pos] & 255])
168+
return pos;
169+
++pos;
170+
}
171+
}
172+
111173
} // namespace ctl

ctl/string_view.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ struct string_view
4545
string_view substr(size_t = 0, size_t = npos) const noexcept;
4646
size_t find(char, size_t = 0) const noexcept;
4747
size_t find(string_view, size_t = 0) const noexcept;
48+
size_t find_first_of(char, size_t = 0) const noexcept;
49+
size_t find_first_of(ctl::string_view, size_t = 0) const noexcept;
50+
size_t find_last_of(char, size_t = npos) const noexcept;
51+
size_t find_last_of(ctl::string_view, size_t = npos) const noexcept;
4852

4953
constexpr string_view& operator=(const string_view s) noexcept
5054
{

test/ctl/string_test.cc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,5 +412,61 @@ main()
412412
return 107;
413413
}
414414

415+
{
416+
String s = "ee";
417+
if (s.find_last_of('E') != String::npos)
418+
return 108;
419+
if (s.find_last_of('e') != 1)
420+
return 109;
421+
}
422+
423+
{
424+
String e = "";
425+
String s = "ee";
426+
if (e.find_last_of("") != String::npos)
427+
return 110;
428+
if (s.find_last_of("") != String::npos)
429+
return 111;
430+
if (s.find_last_of("AE") != String::npos)
431+
return 112;
432+
if (s.find_last_of("ae") != 1)
433+
return 113;
434+
if (s.find_last_of("ae", 1) != 1)
435+
return 114;
436+
if (s.find_last_of("ae", 0) != 0)
437+
return 115;
438+
if (s.find_last_of("ae", 10) != 1)
439+
return 116;
440+
}
441+
442+
{
443+
String s = "ee";
444+
if (s.find_first_of('E') != String::npos)
445+
return 117;
446+
if (s.find_first_of('e') != 0)
447+
return 118;
448+
if (s.find_first_of('e', 1) != 1)
449+
return 119;
450+
}
451+
452+
{
453+
String e = "";
454+
String s = "ee";
455+
if (e.find_first_of("") != String::npos)
456+
return 120;
457+
if (s.find_first_of("") != String::npos)
458+
return 121;
459+
if (s.find_first_of("AE") != String::npos)
460+
return 122;
461+
if (s.find_first_of("ae") != 0)
462+
return 123;
463+
if (s.find_first_of("ae", 1) != 1)
464+
return 124;
465+
if (s.find_first_of("ae", 0) != 0)
466+
return 125;
467+
if (s.find_first_of("ae", 10) != String::npos)
468+
return 126;
469+
}
470+
415471
CheckForMemoryLeaks();
416472
}

test/ctl/string_view_test.cc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,5 +182,61 @@ main(int argc, char* argv[])
182182
return 2;
183183
}
184184

185+
{
186+
ctl::string_view s = "ee";
187+
if (s.find_last_of('E') != ctl::string_view::npos)
188+
return 108;
189+
if (s.find_last_of('e') != 1)
190+
return 109;
191+
}
192+
193+
{
194+
ctl::string_view e = "";
195+
ctl::string_view s = "ee";
196+
if (e.find_last_of("") != ctl::string_view::npos)
197+
return 110;
198+
if (s.find_last_of("") != ctl::string_view::npos)
199+
return 111;
200+
if (s.find_last_of("AE") != ctl::string_view::npos)
201+
return 112;
202+
if (s.find_last_of("ae") != 1)
203+
return 113;
204+
if (s.find_last_of("ae", 1) != 1)
205+
return 114;
206+
if (s.find_last_of("ae", 0) != 0)
207+
return 115;
208+
if (s.find_last_of("ae", 10) != 1)
209+
return 116;
210+
}
211+
212+
{
213+
ctl::string_view s = "ee";
214+
if (s.find_first_of('E') != ctl::string_view::npos)
215+
return 117;
216+
if (s.find_first_of('e') != 0)
217+
return 118;
218+
if (s.find_first_of('e', 1) != 1)
219+
return 119;
220+
}
221+
222+
{
223+
ctl::string_view e = "";
224+
ctl::string_view s = "ee";
225+
if (e.find_first_of("") != ctl::string_view::npos)
226+
return 120;
227+
if (s.find_first_of("") != ctl::string_view::npos)
228+
return 121;
229+
if (s.find_first_of("AE") != ctl::string_view::npos)
230+
return 122;
231+
if (s.find_first_of("ae") != 0)
232+
return 123;
233+
if (s.find_first_of("ae", 1) != 1)
234+
return 124;
235+
if (s.find_first_of("ae", 0) != 0)
236+
return 125;
237+
if (s.find_first_of("ae", 10) != ctl::string_view::npos)
238+
return 126;
239+
}
240+
185241
CheckForMemoryLeaks();
186242
}

0 commit comments

Comments
 (0)