Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 57e7447

Browse files
committed
* Beef-up tests for str.count().
* Speed-up str.count() by using memchr() to fly between first char matches.
1 parent 7cbf1bc commit 57e7447

2 files changed

Lines changed: 35 additions & 2 deletions

File tree

Lib/test/string_tests.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,33 @@ def test_count(self):
114114
self.checkraises(TypeError, 'hello', 'count')
115115
self.checkraises(TypeError, 'hello', 'count', 42)
116116

117+
# For a variety of combinations,
118+
# verify that str.count() matches an equivalent function
119+
# replacing all occurrences and then differencing the string lengths
120+
charset = ['', 'a', 'b']
121+
digits = 7
122+
base = len(charset)
123+
teststrings = set()
124+
for i in xrange(base ** digits):
125+
entry = []
126+
for j in xrange(digits):
127+
i, m = divmod(i, base)
128+
entry.append(charset[m])
129+
teststrings.add(''.join(entry))
130+
teststrings = list(teststrings)
131+
for i in teststrings:
132+
i = self.fixtype(i)
133+
n = len(i)
134+
for j in teststrings:
135+
r1 = i.count(j)
136+
if j:
137+
r2, rem = divmod(n - len(i.replace(j, '')), len(j))
138+
else:
139+
r2, rem = len(i)+1, 0
140+
if rem or r1 != r2:
141+
self.assertEqual(rem, 0)
142+
self.assertEqual(r1, r2)
143+
117144
def test_find(self):
118145
self.checkequal(0, 'abcdefghiabc', 'find', 'abc')
119146
self.checkequal(9, 'abcdefghiabc', 'find', 'abc', 1)
@@ -135,6 +162,7 @@ def test_find(self):
135162
i, m = divmod(i, base)
136163
entry.append(charset[m])
137164
teststrings.add(''.join(entry))
165+
teststrings = list(teststrings)
138166
for i in teststrings:
139167
i = self.fixtype(i)
140168
for j in teststrings:

Objects/stringobject.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,7 +2145,7 @@ interpreted as in slice notation.");
21452145
static PyObject *
21462146
string_count(PyStringObject *self, PyObject *args)
21472147
{
2148-
const char *s = PyString_AS_STRING(self), *sub;
2148+
const char *s = PyString_AS_STRING(self), *sub, *t;
21492149
int len = PyString_GET_SIZE(self), n;
21502150
int i = 0, last = INT_MAX;
21512151
int m, r;
@@ -2186,11 +2186,16 @@ string_count(PyStringObject *self, PyObject *args)
21862186
} else {
21872187
i++;
21882188
}
2189+
if (i >= m)
2190+
break;
2191+
t = memchr(s+i, sub[0], m-i);
2192+
if (t == NULL)
2193+
break;
2194+
i = t - s;
21892195
}
21902196
return PyInt_FromLong((long) r);
21912197
}
21922198

2193-
21942199
PyDoc_STRVAR(swapcase__doc__,
21952200
"S.swapcase() -> string\n\
21962201
\n\

0 commit comments

Comments
 (0)