8000 py: add String.find · go-python/gpython@ab6c445 · GitHub
[go: up one dir, main page]

Skip to content

Commit ab6c445

Browse files
committed
py: add String.find
Updates #139. Signed-off-by: Sebastien Binet <binet@cern.ch>
1 parent 6c9f9e5 commit ab6c445

File tree

2 files changed

+142
-26
lines changed

2 files changed

+142
-26
lines changed

py/string.go

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,43 @@ func fieldsN(s string, n int) []string {
122122
}
123123

124124
func init() {
125+
StringType.Dict["endswith"] = MustNewMethod("endswith", func(self Object, args Tuple) (Object, error) {
126+
selfStr := string(self.(String))
127+
suffix := []string{}
128+
if len(args) > 0 {
129+
if s, ok := args[0].(String); ok {
130+
suffix = append(suffix, string(s))
131+
} else if s, ok := args[0].(Tuple); ok {
132+
for _, t := range s {
133+
if v, ok := t.(String); ok {
134+
suffix = append(suffix, string(v))
135+
}
136+
}
137+
} else {
138+
return nil, ExceptionNewf(TypeError, "endswith first arg must be str, unicode, or tuple, not %s", args[0].Type())
139+
}
140+
} else {
141+
return nil, ExceptionNewf(TypeError, "endswith() takes at least 1 argument (0 given)")
142+
}
143+
for _, s := range suffix {
144+
if strings.HasSuffix(selfStr, s) {
145+
return Bool(true), nil
146+
}
147+
}
148+
return Bool(false), nil
149+
}, 0, "endswith(suffix[, start[, end]]) -> bool")
150+
151+
StringType.Dict["find"] = MustNewMethod("find", func(self Object, args Tuple) (Object, error) {
152+
return self.(String).find(args)
153+
}, 0, `find(...)
154+
S.find(sub[, start[, end]]) -> int
155+
156+
Return the lowest index in S where substring sub is found,
157+
such that sub is contained within S[start:end]. Optional
158+
arguments start and end are interpreted as in slice notation.
159+
160+
Return -1 on failure.`)
161+
125162
StringType.Dict["replace"] = MustNewMethod("replace", func(self Object, args Tuple) (Object, error) {
126163
return self.(String).Replace(args)
127164
}, 0, `replace(self, old, new, count=-1) -> return a copy with all occurrences of substring old replaced by new.
@@ -169,32 +206,6 @@ replaced.`)
169206
return Bool(false), nil
170207
}, 0, "startswith(prefix[, start[, end]]) -> bool")
171208

172-
StringType.Dict["endswith"] = MustNewMethod("endswith", func(self Object, args Tuple) (Object, error) {
173-
selfStr := string(self.(String))
174-
suffix := []string{}
175-
if len(args) > 0 {
176-
if s, ok := args[0].(String); ok {
177-
suffix = append(suffix, string(s))
178-
} else if s, ok := args[0].(Tuple); ok {
179-
for _, t := range s {
180-
if v, ok := t.(String); ok {
181-
suffix = append(suffix, string(v))
182-
}
183-
}
184-
} else {
185-
return nil, ExceptionNewf(TypeError, "endswith first arg must be str, unicode, or tuple, not %s", args[0].Type())
186-
}
187-
} else {
188-
return nil, ExceptionNewf(TypeError, "endswith() takes at least 1 argument (0 given)")
189-
}
190-
for _, s := range suffix {
191-
if strings.HasSuffix(selfStr, s) {
192-
return Bool(true), nil
193-
}
194-
}
195-
return Bool(false), nil
196-
}, 0, "endswith(suffix[, start[, end]]) -> bool")
197-
198209
}
199210

200211
// Type of this object
@@ -578,6 +589,32 @@ func (s String) M__contains__(item Object) (Object, error) {
578589
return NewBool(strings.Contains(string(s), string(needle))), nil
579590
}
580591

592+
func (s String) find(args Tuple) (Object, error) {
593+
var (
594+
pysub Object
595+
pybeg Object = Int(0)
596+
pyend Object = Int(len(s))
597+
pyfmt = "s|ii:find"
598+
)
599+
err := ParseTuple(args, pyfmt, &pysub, &pybeg, &pyend)
600+
if err != nil {
601+
return nil, err
602+
}
603+
604+
var (
605+
beg = int(pybeg.(Int))
606+
end = int(pyend.(Int))
607+
off = s.slice(0, beg, s.len()).len()
608+
str = string(s.slice(beg, end, s.len()))
609+
sub = string(pysub.(String))
610+
idx = strings.Index(str, sub)
611+
)
612+
if idx < 0 {
613+
return Int(idx), nil
614+
}
615+
return Int(off + String(str[:idx]).len()), nil
616+
}
617+
581618
func (s String) Split(args Tuple, kwargs StringDict) (Object, error) {
582619
var (
583620
pyval Object = None

py/string_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2022 The go-python Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package py
6+
7+
import "testing"
8+
9+
func TestStringFind(t *testing.T) {
10+
for _, tc := range []struct {
11+
str string
12+
sub string
13+
beg int
14+
end int
15+
idx int
16+
}{
17+
{
18+
str: "hello world",
19+
sub: "world",
20+
idx: 6,
21+
},
22+
{
23+
str: "hello world",
24+
sub: "o",
25+
idx: 4,
26+
},
27+
{
28+
str: "hello world",
29+
sub: "o",
30+
beg: 5,
31+
idx: 7,
32+
},
33+
{
34+
str: "hello world",
35+
sub: "bye",
36+
idx: -1,
37+
},
38+
{
39+
str: "Hello, 世界",
40+
sub: "界",
41+
idx: 8,
42+
},
43+
{
44+
str: "01234 6789",
45+
sub: " ",
46+
beg: 6,
47+
idx: -1,
48+
},
49+
{
50+
str: "0123456789",
51+
sub: "6",
52+
beg: 1,
53+
end: 6,
54+
idx: -1,
55+
},
56+
{
57+
str: "0123456789",
58+
sub: "6",
59+
beg: 1,
60+
end: 7,
61+
idx: 6,
62+
},
63+
} {
64+
t.Run(tc.str+":"+tc.sub, func(t *testing.T) {
65+
beg := tc.beg
66+
end := tc.end
67+
if end == 0 {
68+
end = len(tc.str)
69+
}
70+
idx, err := String(tc.str).find(Tuple{String(tc.sub), Int(beg), Int(end)})
71+
if err != nil {
72+
t.Fatalf("invalid: %+v", err)
73+
}
74+
if got, want := int(idx.(Int)), tc.idx; got != want {
75+
t.Fatalf("got=%d, want=%d", got, want)
76+
}
77+
})
78+
}
79+
}

0 commit comments

Comments
 (0)
0