Skip to content

Commit dc99668

Browse files
committed
feat(string): add find_by_charcode
1 parent bc2508d commit dc99668

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

string/methods.mbt

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ test "find" {
7171
///|
7272
/// Returns the offset of the first character that satisfies the given predicate.
7373
/// If no such character is found, it returns None.
74+
#locals(pred)
7475
pub fn View::find_by(self : View, pred : (Char) -> Bool) -> Int? {
7576
for i, c in self {
7677
if pred(c) {
@@ -83,8 +84,14 @@ pub fn View::find_by(self : View, pred : (Char) -> Bool) -> Int? {
8384
///|
8485
/// Returns the offset of the first character that satisfies the given predicate.
8586
/// If no such character is found, it returns None.
87+
#locals(pred)
8688
pub fn String::find_by(self : String, pred : (Char) -> Bool) -> Int? {
87-
self[:].find_by(pred)
89+
for i, c in self {
90+
if pred(c) {
91+
return Some(i)
92+
}
93+
}
94+
None
8895
}
8996

9097
///|
@@ -101,6 +108,90 @@ test "find_by" {
101108
inspect!("😀😁😂".find_by(fn(c) { c == '😂' }), content="Some(2)")
102109
}
103110

111+
///|
112+
/// Find the index of the first charcode that satisfies the given predicate.
113+
/// If no such charcode is found, it returns None.
114+
#locals(pred)
115+
pub fn View::find_by_charcode(self : View, pred : (Int) -> Bool) -> Int? {
116+
for i in 0..<self.length() {
117+
if pred(self.unsafe_charcode_at(i)) {
118+
return Some(i)
119+
}
120+
}
121+
None
122+
}
123+
124+
///|
125+
/// Find the index of the first charcode that satisfies the given predicate.
126+
/// If no such charcode is found, it returns None.
127+
#locals(pred)
128+
pub fn String::find_by_charcode(self : String, pred : (Int) -> Bool) -> Int? {
129+
for i in 0..<self.length() {
130+
if pred(self.unsafe_charcode_at(i)) {
131+
return Some(i)
132+
}
133+
}
134+
None
135+
}
136+
137+
///|
138+
test "find_by_charcode" {
139+
// Test basic character finding
140+
inspect!("hello".find_by_charcode(Int::op_equal(_, 'o')), content="Some(4)")
141+
inspect!("hello".find_by_charcode(Int::op_equal(_, 'l')), content="Some(2)")
142+
inspect!("hello".find_by_charcode(Int::op_equal(_, 'z')), content="None")
143+
inspect!(
144+
"hello"[1:].find_by_charcode(Int::op_equal(_, 'o')),
145+
content="Some(3)",
146+
)
147+
inspect!(
148+
"hello"[:4].find_by_charcode(Int::op_equal(_, 'o')),
149+
content="None",
150+
)
151+
inspect!("hello".find_by_charcode(Int::op_equal(_, 'z')), content="None")
152+
153+
// Test empty string
154+
inspect!("".find_by_charcode(Int::op_equal(_, 'a')), content="None")
155+
156+
// Test numeric characters
157+
inspect!(
158+
"hello".find_by_charcode(fn(c) { c >= '0' && c <= '9' }),
159+
content="None",
160+
)
161+
inspect!(
162+
"hello123".find_by_charcode(fn(c) { c >= '0' && c <= '9' }),
163+
content="Some(5)",
164+
)
165+
166+
// Test case sensitivity
167+
inspect!(
168+
"hello".find_by_charcode(fn(c) { c >= 'A' && c <= 'Z' }),
169+
content="None",
170+
)
171+
inspect!(
172+
"Hello".find_by_charcode(fn(c) { c >= 'A' && c <= 'Z' }),
173+
content="Some(0)",
174+
)
175+
176+
// Test non-ASCII characters
177+
inspect!("αβγ".find_by_charcode(fn(c) { c == 'β' }), content="Some(1)")
178+
179+
// Test emoji and multi-byte characters
180+
inspect!(
181+
"😀😁😂".find_by_charcode(fn(c) { c == 0xD83D }),
182+
content="Some(0)",
183+
) // First code unit of 😀
184+
185+
// Test specific code point ranges
186+
inspect!(
187+
"Hello, 世界!".find_by_charcode(fn(c) { c > 127 }),
188+
content="Some(7)",
189+
) // First non-ASCII character
190+
191+
// Test with complex predicate
192+
inspect!("a1b2c3".find_by_charcode(fn(c) { c % 2 == 0 }), content="Some(2)") // '1' has code 49 which is odd
193+
}
194+
104195
///|
105196
/// Returns the offset of the last occurrence of the given substring. If the
106197
/// substring is not found, it returns None.

string/string.mbti

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ impl StringView {
103103
contains_char(Self, Char) -> Bool
104104
find(Self, Self) -> Int?
105105
find_by(Self, (Char) -> Bool) -> Int?
106+
find_by_charcode(Self, (Int) -> Bool) -> Int?
106107
fold[A](Self, init~ : A, (A, Char) -> A) -> A
107108
from_array(Array[Char]) -> Self
108109
from_iter(Iter[Char]) -> Self
@@ -164,6 +165,7 @@ impl String {
164165
ends_with(String, String) -> Bool
165166
find(String, StringView) -> Int?
166167
find_by(String, (Char) -> Bool) -> Int?
168+
find_by_charcode(String, (Int) -> Bool) -> Int?
167169
fold[A](String, init~ : A, (A, Char) -> A) -> A
168170
from_array(Array[Char]) -> String
169171
from_iter(Iter[Char]) -> String

0 commit comments

Comments
 (0)