mirror of https://github.com/python/cpython
Add optional 4th argument to [r]find and [r]index (end of slice).
This commit is contained in:
parent
612316f016
commit
7b7c578616
|
@ -103,24 +103,27 @@ This doesn't understand other non-printing characters or escape
|
||||||
sequences.
|
sequences.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{find}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{find}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Return the lowest index in \var{s} not smaller than \var{start} where the
|
Return the lowest index in \var{s} not smaller than \var{start} and not
|
||||||
substring \var{sub} is found. Return \code{-1} when \var{sub}
|
greater than \var{end} where the substring \var{sub} is found. Return
|
||||||
does not occur as a substring of \var{s} with index at least \var{start}.
|
\code{-1} when \var{sub} does not occur as a substring of \var{s} with
|
||||||
|
index at least \var{start} and less than \var{end}.
|
||||||
If \var{start} is omitted, it defaults to \code{0}. If \var{start} is
|
If \var{start} is omitted, it defaults to \code{0}. If \var{start} is
|
||||||
negative, \code{len(\var{s})} is added.
|
negative, \code{len(\var{s})} is added.
|
||||||
|
If \var{end} is omitted, it defaults to \code{len(\var{s})}. If
|
||||||
|
\var{end} is negative, \code{len(\var{s})} is added.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{rfind}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{rfind}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Like \code{find} but find the highest index.
|
Like \code{find} but find the highest index.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{index}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{index}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Like \code{find} but raise \code{ValueError} when the substring is
|
Like \code{find} but raise \code{ValueError} when the substring is
|
||||||
not found.
|
not found.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{rindex}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{rindex}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Like \code{rfind} but raise \code{ValueError} when the substring is
|
Like \code{rfind} but raise \code{ValueError} when the substring is
|
||||||
not found.
|
not found.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
|
@ -103,24 +103,27 @@ This doesn't understand other non-printing characters or escape
|
||||||
sequences.
|
sequences.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{find}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{find}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Return the lowest index in \var{s} not smaller than \var{start} where the
|
Return the lowest index in \var{s} not smaller than \var{start} and not
|
||||||
substring \var{sub} is found. Return \code{-1} when \var{sub}
|
greater than \var{end} where the substring \var{sub} is found. Return
|
||||||
does not occur as a substring of \var{s} with index at least \var{start}.
|
\code{-1} when \var{sub} does not occur as a substring of \var{s} with
|
||||||
|
index at least \var{start} and less than \var{end}.
|
||||||
If \var{start} is omitted, it defaults to \code{0}. If \var{start} is
|
If \var{start} is omitted, it defaults to \code{0}. If \var{start} is
|
||||||
negative, \code{len(\var{s})} is added.
|
negative, \code{len(\var{s})} is added.
|
||||||
|
If \var{end} is omitted, it defaults to \code{len(\var{s})}. If
|
||||||
|
\var{end} is negative, \code{len(\var{s})} is added.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{rfind}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{rfind}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Like \code{find} but find the highest index.
|
Like \code{find} but find the highest index.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{index}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{index}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Like \code{find} but raise \code{ValueError} when the substring is
|
Like \code{find} but raise \code{ValueError} when the substring is
|
||||||
not found.
|
not found.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{rindex}{s\, sub\optional{\, start}}
|
\begin{funcdesc}{rindex}{s\, sub\optional{\, start\optional{\,end}}}
|
||||||
Like \code{rfind} but raise \code{ValueError} when the substring is
|
Like \code{rfind} but raise \code{ValueError} when the substring is
|
||||||
not found.
|
not found.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
|
@ -120,15 +120,17 @@ def joinfields(words, sep = ' '):
|
||||||
return res[len(sep):]
|
return res[len(sep):]
|
||||||
|
|
||||||
# Find substring, raise exception if not found
|
# Find substring, raise exception if not found
|
||||||
def index(s, sub, i = 0):
|
def index(s, sub, i = 0, last=None):
|
||||||
res = find(s, sub, i)
|
if last == None: last = len(s)
|
||||||
|
res = find(s, sub, i, last)
|
||||||
if res < 0:
|
if res < 0:
|
||||||
raise ValueError, 'substring not found in string.index'
|
raise ValueError, 'substring not found in string.index'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# Find last substring, raise exception if not found
|
# Find last substring, raise exception if not found
|
||||||
def rindex(s, sub, i = 0):
|
def rindex(s, sub, i = 0, last=None):
|
||||||
res = rfind(s, sub, i)
|
if last == None: last = len(s)
|
||||||
|
res = rfind(s, sub, i, last)
|
||||||
if res < 0:
|
if res < 0:
|
||||||
raise ValueError, 'substring not found in string.index'
|
raise ValueError, 'substring not found in string.index'
|
||||||
return res
|
return res
|
||||||
|
@ -149,20 +151,34 @@ def count(s, sub, i = 0):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
# Find substring, return -1 if not found
|
# Find substring, return -1 if not found
|
||||||
def find(s, sub, i = 0):
|
def find(s, sub, i = 0, last=None):
|
||||||
if i < 0: i = max(0, i + len(s))
|
Slen = len(s) # cache this value, for speed
|
||||||
|
if last == None:
|
||||||
|
last = Slen
|
||||||
|
elif last < 0:
|
||||||
|
last = max(0, last + Slen)
|
||||||
|
elif last > Slen:
|
||||||
|
last = Slen
|
||||||
|
if i < 0: i = max(0, i + Slen)
|
||||||
n = len(sub)
|
n = len(sub)
|
||||||
m = len(s) + 1 - n
|
m = last + 1 - n
|
||||||
while i < m:
|
while i < m:
|
||||||
if sub == s[i:i+n]: return i
|
if sub == s[i:i+n]: return i
|
||||||
i = i+1
|
i = i+1
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
# Find last substring, return -1 if not found
|
# Find last substring, return -1 if not found
|
||||||
def rfind(s, sub, i = 0):
|
def rfind(s, sub, i = 0, last=None):
|
||||||
if i < 0: i = max(0, i + len(s))
|
Slen = len(s) # cache this value, for speed
|
||||||
|
if last == None:
|
||||||
|
last = Slen
|
||||||
|
elif last < 0:
|
||||||
|
last = max(0, last + Slen)
|
||||||
|
elif last > Slen:
|
||||||
|
last = Slen
|
||||||
|
if i < 0: i = max(0, i + Slen)
|
||||||
n = len(sub)
|
n = len(sub)
|
||||||
m = len(s) + 1 - n
|
m = last + 1 - n
|
||||||
r = -1
|
r = -1
|
||||||
while i < m:
|
while i < m:
|
||||||
if sub == s[i:i+n]: r = i
|
if sub == s[i:i+n]: r = i
|
||||||
|
|
|
@ -120,15 +120,17 @@ def joinfields(words, sep = ' '):
|
||||||
return res[len(sep):]
|
return res[len(sep):]
|
||||||
|
|
||||||
# Find substring, raise exception if not found
|
# Find substring, raise exception if not found
|
||||||
def index(s, sub, i = 0):
|
def index(s, sub, i = 0, last=None):
|
||||||
res = find(s, sub, i)
|
if last == None: last = len(s)
|
||||||
|
res = find(s, sub, i, last)
|
||||||
if res < 0:
|
if res < 0:
|
||||||
raise ValueError, 'substring not found in string.index'
|
raise ValueError, 'substring not found in string.index'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# Find last substring, raise exception if not found
|
# Find last substring, raise exception if not found
|
||||||
def rindex(s, sub, i = 0):
|
def rindex(s, sub, i = 0, last=None):
|
||||||
res = rfind(s, sub, i)
|
if last == None: last = len(s)
|
||||||
|
res = rfind(s, sub, i, last)
|
||||||
if res < 0:
|
if res < 0:
|
||||||
raise ValueError, 'substring not found in string.index'
|
raise ValueError, 'substring not found in string.index'
|
||||||
return res
|
return res
|
||||||
|
@ -149,20 +151,34 @@ def count(s, sub, i = 0):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
# Find substring, return -1 if not found
|
# Find substring, return -1 if not found
|
||||||
def find(s, sub, i = 0):
|
def find(s, sub, i = 0, last=None):
|
||||||
if i < 0: i = max(0, i + len(s))
|
Slen = len(s) # cache this value, for speed
|
||||||
|
if last == None:
|
||||||
|
last = Slen
|
||||||
|
elif last < 0:
|
||||||
|
last = max(0, last + Slen)
|
||||||
|
elif last > Slen:
|
||||||
|
last = Slen
|
||||||
|
if i < 0: i = max(0, i + Slen)
|
||||||
n = len(sub)
|
n = len(sub)
|
||||||
m = len(s) + 1 - n
|
m = last + 1 - n
|
||||||
while i < m:
|
while i < m:
|
||||||
if sub == s[i:i+n]: return i
|
if sub == s[i:i+n]: return i
|
||||||
i = i+1
|
i = i+1
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
# Find last substring, return -1 if not found
|
# Find last substring, return -1 if not found
|
||||||
def rfind(s, sub, i = 0):
|
def rfind(s, sub, i = 0, last=None):
|
||||||
if i < 0: i = max(0, i + len(s))
|
Slen = len(s) # cache this value, for speed
|
||||||
|
if last == None:
|
||||||
|
last = Slen
|
||||||
|
elif last < 0:
|
||||||
|
last = max(0, last + Slen)
|
||||||
|
elif last > Slen:
|
||||||
|
last = Slen
|
||||||
|
if i < 0: i = max(0, i + Slen)
|
||||||
n = len(sub)
|
n = len(sub)
|
||||||
m = len(s) + 1 - n
|
m = last + 1 - n
|
||||||
r = -1
|
r = -1
|
||||||
while i < m:
|
while i < m:
|
||||||
if sub == s[i:i+n]: r = i
|
if sub == s[i:i+n]: r = i
|
||||||
|
|
|
@ -33,6 +33,12 @@ PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIMITS_H
|
||||||
|
#include <limits.h>
|
||||||
|
#else
|
||||||
|
#define INT_MAX 2147483647
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
/* XXX This file assumes that the <ctype.h> is*() functions
|
/* XXX This file assumes that the <ctype.h> is*() functions
|
||||||
XXX are defined for all 8-bit characters! */
|
XXX are defined for all 8-bit characters! */
|
||||||
|
@ -286,11 +292,17 @@ strop_find(self, args)
|
||||||
PyObject *args;
|
PyObject *args;
|
||||||
{
|
{
|
||||||
char *s, *sub;
|
char *s, *sub;
|
||||||
int len, n, i = 0;
|
int len, n, i = 0, last = INT_MAX;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#s#|i", &s, &len, &sub, &n, &i))
|
if (!PyArg_ParseTuple(args, "s#s#|ii", &s, &len, &sub, &n, &i, &last))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (last > len)
|
||||||
|
last = len;
|
||||||
|
if (last < 0)
|
||||||
|
last += len;
|
||||||
|
if (last < 0)
|
||||||
|
last = 0;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i += len;
|
i += len;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
@ -299,8 +311,8 @@ strop_find(self, args)
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return PyInt_FromLong((long)i);
|
return PyInt_FromLong((long)i);
|
||||||
|
|
||||||
len -= n;
|
last -= n;
|
||||||
for (; i <= len; ++i)
|
for (; i <= last; ++i)
|
||||||
if (s[i] == sub[0] &&
|
if (s[i] == sub[0] &&
|
||||||
(n == 1 || memcmp(&s[i+1], &sub[1], n-1) == 0))
|
(n == 1 || memcmp(&s[i+1], &sub[1], n-1) == 0))
|
||||||
return PyInt_FromLong((long)i);
|
return PyInt_FromLong((long)i);
|
||||||
|
@ -316,20 +328,26 @@ strop_rfind(self, args)
|
||||||
{
|
{
|
||||||
char *s, *sub;
|
char *s, *sub;
|
||||||
int len, n, j;
|
int len, n, j;
|
||||||
int i = 0;
|
int i = 0, last = INT_MAX;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#s#|i", &s, &len, &sub, &n, &i))
|
if (!PyArg_ParseTuple(args, "s#s#|ii", &s, &len, &sub, &n, &i, &last))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (last > len)
|
||||||
|
last = len;
|
||||||
|
if (last < 0)
|
||||||
|
last += len;
|
||||||
|
if (last < 0)
|
||||||
|
last = 0;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i += len;
|
i += len;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return PyInt_FromLong((long)len);
|
return PyInt_FromLong((long)last);
|
||||||
|
|
||||||
for (j = len-n; j >= i; --j)
|
for (j = last-n; j >= i; --j)
|
||||||
if (s[j] == sub[0] &&
|
if (s[j] == sub[0] &&
|
||||||
(n == 1 || memcmp(&s[j+1], &sub[1], n-1) == 0))
|
(n == 1 || memcmp(&s[j+1], &sub[1], n-1) == 0))
|
||||||
return PyInt_FromLong((long)j);
|
return PyInt_FromLong((long)j);
|
||||||
|
@ -663,7 +681,7 @@ strop_atof(self, args)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
PyFPE_START_PROTECT("strop_atof", return 0)
|
PyFPE_START_PROTECT("strop_atof", return 0)
|
||||||
x = strtod(s, &end);
|
x = strtod(s, &end);
|
||||||
PyFPE_END_PROTECT
|
PyFPE_END_PROTECT(x)
|
||||||
while (*end && isspace(Py_CHARMASK(*end)))
|
while (*end && isspace(Py_CHARMASK(*end)))
|
||||||
end++;
|
end++;
|
||||||
if (*end != '\0') {
|
if (*end != '\0') {
|
||||||
|
|
Loading…
Reference in New Issue