1 /* bytes to hex implementation */
2 
3 #include "Python.h"
4 
5 static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen,
6                                  int return_bytes)
7 {
8     PyObject *retval;
9     Py_UCS1* retbuf;
10     Py_ssize_t i, j;
11 
12     assert(arglen >= 0);
13     if (arglen > PY_SSIZE_T_MAX / 2)
14         return PyErr_NoMemory();
15 
16     if (return_bytes) {
17         /* If _PyBytes_FromSize() were public we could avoid malloc+copy. */
18         retbuf = (Py_UCS1*) PyMem_Malloc(arglen*2);
19 	if (!retbuf)
20 	    return PyErr_NoMemory();
21         retval = NULL;  /* silence a compiler warning, assigned later. */
22     } else {
23 	retval = PyUnicode_New(arglen*2, 127);
24 	if (!retval)
25 	    return NULL;
26 	retbuf = PyUnicode_1BYTE_DATA(retval);
27     }
28 
29     /* make hex version of string, taken from shamodule.c */
30     for (i=j=0; i < arglen; i++) {
31         unsigned char c;
32         c = (argbuf[i] >> 4) & 0xf;
33         retbuf[j++] = Py_hexdigits[c];
34         c = argbuf[i] & 0xf;
35         retbuf[j++] = Py_hexdigits[c];
36     }
37 
38     if (return_bytes) {
39         retval = PyBytes_FromStringAndSize((const char *)retbuf, arglen*2);
40         PyMem_Free(retbuf);
41     }
42 #ifdef Py_DEBUG
43     else {
44         assert(_PyUnicode_CheckConsistency(retval, 1));
45     }
46 #endif
47 
48     return retval;
49 }
50 
51 PyAPI_FUNC(PyObject *) _Py_strhex(const char* argbuf, const Py_ssize_t arglen)
52 {
53     return _Py_strhex_impl(argbuf, arglen, 0);
54 }
55 
56 /* Same as above but returns a bytes() instead of str() to avoid the
57  * need to decode the str() when bytes are needed. */
58 PyAPI_FUNC(PyObject *) _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen)
59 {
60     return _Py_strhex_impl(argbuf, arglen, 1);
61 }
62