diff options
author | Barry Warsaw <barry@python.org> | 2000-08-15 06:07:13 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 2000-08-15 06:07:13 (GMT) |
commit | e977c210cbadf5d4a91eefa94b9b10da484f6ef1 (patch) | |
tree | 77d4b141b2ac807650dd6b6a5cdb9980066ac792 /Modules/binascii.c | |
parent | 57b808d21a7651b303bf22264c4bc47824ab3b51 (diff) | |
download | cpython-e977c210cbadf5d4a91eefa94b9b10da484f6ef1.zip cpython-e977c210cbadf5d4a91eefa94b9b10da484f6ef1.tar.gz cpython-e977c210cbadf5d4a91eefa94b9b10da484f6ef1.tar.bz2 |
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.
Diffstat (limited to 'Modules/binascii.c')
-rw-r--r-- | Modules/binascii.c | 148 |
1 files changed, 126 insertions, 22 deletions
diff --git a/Modules/binascii.c b/Modules/binascii.c index 50f8b76..89ccc79 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -874,31 +874,135 @@ binascii_crc32(PyObject *self, PyObject *args) 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 */ static struct PyMethodDef binascii_module_methods[] = { - {"a2b_uu", binascii_a2b_uu, - METH_VARARGS, doc_a2b_uu}, - {"b2a_uu", binascii_b2a_uu, - METH_VARARGS, doc_b2a_uu}, - {"a2b_base64", binascii_a2b_base64, - METH_VARARGS, - doc_a2b_base64}, - {"b2a_base64", binascii_b2a_base64, - METH_VARARGS, doc_b2a_base64}, - {"a2b_hqx", binascii_a2b_hqx, - METH_VARARGS, doc_a2b_hqx}, - {"b2a_hqx", binascii_b2a_hqx, - METH_VARARGS, doc_b2a_hqx}, - {"rlecode_hqx", binascii_rlecode_hqx, - METH_VARARGS, doc_rlecode_hqx}, - {"rledecode_hqx", binascii_rledecode_hqx, - 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 */ + {"a2b_uu", binascii_a2b_uu, METH_VARARGS, doc_a2b_uu}, + {"b2a_uu", binascii_b2a_uu, METH_VARARGS, doc_b2a_uu}, + {"a2b_base64", binascii_a2b_base64, METH_VARARGS, doc_a2b_base64}, + {"b2a_base64", binascii_b2a_base64, METH_VARARGS, doc_b2a_base64}, + {"a2b_hqx", binascii_a2b_hqx, METH_VARARGS, doc_a2b_hqx}, + {"b2a_hqx", binascii_b2a_hqx, METH_VARARGS, doc_b2a_hqx}, + {"b2a_hex", binascii_hexlify, METH_VARARGS, doc_hexlify}, + {"a2b_hex", binascii_unhexlify, METH_VARARGS, doc_unhexlify}, + {"hexlify", binascii_hexlify, METH_VARARGS, doc_hexlify}, + {"unhexlify", binascii_unhexlify, METH_VARARGS, doc_unhexlify}, + {"rlecode_hqx", binascii_rlecode_hqx, METH_VARARGS, doc_rlecode_hqx}, + {"rledecode_hqx", binascii_rledecode_hqx, 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 */ }; |