Mercurial > cpython-lru_cache-weakref
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 } |
