comparison Objects/bytesobject.c @ 58227:7e2af4e57039

Issue #6688: Optimize PyBytes_FromObject(). - Add special-cases for list and tuple objects. - Use _PyObject_LengthHint() instead of an arbitrary value for the size of the initial buffer of the returned object.
author Alexandre Vassalotti <alexandre@peadrop.com>
date Sat, 09 Jan 2010 22:14:46 +0000
parents d52a7179eece
children efa5867d8a14
comparison
equal deleted inserted replaced
58225:a7ab1abdeb92 58227:7e2af4e57039
2977 PyErr_SetString(PyExc_TypeError, 2977 PyErr_SetString(PyExc_TypeError,
2978 "cannot convert unicode object to bytes"); 2978 "cannot convert unicode object to bytes");
2979 return NULL; 2979 return NULL;
2980 } 2980 }
2981 2981
2982 if (PyList_CheckExact(x)) {
2983 new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
2984 if (new == NULL)
2985 return NULL;
2986 for (i = 0; i < Py_SIZE(x); i++) {
2987 Py_ssize_t value = PyNumber_AsSsize_t(
2988 PyList_GET_ITEM(x, i), PyExc_ValueError);
2989 if (value == -1 && PyErr_Occurred()) {
2990 Py_DECREF(new);
2991 return NULL;
2992 }
2993 if (value < 0 || value >= 256) {
2994 PyErr_SetString(PyExc_ValueError,
2995 "bytes must be in range(0, 256)");
2996 Py_DECREF(new);
2997 return NULL;
2998 }
2999 ((PyBytesObject *)new)->ob_sval[i] = value;
3000 }
3001 return new;
3002 }
3003 if (PyTuple_CheckExact(x)) {
3004 new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
3005 if (new == NULL)
3006 return NULL;
3007 for (i = 0; i < Py_SIZE(x); i++) {
3008 Py_ssize_t value = PyNumber_AsSsize_t(
3009 PyTuple_GET_ITEM(x, i), PyExc_ValueError);
3010 if (value == -1 && PyErr_Occurred()) {
3011 Py_DECREF(new);
3012 return NULL;
3013 }
3014 if (value < 0 || value >= 256) {
3015 PyErr_SetString(PyExc_ValueError,
3016 "bytes must be in range(0, 256)");
3017 Py_DECREF(new);
3018 return NULL;
3019 }
3020 ((PyBytesObject *)new)->ob_sval[i] = value;
3021 }
3022 return new;
3023 }
3024
2982 /* For iterator version, create a string object and resize as needed */ 3025 /* For iterator version, create a string object and resize as needed */
2983 /* XXX(gb): is 64 a good value? also, optimize if length is known */ 3026 size = _PyObject_LengthHint(x, 64);
2984 /* XXX(guido): perhaps use Pysequence_Fast() -- I can't imagine the 3027 if (size == -1 && PyErr_Occurred())
2985 input being a truly long iterator. */ 3028 return NULL;
2986 size = 64; 3029 /* Allocate an extra byte to prevent PyBytes_FromStringAndSize() from
3030 returning a shared empty bytes string. This required because we
3031 want to call _PyBytes_Resize() the returned object, which we can
3032 only do on bytes objects with refcount == 1. */
3033 size += 1;
2987 new = PyBytes_FromStringAndSize(NULL, size); 3034 new = PyBytes_FromStringAndSize(NULL, size);
2988 if (new == NULL) 3035 if (new == NULL)
2989 return NULL; 3036 return NULL;
2990
2991 /* XXX Optimize this if the arguments is a list, tuple */
2992 3037
2993 /* Get the iterator */ 3038 /* Get the iterator */
2994 it = PyObject_GetIter(x); 3039 it = PyObject_GetIter(x);
2995 if (it == NULL) 3040 if (it == NULL)
2996 goto error; 3041 goto error;
3021 goto error; 3066 goto error;
3022 } 3067 }
3023 3068
3024 /* Append the byte */ 3069 /* Append the byte */
3025 if (i >= size) { 3070 if (i >= size) {
3026 size *= 2; 3071 size = 2 * size + 1;
3027 if (_PyBytes_Resize(&new, size) < 0) 3072 if (_PyBytes_Resize(&new, size) < 0)
3028 goto error; 3073 goto error;
3029 } 3074 }
3030 ((PyBytesObject *)new)->ob_sval[i] = value; 3075 ((PyBytesObject *)new)->ob_sval[i] = value;
3031 } 3076 }