diff -r e948154af406 Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py Sat Apr 13 18:00:04 2013 +0300 +++ b/Lib/test/test_bytes.py Sat Apr 13 16:33:46 2013 -0400 @@ -1211,6 +1211,28 @@ self.assertRaises(TypeError, b.translate, None, None) self.assertRaises(TypeError, ba.translate, None, None) + def test_mtranslate(self): + rosetta = bytearray(range(0, 256)) + rosetta[ord('o')] = ord('e') + + ba = bytearray(b'hello') + ba.mtranslate(rosetta, b'l') + self.assertEqual(ba, b'hee') + + ba = bytearray(b'hello') + ba.mtranslate(None, b'e') + self.assertEqual(ba, b'hllo') + + ba = bytearray(b'ohio') + ba.mtranslate(rosetta) + self.assertEqual(ba, bytearray(b'ehie')) + + ba = bytearray(b'erie') + ba.mtranslate(rosetta, b'e') + self.assertEqual(ba, bytearray(b'ri')) + + self.assertRaises(TypeError, ba.mtranslate, None, None) + def test_split_bytearray(self): self.assertEqual(b'a b'.split(memoryview(b' ')), [b'a', b'b']) diff -r e948154af406 Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c Sat Apr 13 18:00:04 2013 +0300 +++ b/Objects/bytearrayobject.c Sat Apr 13 16:33:46 2013 -0400 @@ -1417,6 +1417,100 @@ return PyBool_FromLong(result); } +PyDoc_STRVAR(mtranslate__doc__, +"B.mtranslate(table[, deletechars]) -> bytearray\n\ +\n\ +Mutable translate performs the same action as translate,\n\ +in place on the string"); + +static PyObject * +bytearray_mtranslate(PyByteArrayObject *self, PyObject *args) +{ + register char *input, *target; + register const char *table; + register Py_ssize_t i, c; + PyObject *tableobj = NULL, *delobj = NULL; + Py_buffer vtable, vdel; + PyObject *input_obj = (PyObject*)self; + int inlen, outlen; + int trans_table[256]; + + if(!PyArg_UnpackTuple(args, "translate", 1, 2, + &tableobj, &delobj)){ + return NULL; + } + + if (tableobj == Py_None) { + table = NULL; + tableobj = NULL; + } else if(_getbuffer(tableobj, &vtable) < 0) { + return NULL; + } else { + if(vtable.len != 256){ + PyErr_SetString(PyExc_ValueError, + "translation table must be 256 characters long"); + PyBuffer_Release(&vtable); + return NULL; + } + table = (const char*)vtable.buf; + } + + if (delobj != NULL) { + if (_getbuffer(delobj, &vdel) < 0) { + if (tableobj != NULL) + PyBuffer_Release(&vtable); + return NULL; + } + } + else { + vdel.buf = NULL; + vdel.len = 0; + } + + inlen = PyByteArray_GET_SIZE(input_obj); + input = PyByteArray_AS_STRING(input_obj); + + if(vdel.len == 0 && table != NULL){ + for (i = inlen; --i >= 0; ) { + c = Py_CHARMASK(*input); + *input = table[c]; + ++input; + } + goto done; + } + + if (table == NULL) { + for (i = 0; i < 256; i++) + trans_table[i] = Py_CHARMASK(i); + } else { + for (i = 0; i < 256; i++) + trans_table[i] = Py_CHARMASK(table[i]); + } + + for (i = 0; i < vdel.len; i++) + trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1; + + outlen = 0; + target = input; + for (i = inlen; --i >= 0; ) { + c = Py_CHARMASK(*input); + if (trans_table[c] != -1){ + ++outlen; + *target++ = (char)trans_table[c]; + } + ++input; + } + + if(outlen != inlen) + PyByteArray_Resize(input_obj, outlen); + +done: + if (tableobj != NULL) + PyBuffer_Release(&vtable); + if (delobj != NULL) + PyBuffer_Release(&vdel); + return Py_None; +} PyDoc_STRVAR(translate__doc__, "B.translate(table[, deletechars]) -> bytearray\n\ @@ -2874,6 +2968,8 @@ {"lstrip", (PyCFunction)bytearray_lstrip, METH_VARARGS, lstrip__doc__}, {"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, _Py_maketrans__doc__}, + {"mtranslate", (PyCFunction)bytearray_mtranslate, METH_VARARGS, + mtranslate__doc__}, {"partition", (PyCFunction)bytearray_partition, METH_O, partition__doc__}, {"pop", (PyCFunction)bytearray_pop, METH_VARARGS, pop__doc__}, {"remove", (PyCFunction)bytearray_remove, METH_O, remove__doc__},