[Python-checkins] r46388 - python/trunk/Objects/stringobject.c
andrew.dalke
python-checkins at python.org
Fri May 26 21:02:11 CEST 2006
Author: andrew.dalke
Date: Fri May 26 21:02:09 2006
New Revision: 46388
Modified:
python/trunk/Objects/stringobject.c
Log:
substring split now uses /F's fast string matching algorithm.
(If compiled without FAST search support, changed the pre-memcmp test
to check the last character as well as the first. This gave a 25%
speedup for my test case.)
Rewrote the split algorithms so they stop when maxsplit gets to 0.
Previously they did a string match first then checked if the maxsplit
was reached. The new way prevents a needless string search.
Modified: python/trunk/Objects/stringobject.c
==============================================================================
--- python/trunk/Objects/stringobject.c (original)
+++ python/trunk/Objects/stringobject.c Fri May 26 21:02:09 2006
@@ -1322,6 +1322,13 @@
#define STRIPNAME(i) (stripformat[i]+3)
+/* Don't call if length < 2 */
+#define Py_STRING_MATCH(target, offset, pattern, length) \
+ (target[offset] == pattern[0] && \
+ target[offset+length-1] == pattern[length-1] && \
+ !memcmp(target+offset+1, pattern+1, length-2) )
+
+
/* Overallocate the initial list to reduce the number of reallocs for small
split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three
resizes, to sizes 4, 8, then 16. Most observed string splits are for human
@@ -1416,18 +1423,19 @@
if (list == NULL)
return NULL;
- for (i = j = 0; i < len; ) {
- /* TODO: Use findchar/memchr for this? */
- if (s[i] == ch) {
- if (maxcount-- <= 0)
+ i = j = 0;
+ while ((j < len) && (maxcount-- > 0)) {
+ for(; j<len; j++) {
+ /* I found that using memchr makes no difference */
+ if (s[j] == ch) {
+ SPLIT_ADD(s, i, j);
+ i = j = j + 1;
break;
- SPLIT_ADD(s, j, i);
- i = j = i + 1;
- } else
- i++;
+ }
+ }
}
- if (j <= len) {
- SPLIT_ADD(s, j, len);
+ if (i <= len) {
+ SPLIT_ADD(s, i, len);
}
FIX_PREALLOC_SIZE(list);
return list;
@@ -1452,6 +1460,9 @@
Py_ssize_t maxsplit = -1, count=0;
const char *s = PyString_AS_STRING(self), *sub;
PyObject *list, *str, *subobj = Py_None;
+#ifdef USE_FAST
+ Py_ssize_t pos;
+#endif
if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit))
return NULL;
@@ -1481,19 +1492,30 @@
if (list == NULL)
return NULL;
+#ifdef USE_FAST
+ i = j = 0;
+ while (maxsplit-- > 0) {
+ pos = fastsearch(s+i, len-i, sub, n, FAST_SEARCH);
+ if (pos < 0)
+ break;
+ j = i+pos;
+ SPLIT_ADD(s, i, j);
+ i = j + n;
+
+ }
+#else
i = j = 0;
- while (i+n <= len) {
- /* TODO: Use Py_STRING_MATCH */
- if (s[i] == sub[0] && memcmp(s+i, sub, n) == 0) {
- if (maxsplit-- <= 0)
+ while ((j+n <= len) && (maxsplit-- > 0)) {
+ for (; j+n <= len; j++) {
+ if (Py_STRING_MATCH(s, j, sub, n)) {
+ SPLIT_ADD(s, i, j);
+ i = j = j + n;
break;
- SPLIT_ADD(s, j, i);
- i = j = i + n;
+ }
}
- else
- i++;
}
- SPLIT_ADD(s, j, len);
+#endif
+ SPLIT_ADD(s, i, len);
FIX_PREALLOC_SIZE(list);
return list;
@@ -1610,14 +1632,15 @@
if (list == NULL)
return NULL;
- for (i = j = len - 1; i >= 0; ) {
- if (s[i] == ch) {
- if (maxcount-- <= 0)
+ i = j = len - 1;
+ while ((i >= 0) && (maxcount-- > 0)) {
+ for (; i >= 0; i--) {
+ if (s[i] == ch) {
+ SPLIT_ADD(s, i + 1, j + 1);
+ j = i = i - 1;
break;
- SPLIT_ADD(s, i + 1, j + 1);
- j = i = i - 1;
- } else
- i--;
+ }
+ }
}
if (j >= -1) {
SPLIT_ADD(s, 0, j + 1);
@@ -1679,16 +1702,16 @@
j = len;
i = j - n;
- while (i >= 0) {
- if (s[i] == sub[0] && memcmp(s+i, sub, n) == 0) {
- if (maxsplit-- <= 0)
+
+ while ( (i >= 0) && (maxsplit-- > 0) ) {
+ for (; i>=0; i--) {
+ if (Py_STRING_MATCH(s, i, sub, n)) {
+ SPLIT_ADD(s, i + n, j);
+ j = i;
+ i -= n;
break;
- SPLIT_ADD(s, i+n, j);
- j = i;
- i -= n;
+ }
}
- else
- i--;
}
SPLIT_ADD(s, 0, j);
FIX_PREALLOC_SIZE(list);
@@ -2449,12 +2472,6 @@
/* find and count characters and substrings */
-/* Don't call if length < 2 */
-#define Py_STRING_MATCH(target, offset, pattern, length) \
- (target[offset] == pattern[0] && \
- target[offset+length-1] == pattern[length-1] && \
- !memcmp(target+offset+1, pattern+1, length-2) )
-
#define findchar(target, target_len, c) \
((char *)memchr((const void *)(target), c, target_len))
More information about the Python-checkins
mailing list