summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--docs/library/ubinascii.rst5
-rw-r--r--extmod/modubinascii.c33
-rw-r--r--py/lexer.c12
-rw-r--r--py/misc.h1
-rw-r--r--py/qstrdefs.h1
-rw-r--r--py/unicode.c10
-rw-r--r--tests/extmod/ubinascii_unhexlify.py9
7 files changed, 59 insertions, 12 deletions
diff --git a/docs/library/ubinascii.rst b/docs/library/ubinascii.rst
index 9dba9180d2..a6327ea308 100644
--- a/docs/library/ubinascii.rst
+++ b/docs/library/ubinascii.rst
@@ -13,3 +13,8 @@ Functions
.. function:: hexlify(data)
Convert binary data to hexadecimal representation. Return bytes string.
+
+.. function:: unhexlify(data)
+
+ Convert hexadecimal data to binary representation. Return bytes string.
+ (i.e. inverse of hexlify)
diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c
index e258818af4..5e366cae89 100644
--- a/extmod/modubinascii.c
+++ b/extmod/modubinascii.c
@@ -35,6 +35,8 @@
#if MICROPY_PY_UBINASCII
STATIC mp_obj_t mod_binascii_hexlify(mp_uint_t n_args, const mp_obj_t *args) {
+ // Second argument is for an extension to allow a separator to be used
+ // between values.
(void)n_args;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
@@ -58,10 +60,39 @@ STATIC mp_obj_t mod_binascii_hexlify(mp_uint_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify);
+STATIC mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
+
+ if ((bufinfo.len & 1) != 0) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "odd-length string"));
+ }
+ vstr_t vstr;
+ vstr_init_len(&vstr, bufinfo.len / 2);
+ byte *in = bufinfo.buf, *out = (byte*)vstr.buf;
+ byte hex_byte = 0;
+ for (mp_uint_t i = bufinfo.len; i--;) {
+ byte hex_ch = *in++;
+ if (unichar_isxdigit(hex_ch)) {
+ hex_byte += unichar_xdigit_value(hex_ch);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "non-hex digit found"));
+ }
+ if (i & 1) {
+ hex_byte <<= 4;
+ } else {
+ *out++ = hex_byte;
+ hex_byte = 0;
+ }
+ }
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify);
+
STATIC const mp_map_elem_t mp_module_binascii_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_hexlify), (mp_obj_t)&mod_binascii_hexlify_obj },
-// { MP_OBJ_NEW_QSTR(MP_QSTR_unhexlify), (mp_obj_t)&mod_binascii_unhexlify_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_unhexlify), (mp_obj_t)&mod_binascii_unhexlify_obj },
// { MP_OBJ_NEW_QSTR(MP_QSTR_a2b_base64), (mp_obj_t)&mod_binascii_a2b_base64_obj },
// { MP_OBJ_NEW_QSTR(MP_QSTR_b2a_base64), (mp_obj_t)&mod_binascii_b2a_base64_obj },
};
diff --git a/py/lexer.c b/py/lexer.c
index 536208e41f..12cb5ae5b2 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -261,16 +261,6 @@ STATIC const char *tok_kw[] = {
"__debug__",
};
-STATIC mp_uint_t hex_digit(unichar c) {
- // c is assumed to be hex digit
- mp_uint_t n = c - '0';
- if (n > 9) {
- n &= ~('a' - 'A');
- n -= ('A' - ('9' + 1));
- }
- return n;
-}
-
// This is called with CUR_CHAR() before first hex digit, and should return with
// it pointing to last hex digit
// num_digits must be greater than zero
@@ -282,7 +272,7 @@ STATIC bool get_hex(mp_lexer_t *lex, mp_uint_t num_digits, mp_uint_t *result) {
if (!unichar_isxdigit(c)) {
return false;
}
- num = (num << 4) + hex_digit(c);
+ num = (num << 4) + unichar_xdigit_value(c);
}
*result = num;
return true;
diff --git a/py/misc.h b/py/misc.h
index 2c00b6880f..91bd000961 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -127,6 +127,7 @@ bool unichar_isupper(unichar c);
bool unichar_islower(unichar c);
unichar unichar_tolower(unichar c);
unichar unichar_toupper(unichar c);
+mp_uint_t unichar_xdigit_value(unichar c);
mp_uint_t unichar_charlen(const char *str, mp_uint_t len);
#define UTF8_IS_NONASCII(ch) ((ch) & 0x80)
#define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80)
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 5d0dc9d274..a5e543bbbc 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -584,6 +584,7 @@ Q(sha256)
#if MICROPY_PY_UBINASCII
Q(ubinascii)
Q(hexlify)
+Q(unhexlify)
#endif
#if MICROPY_PY_MACHINE
diff --git a/py/unicode.c b/py/unicode.c
index db4aa438ac..63e9601185 100644
--- a/py/unicode.c
+++ b/py/unicode.c
@@ -169,3 +169,13 @@ unichar unichar_toupper(unichar c) {
}
return c;
}
+
+mp_uint_t unichar_xdigit_value(unichar c) {
+ // c is assumed to be hex digit
+ mp_uint_t n = c - '0';
+ if (n > 9) {
+ n &= ~('a' - 'A');
+ n -= ('A' - ('9' + 1));
+ }
+ return n;
+}
diff --git a/tests/extmod/ubinascii_unhexlify.py b/tests/extmod/ubinascii_unhexlify.py
new file mode 100644
index 0000000000..1ec6972c5b
--- /dev/null
+++ b/tests/extmod/ubinascii_unhexlify.py
@@ -0,0 +1,9 @@
+try:
+ import ubinascii as binascii
+except ImportError:
+ import binascii
+
+print(binascii.unhexlify(b'0001020304050607'))
+print(binascii.unhexlify(b'08090a0b0c0d0e0f'))
+print(binascii.unhexlify(b'7f80ff'))
+print(binascii.unhexlify(b'313233344142434461626364'))