Skip to content

Commit 6b5df90

Browse files
sir-sigurdserhiy-storchaka
authored andcommitted
bpo-32147: Improved perfomance of binascii.unhexlify(). (GH-4586)
1 parent 19e7d48 commit 6b5df90

File tree

4 files changed

+13
-33
lines changed

4 files changed

+13
-33
lines changed

Lib/test/test_binascii.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ def test_hex(self):
198198
self.assertEqual(s, u)
199199
self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1])
200200
self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1] + b'q')
201+
self.assertRaises(binascii.Error, binascii.a2b_hex, bytes([255, 255]))
202+
self.assertRaises(binascii.Error, binascii.a2b_hex, b'0G')
203+
self.assertRaises(binascii.Error, binascii.a2b_hex, b'0g')
204+
self.assertRaises(binascii.Error, binascii.a2b_hex, b'G0')
205+
self.assertRaises(binascii.Error, binascii.a2b_hex, b'g0')
201206

202207
# Confirm that b2a_hex == hexlify and a2b_hex == unhexlify
203208
self.assertEqual(binascii.hexlify(self.type2test(s)), t)

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ Michael Farrell
460460
Troy J. Farrell
461461
Jim Fasarakis-Hilliard
462462
Mark Favas
463+
Sergey Fedoseev
463464
Boris Feld
464465
Thomas Fenzl
465466
Niels Ferguson
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`binascii.unhexlify` is now up to 2 times faster.
2+
Patch by Sergey Fedoseev.

Modules/binascii.c

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,21 +1130,6 @@ binascii_hexlify_impl(PyObject *module, Py_buffer *data)
11301130
return _Py_strhex_bytes((const char *)data->buf, data->len);
11311131
}
11321132

1133-
static int
1134-
to_int(int c)
1135-
{
1136-
if (Py_ISDIGIT(c))
1137-
return c - '0';
1138-
else {
1139-
if (Py_ISUPPER(c))
1140-
c = Py_TOLOWER(c);
1141-
if (c >= 'a' && c <= 'f')
1142-
return c - 'a' + 10;
1143-
}
1144-
return -1;
1145-
}
1146-
1147-
11481133
/*[clinic input]
11491134
binascii.a2b_hex
11501135
@@ -1187,9 +1172,9 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
11871172
retbuf = PyBytes_AS_STRING(retval);
11881173

11891174
for (i=j=0; i < arglen; i += 2) {
1190-
int top = to_int(Py_CHARMASK(argbuf[i]));
1191-
int bot = to_int(Py_CHARMASK(argbuf[i+1]));
1192-
if (top == -1 || bot == -1) {
1175+
unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])];
1176+
unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])];
1177+
if (top >= 16 || bot >= 16) {
11931178
PyErr_SetString(Error,
11941179
"Non-hexadecimal digit found");
11951180
goto finally;
@@ -1218,19 +1203,6 @@ binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr)
12181203
return binascii_a2b_hex_impl(module, hexstr);
12191204
}
12201205

1221-
static const int table_hex[128] = {
1222-
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
1223-
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
1224-
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
1225-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1,
1226-
-1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
1227-
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
1228-
-1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
1229-
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
1230-
};
1231-
1232-
#define hexval(c) table_hex[(unsigned int)(c)]
1233-
12341206
#define MAXLINESIZE 76
12351207

12361208

@@ -1293,9 +1265,9 @@ binascii_a2b_qp_impl(PyObject *module, Py_buffer *data, int header)
12931265
(ascii_data[in+1] >= 'a' && ascii_data[in+1] <= 'f') ||
12941266
(ascii_data[in+1] >= '0' && ascii_data[in+1] <= '9'))) {
12951267
/* hexval */
1296-
ch = hexval(ascii_data[in]) << 4;
1268+
ch = _PyLong_DigitValue[ascii_data[in]] << 4;
12971269
in++;
1298-
ch |= hexval(ascii_data[in]);
1270+
ch |= _PyLong_DigitValue[ascii_data[in]];
12991271
in++;
13001272
odata[out++] = ch;
13011273
}

0 commit comments

Comments
 (0)