@@ -43,24 +43,12 @@ _getbytevalue(PyObject* arg, int *value)
4343 return 1 ;
4444}
4545
46- static inline void
47- bytearray_write_trailing_null_byte (PyByteArrayObject * self )
48- {
49- char * data = PyByteArray_AS_STRING (self );
50- Py_ssize_t size = PyByteArray_GET_SIZE (self );
51- data [size ] = '\0' ;
52- }
53-
54-
5546static void
56- bytearray_reinit_from_bytes (PyByteArrayObject * self , Py_ssize_t size )
47+ bytearray_reinit_from_bytes (PyByteArrayObject * self , Py_ssize_t size ,
48+ Py_ssize_t alloc )
5749{
58- Py_ssize_t alloc = PyBytes_GET_SIZE (self -> ob_bytes_object );
59- assert (0 <= size && size <= alloc );
60-
6150 /* Only the empty bytes may be immortal. */
6251 assert ((alloc == 0 ) == _Py_IsImmortal (self -> ob_bytes_object ));
63-
6452 self -> ob_bytes = self -> ob_start = PyBytes_AS_STRING (self -> ob_bytes_object );
6553 Py_SET_SIZE (self , size );
6654 FT_ATOMIC_STORE_SSIZE_RELAXED (self -> ob_alloc , alloc );
@@ -197,7 +185,7 @@ PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size)
197185 Py_DECREF (new );
198186 return NULL ;
199187 }
200- bytearray_reinit_from_bytes (new , size );
188+ bytearray_reinit_from_bytes (new , size , size );
201189 if (bytes != NULL && size > 0 ) {
202190 memcpy (new -> ob_bytes , bytes , size );
203191 }
@@ -223,43 +211,6 @@ PyByteArray_AsString(PyObject *self)
223211 return PyByteArray_AS_STRING (self );
224212}
225213
226-
227- static int
228- bytearray_resize_storage (PyByteArrayObject * self ,
229- Py_ssize_t new_size , Py_ssize_t alloc )
230- {
231- _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (self );
232- assert (1 <= new_size && new_size <= alloc );
233-
234- Py_ssize_t size = Py_SIZE (self );
235-
236- /* Re-align data to the start of the allocation. */
237- char * old_start = self -> ob_start ;
238- if (self -> ob_start != self -> ob_bytes ) {
239- /* optimization tradeoff: This is faster than a new allocation when
240- the number of bytes being removed in a resize is small; for
241- large size changes it may be better to just make a new bytes
242- object as _PyBytes_Resize will do a malloc + memcpy internally.
243- */
244- Py_ssize_t move = Py_MIN (new_size , size );
245- memmove (self -> ob_bytes , self -> ob_start , move );
246- self -> ob_start = self -> ob_bytes ;
247- }
248-
249- if (_PyBytes_ResizeKeepOnError (& self -> ob_bytes_object , alloc ) < 0 ) {
250- if (old_start != self -> ob_bytes && new_size < size ) {
251- // Move remaining bytes
252- Py_ssize_t moved = new_size ;
253- Py_ssize_t remaining = size - moved ;
254- memmove (self -> ob_bytes + moved , old_start + moved , remaining );
255- }
256- bytearray_write_trailing_null_byte (self );
257- return -1 ;
258- }
259- return 0 ;
260- }
261-
262-
263214static int
264215bytearray_resize_lock_held (PyObject * self , Py_ssize_t requested_size )
265216{
@@ -295,7 +246,7 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
295246 if (requested_size == 0 ) {
296247 Py_SETREF (obj -> ob_bytes_object ,
297248 Py_GetConstant (Py_CONSTANT_EMPTY_BYTES ));
298- bytearray_reinit_from_bytes (obj , 0 );
249+ bytearray_reinit_from_bytes (obj , 0 , 0 );
299250 return 0 ;
300251 }
301252
@@ -310,7 +261,7 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
310261 /* Minor downsize; quick exit */
311262 Py_SET_SIZE (self , size );
312263 /* Add mid-buffer null; end provided by bytes. */
313- bytearray_write_trailing_null_byte ( _PyByteArray_CAST ( self ));
264+ PyByteArray_AS_STRING ( self )[ size ] = '\0' ; /* Trailing null */
314265 return 0 ;
315266 }
316267 }
@@ -330,16 +281,28 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
330281 return -1 ;
331282 }
332283
333- if (bytearray_resize_storage (obj , requested_size , (Py_ssize_t )alloc ) < 0 ) {
334- return -1 ;
284+ /* Re-align data to the start of the allocation. */
285+ if (logical_offset > 0 ) {
286+ /* optimization tradeoff: This is faster than a new allocation when
287+ the number of bytes being removed in a resize is small; for large
288+ size changes it may be better to just make a new bytes object as
289+ _PyBytes_Resize will do a malloc + memcpy internally. */
290+ memmove (obj -> ob_bytes , obj -> ob_start ,
291+ Py_MIN (requested_size , Py_SIZE (self )));
335292 }
336293
337- bytearray_reinit_from_bytes (obj , size );
294+ int ret = _PyBytes_Resize (& obj -> ob_bytes_object , alloc );
295+ if (ret == -1 ) {
296+ obj -> ob_bytes_object = Py_GetConstant (Py_CONSTANT_EMPTY_BYTES );
297+ size = alloc = 0 ;
298+ }
299+ bytearray_reinit_from_bytes (obj , size , alloc );
338300 if (alloc != size ) {
339301 /* Add mid-buffer null; end provided by bytes. */
340- bytearray_write_trailing_null_byte ( obj ) ;
302+ obj -> ob_bytes [ size ] = '\0' ;
341303 }
342- return 0 ;
304+
305+ return ret ;
343306}
344307
345308int
@@ -965,7 +928,7 @@ bytearray_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
965928 }
966929 PyByteArrayObject * self = _PyByteArray_CAST (op );
967930 self -> ob_bytes_object = Py_GetConstant (Py_CONSTANT_EMPTY_BYTES );
968- bytearray_reinit_from_bytes (self , 0 );
931+ bytearray_reinit_from_bytes (self , 0 , 0 );
969932 self -> ob_exports = 0 ;
970933 return op ;
971934}
@@ -1031,9 +994,9 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
1031994 if (_PyObject_IsUniquelyReferenced (encoded )
1032995 && PyBytes_CheckExact (encoded ))
1033996 {
1034- Py_ssize_t size = PyBytes_GET_SIZE (encoded );
997+ Py_ssize_t size = Py_SIZE (encoded );
1035998 self -> ob_bytes_object = encoded ;
1036- bytearray_reinit_from_bytes (self , size );
999+ bytearray_reinit_from_bytes (self , size , size );
10371000 return 0 ;
10381001 }
10391002 new = bytearray_iconcat ((PyObject * )self , encoded );
@@ -1157,7 +1120,7 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
11571120 /* Append the byte */
11581121 if (Py_SIZE (self ) + 1 < self -> ob_alloc ) {
11591122 Py_SET_SIZE (self , Py_SIZE (self ) + 1 );
1160- bytearray_write_trailing_null_byte (self );
1123+ PyByteArray_AS_STRING (self )[ Py_SIZE ( self )] = '\0' ;
11611124 }
11621125 else if (PyByteArray_Resize ((PyObject * )self , Py_SIZE (self )+ 1 ) < 0 )
11631126 goto error ;
@@ -1647,7 +1610,6 @@ bytearray_take_bytes_impl(PyByteArrayObject *self, PyObject *n)
16471610 }
16481611
16491612 Py_ssize_t remaining_length = size - to_take ;
1650-
16511613 // optimization: If taking less than leaving, just copy the small to_take
16521614 // portion out and move ob_start.
16531615 if (to_take < remaining_length ) {
@@ -1669,15 +1631,24 @@ bytearray_take_bytes_impl(PyByteArrayObject *self, PyObject *n)
16691631 memcpy (PyBytes_AS_STRING (remaining ), self -> ob_start + to_take ,
16701632 remaining_length );
16711633
1672- if (bytearray_resize_storage (self , to_take , to_take ) < 0 ) {
1634+ // If the bytes are offset inside the buffer must first align.
1635+ if (self -> ob_start != self -> ob_bytes ) {
1636+ memmove (self -> ob_bytes , self -> ob_start , to_take );
1637+ self -> ob_start = self -> ob_bytes ;
1638+ }
1639+
1640+ if (_PyBytes_Resize (& self -> ob_bytes_object , to_take ) == -1 ) {
1641+ assert (self -> ob_bytes_object == NULL );
1642+ self -> ob_bytes_object = Py_GetConstant (Py_CONSTANT_EMPTY_BYTES );
1643+ bytearray_reinit_from_bytes (self , 0 , 0 );
16731644 Py_DECREF (remaining );
16741645 return NULL ;
16751646 }
16761647
16771648 // Point the bytearray towards the buffer with the remaining data.
16781649 PyObject * result = self -> ob_bytes_object ;
16791650 self -> ob_bytes_object = remaining ;
1680- bytearray_reinit_from_bytes (self , remaining_length );
1651+ bytearray_reinit_from_bytes (self , remaining_length , remaining_length );
16811652 return result ;
16821653}
16831654
0 commit comments