mirror of https://github.com/python/cpython.git
After a brief conversation and code review with TP, adding two very
commonly used functions to convert an arbitrary binary string into a hexadecimal digit representation and back again. These are often (and often differently) implemented in Python. Best to have one common fast implementation. Specifically, binascii_hexlify(): a.k.a. b2a_hex() to return the hex representation of binary data. binascii_unhexlify(): a.k.a. a2b_hex() to do the inverse conversion (hex digits to binary data). The argument must have an even length, and must contain only hex digits, otherwise a TypeError is raised.
This commit is contained in:
parent
57b808d21a
commit
e977c210cb
|
@ -874,31 +874,135 @@ binascii_crc32(PyObject *self, PyObject *args)
|
||||||
return Py_BuildValue("l", crc ^ 0xFFFFFFFFUL);
|
return Py_BuildValue("l", crc ^ 0xFFFFFFFFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
binascii_hexlify(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char* argbuf;
|
||||||
|
int arglen;
|
||||||
|
PyObject *retval;
|
||||||
|
char* retbuf;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "t#:b2a_hex", &argbuf, &arglen))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
retval = PyString_FromStringAndSize(NULL, arglen*2);
|
||||||
|
if (!retval)
|
||||||
|
return NULL;
|
||||||
|
retbuf = PyString_AsString(retval);
|
||||||
|
if (!retbuf)
|
||||||
|
goto finally;
|
||||||
|
|
||||||
|
/* make hex version of string, taken from shamodule.c */
|
||||||
|
for (i=j=0; i < arglen; i++) {
|
||||||
|
char c;
|
||||||
|
c = (argbuf[i] >> 4) & 0xf;
|
||||||
|
c = (c>9) ? c+'a'-10 : c + '0';
|
||||||
|
retbuf[j++] = c;
|
||||||
|
c = argbuf[i] & 0xf;
|
||||||
|
c = (c>9) ? c+'a'-10 : c + '0';
|
||||||
|
retbuf[j++] = c;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
finally:
|
||||||
|
Py_DECREF(retval);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char doc_hexlify[] =
|
||||||
|
"b2a_hex(data) -> s; Hexadecimal representation of binary data.\n\
|
||||||
|
\n\
|
||||||
|
This function is also available as \"hexlify()\".";
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
to_int(char c)
|
||||||
|
{
|
||||||
|
if (isdigit(c))
|
||||||
|
return c - '0';
|
||||||
|
else {
|
||||||
|
if (isupper(c))
|
||||||
|
c = tolower(c);
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
binascii_unhexlify(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char* argbuf;
|
||||||
|
int arglen;
|
||||||
|
PyObject *retval;
|
||||||
|
char* retbuf;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* XXX What should we do about odd-lengthed strings? Should we add
|
||||||
|
* an implicit leading zero, or a trailing zero? For now, raise an
|
||||||
|
* exception.
|
||||||
|
*/
|
||||||
|
if (arglen % 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "odd lengthed string");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = PyString_FromStringAndSize(NULL, (arglen/2));
|
||||||
|
if (!retval)
|
||||||
|
return NULL;
|
||||||
|
retbuf = PyString_AsString(retval);
|
||||||
|
if (!retbuf)
|
||||||
|
goto finally;
|
||||||
|
|
||||||
|
for (i=j=0; i < arglen; i += 2) {
|
||||||
|
int top = to_int(Py_CHARMASK(argbuf[i]));
|
||||||
|
int bot = to_int(Py_CHARMASK(argbuf[i+1]));
|
||||||
|
if (top == -1 || bot == -1) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"non-hexadecimal digit found");
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
retbuf[j++] = (top << 4) + bot;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
finally:
|
||||||
|
Py_DECREF(retval);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char doc_unhexlify[] =
|
||||||
|
"a2b_hex(hexstr) -> s; Binary data of hexadecimal representation.\n\
|
||||||
|
\n\
|
||||||
|
hexstr must contain an even number of hex digits (upper or lower case).\n\
|
||||||
|
This function is also available as \"unhexlify()\"";
|
||||||
|
|
||||||
|
|
||||||
/* List of functions defined in the module */
|
/* List of functions defined in the module */
|
||||||
|
|
||||||
static struct PyMethodDef binascii_module_methods[] = {
|
static struct PyMethodDef binascii_module_methods[] = {
|
||||||
{"a2b_uu", binascii_a2b_uu,
|
{"a2b_uu", binascii_a2b_uu, METH_VARARGS, doc_a2b_uu},
|
||||||
METH_VARARGS, doc_a2b_uu},
|
{"b2a_uu", binascii_b2a_uu, METH_VARARGS, doc_b2a_uu},
|
||||||
{"b2a_uu", binascii_b2a_uu,
|
{"a2b_base64", binascii_a2b_base64, METH_VARARGS, doc_a2b_base64},
|
||||||
METH_VARARGS, doc_b2a_uu},
|
{"b2a_base64", binascii_b2a_base64, METH_VARARGS, doc_b2a_base64},
|
||||||
{"a2b_base64", binascii_a2b_base64,
|
{"a2b_hqx", binascii_a2b_hqx, METH_VARARGS, doc_a2b_hqx},
|
||||||
METH_VARARGS,
|
{"b2a_hqx", binascii_b2a_hqx, METH_VARARGS, doc_b2a_hqx},
|
||||||
doc_a2b_base64},
|
{"b2a_hex", binascii_hexlify, METH_VARARGS, doc_hexlify},
|
||||||
{"b2a_base64", binascii_b2a_base64,
|
{"a2b_hex", binascii_unhexlify, METH_VARARGS, doc_unhexlify},
|
||||||
METH_VARARGS, doc_b2a_base64},
|
{"hexlify", binascii_hexlify, METH_VARARGS, doc_hexlify},
|
||||||
{"a2b_hqx", binascii_a2b_hqx,
|
{"unhexlify", binascii_unhexlify, METH_VARARGS, doc_unhexlify},
|
||||||
METH_VARARGS, doc_a2b_hqx},
|
{"rlecode_hqx", binascii_rlecode_hqx, METH_VARARGS, doc_rlecode_hqx},
|
||||||
{"b2a_hqx", binascii_b2a_hqx,
|
{"rledecode_hqx", binascii_rledecode_hqx, METH_VARARGS,
|
||||||
METH_VARARGS, doc_b2a_hqx},
|
doc_rledecode_hqx},
|
||||||
{"rlecode_hqx", binascii_rlecode_hqx,
|
{"crc_hqx", binascii_crc_hqx, METH_VARARGS, doc_crc_hqx},
|
||||||
METH_VARARGS, doc_rlecode_hqx},
|
{"crc32", binascii_crc32, METH_VARARGS, doc_crc32},
|
||||||
{"rledecode_hqx", binascii_rledecode_hqx,
|
{NULL, NULL} /* sentinel */
|
||||||
METH_VARARGS, doc_rledecode_hqx},
|
|
||||||
{"crc_hqx", binascii_crc_hqx,
|
|
||||||
METH_VARARGS, doc_crc_hqx},
|
|
||||||
{"crc32", binascii_crc32,
|
|
||||||
METH_VARARGS, doc_crc32},
|
|
||||||
{NULL, NULL} /* sentinel */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue