1248 lines · 27.8 KB · C
RawDownload
/* strop module */ #define PY_SSIZE_T_CLEAN#include "Python.h"#include <ctype.h> PyDoc_STRVAR(strop_module__doc__,"Common string manipulations, optimized for speed.\n""\n""Always use \"import string\" rather than referencing\n""this module directly."); /* XXX This file assumes that the <ctype.h> is*() functions   XXX are defined for all 8-bit characters! */ #define WARN if (PyErr_Warn(PyExc_DeprecationWarning, \		       "strop functions are obsolete; use string methods")) \	     return NULL /* The lstrip(), rstrip() and strip() functions are implemented   in do_strip(), which uses an additional parameter to indicate what   type of strip should occur. */ #define LEFTSTRIP 0#define RIGHTSTRIP 1#define BOTHSTRIP 2  static PyObject *split_whitespace(char *s, Py_ssize_t len, Py_ssize_t maxsplit){	Py_ssize_t i = 0, j;	int err;	Py_ssize_t countsplit = 0;	PyObject* item;	PyObject *list = PyList_New(0); 	if (list == NULL)		return NULL; 	while (i < len) {		while (i < len && isspace(Py_CHARMASK(s[i]))) {			i = i+1;		}		j = i;		while (i < len && !isspace(Py_CHARMASK(s[i]))) {			i = i+1;		}		if (j < i) {			item = PyString_FromStringAndSize(s+j, i-j);			if (item == NULL)				goto finally; 			err = PyList_Append(list, item);			Py_DECREF(item);			if (err < 0)				goto finally; 			countsplit++;			while (i < len && isspace(Py_CHARMASK(s[i]))) {				i = i+1;			}			if (maxsplit && (countsplit >= maxsplit) && i < len) {				item = PyString_FromStringAndSize(                                        s+i, len - i);				if (item == NULL)					goto finally; 				err = PyList_Append(list, item);				Py_DECREF(item);				if (err < 0)					goto finally; 				i = len;			}		}	}	return list;  finally:	Py_DECREF(list);	return NULL;}  PyDoc_STRVAR(splitfields__doc__,"split(s [,sep [,maxsplit]]) -> list of strings\n""splitfields(s [,sep [,maxsplit]]) -> list of strings\n""\n""Return a list of the words in the string s, using sep as the\n""delimiter string.  If maxsplit is nonzero, splits into at most\n""maxsplit words.  If sep is not specified, any whitespace string\n""is a separator.  Maxsplit defaults to 0.\n""\n""(split and splitfields are synonymous)"); static PyObject *strop_splitfields(PyObject *self, PyObject *args){	Py_ssize_t len, n, i, j, err;	Py_ssize_t splitcount, maxsplit;	char *s, *sub;	PyObject *list, *item; 	WARN;	sub = NULL;	n = 0;	splitcount = 0;	maxsplit = 0;	if (!PyArg_ParseTuple(args, "t#|z#n:split", &s, &len, &sub, &n, &maxsplit))		return NULL;	if (sub == NULL)		return split_whitespace(s, len, maxsplit);	if (n == 0) {		PyErr_SetString(PyExc_ValueError, "empty separator");		return NULL;	} 	list = PyList_New(0);	if (list == NULL)		return NULL; 	i = j = 0;	while (i+n <= len) {		if (s[i] == sub[0] && (n == 1 || memcmp(s+i, sub, n) == 0)) {			item = PyString_FromStringAndSize(s+j, i-j);			if (item == NULL)				goto fail;			err = PyList_Append(list, item);			Py_DECREF(item);			if (err < 0)				goto fail;			i = j = i + n;			splitcount++;			if (maxsplit && (splitcount >= maxsplit))				break;		}		else			i++;	}	item = PyString_FromStringAndSize(s+j, len-j);	if (item == NULL)		goto fail;	err = PyList_Append(list, item);	Py_DECREF(item);	if (err < 0)		goto fail; 	return list;  fail:	Py_DECREF(list);	return NULL;}  PyDoc_STRVAR(joinfields__doc__,"join(list [,sep]) -> string\n""joinfields(list [,sep]) -> string\n""\n""Return a string composed of the words in list, with\n""intervening occurrences of sep.  Sep defaults to a single\n""space.\n""\n""(join and joinfields are synonymous)"); static PyObject *strop_joinfields(PyObject *self, PyObject *args){	PyObject *seq;	char *sep = NULL;	Py_ssize_t seqlen, seplen = 0;	Py_ssize_t i, reslen = 0, slen = 0, sz = 100;	PyObject *res = NULL;	char* p = NULL;	ssizeargfunc getitemfunc; 	WARN;	if (!PyArg_ParseTuple(args, "O|t#:join", &seq, &sep, &seplen))		return NULL;	if (sep == NULL) {		sep = " ";		seplen = 1;	} 	seqlen = PySequence_Size(seq);	if (seqlen < 0 && PyErr_Occurred())		return NULL; 	if (seqlen == 1) {		/* Optimization if there's only one item */		PyObject *item = PySequence_GetItem(seq, 0);		if (item && !PyString_Check(item)) {			PyErr_SetString(PyExc_TypeError,				 "first argument must be sequence of strings");			Py_DECREF(item);			return NULL;		}		return item;	} 	if (!(res = PyString_FromStringAndSize((char*)NULL, sz)))		return NULL;	p = PyString_AsString(res); 	/* optimize for lists, since it's the most common case.  all others	 * (tuples and arbitrary sequences) just use the sequence abstract	 * interface.	 */	if (PyList_Check(seq)) {		for (i = 0; i < seqlen; i++) {			PyObject *item = PyList_GET_ITEM(seq, i);			if (!PyString_Check(item)) {				PyErr_SetString(PyExc_TypeError,				"first argument must be sequence of strings");				Py_DECREF(res);				return NULL;			}			slen = PyString_GET_SIZE(item);			while (reslen + slen + seplen >= sz) {				if (_PyString_Resize(&res, sz * 2) < 0)					return NULL;				sz *= 2;				p = PyString_AsString(res) + reslen;			}			if (i > 0) {				memcpy(p, sep, seplen);				p += seplen;				reslen += seplen;			}			memcpy(p, PyString_AS_STRING(item), slen);			p += slen;			reslen += slen;		}		_PyString_Resize(&res, reslen);		return res;	} 	if (seq->ob_type->tp_as_sequence == NULL ||		 (getitemfunc = seq->ob_type->tp_as_sequence->sq_item) == NULL)	{		PyErr_SetString(PyExc_TypeError,				"first argument must be a sequence");		return NULL;	}	/* This is now type safe */	for (i = 0; i < seqlen; i++) {		PyObject *item = getitemfunc(seq, i);		if (!item || !PyString_Check(item)) {			PyErr_SetString(PyExc_TypeError,				 "first argument must be sequence of strings");			Py_DECREF(res);			Py_XDECREF(item);			return NULL;		}		slen = PyString_GET_SIZE(item);		while (reslen + slen + seplen >= sz) {			if (_PyString_Resize(&res, sz * 2) < 0) {				Py_DECREF(item);				return NULL;			}			sz *= 2;			p = PyString_AsString(res) + reslen;		}		if (i > 0) {			memcpy(p, sep, seplen);			p += seplen;			reslen += seplen;		}		memcpy(p, PyString_AS_STRING(item), slen);		p += slen;		reslen += slen;		Py_DECREF(item);	}	_PyString_Resize(&res, reslen);	return res;}  PyDoc_STRVAR(find__doc__,"find(s, sub [,start [,end]]) -> in\n""\n""Return the lowest index in s where substring sub is found,\n""such that sub is contained within s[start,end].  Optional\n""arguments start and end are interpreted as in slice notation.\n""\n""Return -1 on failure."); static PyObject *strop_find(PyObject *self, PyObject *args){	char *s, *sub;	Py_ssize_t len, n, i = 0, last = PY_SSIZE_T_MAX; 	WARN;	if (!PyArg_ParseTuple(args, "t#t#|nn:find", &s, &len, &sub, &n, &i, &last))		return NULL; 	if (last > len)		last = len;	if (last < 0)		last += len;	if (last < 0)		last = 0;	if (i < 0)		i += len;	if (i < 0)		i = 0; 	if (n == 0 && i <= last)		return PyInt_FromLong((long)i); 	last -= n;	for (; i <= last; ++i)		if (s[i] == sub[0] &&		    (n == 1 || memcmp(&s[i+1], &sub[1], n-1) == 0))			return PyInt_FromLong((long)i); 	return PyInt_FromLong(-1L);}  PyDoc_STRVAR(rfind__doc__,"rfind(s, sub [,start [,end]]) -> int\n""\n""Return the highest index in s where substring sub is found,\n""such that sub is contained within s[start,end].  Optional\n""arguments start and end are interpreted as in slice notation.\n""\n""Return -1 on failure."); static PyObject *strop_rfind(PyObject *self, PyObject *args){	char *s, *sub;	Py_ssize_t len, n, j;	Py_ssize_t i = 0, last = PY_SSIZE_T_MAX; 	WARN;	if (!PyArg_ParseTuple(args, "t#t#|nn:rfind", &s, &len, &sub, &n, &i, &last))		return NULL; 	if (last > len)		last = len;	if (last < 0)		last += len;	if (last < 0)		last = 0;	if (i < 0)		i += len;	if (i < 0)		i = 0; 	if (n == 0 && i <= last)		return PyInt_FromLong((long)last); 	for (j = last-n; j >= i; --j)		if (s[j] == sub[0] &&		    (n == 1 || memcmp(&s[j+1], &sub[1], n-1) == 0))			return PyInt_FromLong((long)j); 	return PyInt_FromLong(-1L);}  static PyObject *do_strip(PyObject *args, int striptype){	char *s;	Py_ssize_t len, i, j;  	if (PyString_AsStringAndSize(args, &s, &len))		return NULL; 	i = 0;	if (striptype != RIGHTSTRIP) {		while (i < len && isspace(Py_CHARMASK(s[i]))) {			i++;		}	} 	j = len;	if (striptype != LEFTSTRIP) {		do {			j--;		} while (j >= i && isspace(Py_CHARMASK(s[j])));		j++;	} 	if (i == 0 && j == len) {		Py_INCREF(args);		return args;	}	else		return PyString_FromStringAndSize(s+i, j-i);}  PyDoc_STRVAR(strip__doc__,"strip(s) -> string\n""\n""Return a copy of the string s with leading and trailing\n""whitespace removed."); static PyObject *strop_strip(PyObject *self, PyObject *args){	WARN;	return do_strip(args, BOTHSTRIP);}  PyDoc_STRVAR(lstrip__doc__,"lstrip(s) -> string\n""\n""Return a copy of the string s with leading whitespace removed."); static PyObject *strop_lstrip(PyObject *self, PyObject *args){	WARN;	return do_strip(args, LEFTSTRIP);}  PyDoc_STRVAR(rstrip__doc__,"rstrip(s) -> string\n""\n""Return a copy of the string s with trailing whitespace removed."); static PyObject *strop_rstrip(PyObject *self, PyObject *args){	WARN;	return do_strip(args, RIGHTSTRIP);}  PyDoc_STRVAR(lower__doc__,"lower(s) -> string\n""\n""Return a copy of the string s converted to lowercase."); static PyObject *strop_lower(PyObject *self, PyObject *args){	char *s, *s_new;	Py_ssize_t i, n;	PyObject *newstr;	int changed; 	WARN;	if (PyString_AsStringAndSize(args, &s, &n))		return NULL;	newstr = PyString_FromStringAndSize(NULL, n);	if (newstr == NULL)		return NULL;	s_new = PyString_AsString(newstr);	changed = 0;	for (i = 0; i < n; i++) {		int c = Py_CHARMASK(*s++);		if (isupper(c)) {			changed = 1;			*s_new = tolower(c);		} else			*s_new = c;		s_new++;	}	if (!changed) {		Py_DECREF(newstr);		Py_INCREF(args);		return args;	}	return newstr;}  PyDoc_STRVAR(upper__doc__,"upper(s) -> string\n""\n""Return a copy of the string s converted to uppercase."); static PyObject *strop_upper(PyObject *self, PyObject *args){	char *s, *s_new;	Py_ssize_t i, n;	PyObject *newstr;	int changed; 	WARN;	if (PyString_AsStringAndSize(args, &s, &n))		return NULL;	newstr = PyString_FromStringAndSize(NULL, n);	if (newstr == NULL)		return NULL;	s_new = PyString_AsString(newstr);	changed = 0;	for (i = 0; i < n; i++) {		int c = Py_CHARMASK(*s++);

Lines 1–500 of 1248.