blob: 511ac07329767e93668f099b065058cabd316715 [file]
#include "bytes_extra_ops.h"
PyObject *CPyBytes_Translate(PyObject *bytes, PyObject *table) {
// Fast path: exact bytes object with exact bytes table
if (PyBytes_CheckExact(bytes) && PyBytes_CheckExact(table)) {
Py_ssize_t table_len = PyBytes_GET_SIZE(table);
if (table_len != 256) {
PyErr_SetString(PyExc_ValueError,
"translation table must be 256 characters long");
return NULL;
}
Py_ssize_t len = PyBytes_GET_SIZE(bytes);
const char *input = PyBytes_AS_STRING(bytes);
const char *trans_table = PyBytes_AS_STRING(table);
PyObject *result = PyBytes_FromStringAndSize(NULL, len);
if (result == NULL) {
return NULL;
}
char *output = PyBytes_AS_STRING(result);
bool changed = false;
// Without a loop unrolling hint performance can be worse than CPython
CPY_UNROLL_LOOP(4)
for (Py_ssize_t i = len; --i >= 0;) {
char c = *input++;
if ((*output++ = trans_table[(unsigned char)c]) != c)
changed = true;
}
// If nothing changed, discard result and return the original object
if (!changed) {
Py_DECREF(result);
Py_INCREF(bytes);
return bytes;
}
return result;
}
// Fallback to Python method call for non-exact types or non-standard tables
return PyObject_CallMethodOneArg(bytes, mypyc_interned_str.translate, table);
}