[Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.103,2.104 listobject.c,2.95,2.96 stringobject.c,2.118,2.119 tupleobject.c,2.52,2.53

Tim Peters tim_one@users.sourceforge.net
Fri, 15 Jun 2001 22:11:20 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv12913/python/dist/src/Objects

Modified Files:
	dictobject.c listobject.c stringobject.c tupleobject.c 
Log Message:
SF bug 433228: repr(list) woes when len(list) big.
Gave Python linear-time repr() implementations for dicts, lists, strings.
This means, e.g., that repr(range(50000)) is no longer 50x slower than
pprint.pprint() in 2.2 <wink>.

I don't consider this a bugfix candidate, as it's a performance boost.

Added _PyString_Join() to the internal string API.  If we want that in the
public API, fine, but then it requires runtime error checks instead of
asserts.


Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.103
retrieving revision 2.104
diff -C2 -r2.103 -r2.104
*** dictobject.c	2001/06/04 21:00:21	2.103
--- dictobject.c	2001/06/16 05:11:17	2.104
***************
*** 810,849 ****
  dict_repr(dictobject *mp)
  {
! 	auto PyObject *v;
! 	PyObject *sepa, *colon;
! 	register int i;
! 	register int any;
  
! 	i = Py_ReprEnter((PyObject*)mp);
  	if (i != 0) {
! 		if (i > 0)
! 			return PyString_FromString("{...}");
! 		return NULL;
  	}
  
! 	v = PyString_FromString("{");
! 	sepa = PyString_FromString(", ");
  	colon = PyString_FromString(": ");
! 	any = 0;
! 	for (i = 0; i <= mp->ma_mask && v; i++) {
! 		dictentry *ep = mp->ma_table + i;
! 		PyObject *pvalue = ep->me_value;
! 		if (pvalue != NULL) {
! 			/* Prevent PyObject_Repr from deleting value during
! 			   key format */
! 			Py_INCREF(pvalue);
! 			if (any++)
! 				PyString_Concat(&v, sepa);
! 			PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key));
! 			PyString_Concat(&v, colon);
! 			PyString_ConcatAndDel(&v, PyObject_Repr(pvalue));
! 			Py_DECREF(pvalue);
! 		}
  	}
! 	PyString_ConcatAndDel(&v, PyString_FromString("}"));
! 	Py_ReprLeave((PyObject*)mp);
! 	Py_XDECREF(sepa);
  	Py_XDECREF(colon);
! 	return v;
  }
  
--- 810,887 ----
  dict_repr(dictobject *mp)
  {
! 	int i, pos;
! 	PyObject *s, *temp, *colon = NULL;
! 	PyObject *pieces = NULL, *result = NULL;
! 	PyObject *key, *value;
  
! 	i = Py_ReprEnter((PyObject *)mp);
  	if (i != 0) {
! 		return i > 0 ? PyString_FromString("{...}") : NULL;
  	}
  
! 	if (mp->ma_used == 0) {
! 		result = PyString_FromString("{}");
! 		goto Done;
! 	}
! 
! 	pieces = PyList_New(0);
! 	if (pieces == NULL)
! 		goto Done;
! 
  	colon = PyString_FromString(": ");
! 	if (colon == NULL)
! 		goto Done;
! 
! 	/* Do repr() on each key+value pair, and insert ": " between them.
! 	   Note that repr may mutate the dict. */
! 	pos = 0;
! 	while (PyDict_Next((PyObject *)mp, &pos, &key, &value)) {
! 		int status;
! 		/* Prevent repr from deleting value during key format. */
! 		Py_INCREF(value);
! 		s = PyObject_Repr(key);
! 		PyString_Concat(&s, colon);
! 		PyString_ConcatAndDel(&s, PyObject_Repr(value));
! 		Py_DECREF(value);
! 		if (s == NULL)
! 			goto Done;
! 		status = PyList_Append(pieces, s);
! 		Py_DECREF(s);  /* append created a new ref */
! 		if (status < 0)
! 			goto Done;
  	}
! 
! 	/* Add "{}" decorations to the first and last items. */
! 	assert(PyList_GET_SIZE(pieces) > 0);
! 	s = PyString_FromString("{");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyList_GET_ITEM(pieces, 0);
! 	PyString_ConcatAndDel(&s, temp);
! 	PyList_SET_ITEM(pieces, 0, s);
! 	if (s == NULL)
! 		goto Done;
! 
! 	s = PyString_FromString("}");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
! 	PyString_ConcatAndDel(&temp, s);
! 	PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
! 	if (temp == NULL)
! 		goto Done;
! 
! 	/* Paste them all together with ", " between. */
! 	s = PyString_FromString(", ");
! 	if (s == NULL)
! 		goto Done;
! 	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);	
! 
! Done:
! 	Py_XDECREF(pieces);
  	Py_XDECREF(colon);
! 	Py_ReprLeave((PyObject *)mp);
! 	return result;
  }
  

Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.95
retrieving revision 2.96
diff -C2 -r2.95 -r2.96
*** listobject.c	2001/05/26 19:37:54	2.95
--- listobject.c	2001/06/16 05:11:17	2.96
***************
*** 247,270 ****
  list_repr(PyListObject *v)
  {
- 	PyObject *s, *comma;
  	int i;
  
  	i = Py_ReprEnter((PyObject*)v);
  	if (i != 0) {
! 		if (i > 0)
! 			return PyString_FromString("[...]");
! 		return NULL;
  	}
! 	s = PyString_FromString("[");
! 	comma = PyString_FromString(", ");
! 	for (i = 0; i < v->ob_size && s != NULL; i++) {
! 		if (i > 0)
! 			PyString_Concat(&s, comma);
! 		PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i]));
  	}
! 	Py_XDECREF(comma);
! 	PyString_ConcatAndDel(&s, PyString_FromString("]"));
  	Py_ReprLeave((PyObject *)v);
! 	return s;
  }
  
--- 247,312 ----
  list_repr(PyListObject *v)
  {
  	int i;
+ 	PyObject *s, *temp;
+ 	PyObject *pieces = NULL, *result = NULL;
  
  	i = Py_ReprEnter((PyObject*)v);
  	if (i != 0) {
! 		return i > 0 ? PyString_FromString("[...]") : NULL;
  	}
! 
! 	if (v->ob_size == 0) {
! 		result = PyString_FromString("[]");
! 		goto Done;
! 	}
! 
! 	pieces = PyList_New(0);
! 	if (pieces == NULL)
! 		goto Done;
! 
! 	/* Do repr() on each element.  Note that this may mutate the list,
! 	   so must refetch the list size on each iteration. */
! 	for (i = 0; i < v->ob_size; ++i) {
! 		int status;
! 		s = PyObject_Repr(v->ob_item[i]);
! 		if (s == NULL)
! 			goto Done;
! 		status = PyList_Append(pieces, s);
! 		Py_DECREF(s);  /* append created a new ref */
! 		if (status < 0)
! 			goto Done;
  	}
! 
! 	/* Add "[]" decorations to the first and last items. */
! 	assert(PyList_GET_SIZE(pieces) > 0);
! 	s = PyString_FromString("[");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyList_GET_ITEM(pieces, 0);
! 	PyString_ConcatAndDel(&s, temp);
! 	PyList_SET_ITEM(pieces, 0, s);
! 	if (s == NULL)
! 		goto Done;
! 
! 	s = PyString_FromString("]");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
! 	PyString_ConcatAndDel(&temp, s);
! 	PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
! 	if (temp == NULL)
! 		goto Done;
! 
! 	/* Paste them all together with ", " between. */
! 	s = PyString_FromString(", ");
! 	if (s == NULL)
! 		goto Done;
! 	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);	
! 
! Done:
! 	Py_XDECREF(pieces);
  	Py_ReprLeave((PyObject *)v);
! 	return result;
  }
  

Index: stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.118
retrieving revision 2.119
diff -C2 -r2.118 -r2.119
*** stringobject.c	2001/06/12 13:14:10	2.118
--- stringobject.c	2001/06/16 05:11:17	2.119
***************
*** 1032,1035 ****
--- 1032,1052 ----
  }
  
+ PyObject *_PyString_Join(PyObject *sep, PyObject *x)
+ {
+ 	PyObject* args;
+ 	PyObject* result = NULL;
+ 
+ 	assert(sep != NULL && PyString_Check(sep));
+ 	assert(x != NULL);
+ 	args = PyTuple_New(1);
+ 	if (args != NULL) {
+ 		Py_INCREF(x);
+ 		PyTuple_SET_ITEM(args, 0, x);
+ 		result = string_join((PyStringObject *)sep, args);
+ 		Py_DECREF(args);
+ 	}
+ 	return result;
+ }
+ 
  static long
  string_find_internal(PyStringObject *self, PyObject *args, int dir)

Index: tupleobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v
retrieving revision 2.52
retrieving revision 2.53
diff -C2 -r2.52 -r2.53
*** tupleobject.c	2001/05/29 07:58:45	2.52
--- tupleobject.c	2001/06/16 05:11:17	2.53
***************
*** 185,202 ****
  tuplerepr(PyTupleObject *v)
  {
! 	PyObject *s, *comma;
! 	int i;
! 	s = PyString_FromString("(");
! 	comma = PyString_FromString(", ");
! 	for (i = 0; i < v->ob_size && s != NULL; i++) {
! 		if (i > 0)
! 			PyString_Concat(&s, comma);
! 		PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i]));
  	}
! 	Py_DECREF(comma);
! 	if (v->ob_size == 1)
! 		PyString_ConcatAndDel(&s, PyString_FromString(","));
! 	PyString_ConcatAndDel(&s, PyString_FromString(")"));
! 	return s;
  }
  
--- 185,238 ----
  tuplerepr(PyTupleObject *v)
  {
! 	int i, n;
! 	PyObject *s, *temp;
! 	PyObject *pieces, *result = NULL;
! 
! 	n = v->ob_size;
! 	if (n == 0)
! 		return PyString_FromString("()");
! 
! 	pieces = PyTuple_New(n);
! 	if (pieces == NULL)
! 		return NULL;
! 
! 	/* Do repr() on each element. */
! 	for (i = 0; i < n; ++i) {
! 		s = PyObject_Repr(v->ob_item[i]);
! 		if (s == NULL)
! 			goto Done;
! 		PyTuple_SET_ITEM(pieces, i, s);
  	}
! 
! 	/* Add "()" decorations to the first and last items. */
! 	assert(n > 0);
! 	s = PyString_FromString("(");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyTuple_GET_ITEM(pieces, 0);
! 	PyString_ConcatAndDel(&s, temp);
! 	PyTuple_SET_ITEM(pieces, 0, s);
! 	if (s == NULL)
! 		goto Done;
! 
! 	s = PyString_FromString(n == 1 ? ",)" : ")");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyTuple_GET_ITEM(pieces, n-1);
! 	PyString_ConcatAndDel(&temp, s);
! 	PyTuple_SET_ITEM(pieces, n-1, temp);
! 	if (temp == NULL)
! 		goto Done;
! 
! 	/* Paste them all together with ", " between. */
! 	s = PyString_FromString(", ");
! 	if (s == NULL)
! 		goto Done;
! 	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);	
! 
! Done:
! 	Py_DECREF(pieces);
! 	return result;
  }