Issue #13088: Add shared Py_hexdigits constant to format a number into base 16
diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c
index c9843c2..26c8788 100644
--- a/Modules/_codecsmodule.c
+++ b/Modules/_codecsmodule.c
@@ -162,7 +162,6 @@
 escape_encode(PyObject *self,
               PyObject *args)
 {
-    static const char *hexdigits = "0123456789abcdef";
     PyObject *str;
     Py_ssize_t size;
     Py_ssize_t newsize;
@@ -205,8 +204,8 @@
             else if (c < ' ' || c >= 0x7f) {
                 *p++ = '\\';
                 *p++ = 'x';
-                *p++ = hexdigits[(c & 0xf0) >> 4];
-                *p++ = hexdigits[c & 0xf];
+                *p++ = Py_hexdigits[(c & 0xf0) >> 4];
+                *p++ = Py_hexdigits[c & 0xf];
             }
             else
                 *p++ = c;
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index dd4317f..d37689e 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -201,13 +201,11 @@
 
     /* Make hex version of the digest */
     for(i=j=0; i<digest_size; i++) {
-        char c;
+        unsigned char c;
         c = (digest[i] >> 4) & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
         c = (digest[i] & 0xf);
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
     }
     retval = PyUnicode_FromStringAndSize(hex_digest, digest_size * 2);
     PyMem_Free(hex_digest);
diff --git a/Modules/_json.c b/Modules/_json.c
index dca3791..cafd5a9 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -175,18 +175,18 @@
                 Py_UCS4 v = c - 0x10000;
                 c = 0xd800 | ((v >> 10) & 0x3ff);
                 output[chars++] = 'u';
-                output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
-                output[chars++] = "0123456789abcdef"[(c >>  8) & 0xf];
-                output[chars++] = "0123456789abcdef"[(c >>  4) & 0xf];
-                output[chars++] = "0123456789abcdef"[(c      ) & 0xf];
+                output[chars++] = Py_hexdigits[(c >> 12) & 0xf];
+                output[chars++] = Py_hexdigits[(c >>  8) & 0xf];
+                output[chars++] = Py_hexdigits[(c >>  4) & 0xf];
+                output[chars++] = Py_hexdigits[(c      ) & 0xf];
                 c = 0xdc00 | (v & 0x3ff);
                 output[chars++] = '\\';
             }
             output[chars++] = 'u';
-            output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf];
-            output[chars++] = "0123456789abcdef"[(c >>  8) & 0xf];
-            output[chars++] = "0123456789abcdef"[(c >>  4) & 0xf];
-            output[chars++] = "0123456789abcdef"[(c      ) & 0xf];
+            output[chars++] = Py_hexdigits[(c >> 12) & 0xf];
+            output[chars++] = Py_hexdigits[(c >>  8) & 0xf];
+            output[chars++] = Py_hexdigits[(c >>  4) & 0xf];
+            output[chars++] = Py_hexdigits[(c      ) & 0xf];
     }
     return chars;
 }
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 6a44b82..ad185a7 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -1776,7 +1776,6 @@
 static PyObject *
 raw_unicode_escape(PyObject *obj)
 {
-    static const char *hexdigits = "0123456789abcdef";
     PyObject *repr, *result;
     char *p;
     Py_ssize_t i, size, expandsize;
@@ -1809,23 +1808,23 @@
         if (ch >= 0x10000) {
             *p++ = '\\';
             *p++ = 'U';
-            *p++ = hexdigits[(ch >> 28) & 0xf];
-            *p++ = hexdigits[(ch >> 24) & 0xf];
-            *p++ = hexdigits[(ch >> 20) & 0xf];
-            *p++ = hexdigits[(ch >> 16) & 0xf];
-            *p++ = hexdigits[(ch >> 12) & 0xf];
-            *p++ = hexdigits[(ch >> 8) & 0xf];
-            *p++ = hexdigits[(ch >> 4) & 0xf];
-            *p++ = hexdigits[ch & 15];
+            *p++ = Py_hexdigits[(ch >> 28) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 24) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 20) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 16) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 12) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 8) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 4) & 0xf];
+            *p++ = Py_hexdigits[ch & 15];
         }
         /* Map 16-bit characters to '\uxxxx' */
         else if (ch >= 256 || ch == '\\' || ch == '\n') {
             *p++ = '\\';
             *p++ = 'u';
-            *p++ = hexdigits[(ch >> 12) & 0xf];
-            *p++ = hexdigits[(ch >> 8) & 0xf];
-            *p++ = hexdigits[(ch >> 4) & 0xf];
-            *p++ = hexdigits[ch & 15];
+            *p++ = Py_hexdigits[(ch >> 12) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 8) & 0xf];
+            *p++ = Py_hexdigits[(ch >> 4) & 0xf];
+            *p++ = Py_hexdigits[ch & 15];
         }
         /* Copy everything else as-is */
         else
diff --git a/Modules/binascii.c b/Modules/binascii.c
index 19681b4..dc4fef5 100644
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -1078,13 +1078,11 @@
 
     /* make hex version of string, taken from shamodule.c */
     for (i=j=0; i < arglen; i++) {
-        char c;
+        unsigned char c;
         c = (argbuf[i] >> 4) & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        retbuf[j++] = c;
+        retbuf[j++] = Py_hexdigits[c];
         c = argbuf[i] & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        retbuf[j++] = c;
+        retbuf[j++] = Py_hexdigits[c];
     }
     PyBuffer_Release(&parg);
     return retval;
diff --git a/Modules/md5module.c b/Modules/md5module.c
index b6ab5ca..86f602e 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -391,13 +391,11 @@
 
     /* Make hex version of the digest */
     for(i=j=0; i<MD5_DIGESTSIZE; i++) {
-        char c;
+        unsigned char c;
         c = (digest[i] >> 4) & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
         c = (digest[i] & 0xf);
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
     }
     return retval;
 }
diff --git a/Modules/sha1module.c b/Modules/sha1module.c
index d25aaea..30e5c50 100644
--- a/Modules/sha1module.c
+++ b/Modules/sha1module.c
@@ -367,13 +367,11 @@
 
     /* Make hex version of the digest */
     for(i=j=0; i<SHA1_DIGESTSIZE; i++) {
-        char c;
+        unsigned char c;
         c = (digest[i] >> 4) & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
         c = (digest[i] & 0xf);
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
     }
     return retval;
 }
diff --git a/Modules/sha256module.c b/Modules/sha256module.c
index fe2dcfa..f1ef329 100644
--- a/Modules/sha256module.c
+++ b/Modules/sha256module.c
@@ -460,13 +460,11 @@
 
     /* Make hex version of the digest */
     for(i=j=0; i<self->digestsize; i++) {
-        char c;
+        unsigned char c;
         c = (digest[i] >> 4) & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
         c = (digest[i] & 0xf);
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
     }
     return retval;
 }
diff --git a/Modules/sha512module.c b/Modules/sha512module.c
index 4177000..4f5a113 100644
--- a/Modules/sha512module.c
+++ b/Modules/sha512module.c
@@ -526,13 +526,11 @@
 
     /* Make hex version of the digest */
     for (i=j=0; i<self->digestsize; i++) {
-        char c;
+        unsigned char c;
         c = (digest[i] >> 4) & 0xf;
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
         c = (digest[i] & 0xf);
-        c = (c>9) ? c+'a'-10 : c + '0';
-        hex_digest[j++] = c;
+        hex_digest[j++] = Py_hexdigits[c];
     }
     return retval;
 }