diff options
author | Galen Hazelwood <galenhz@gmail.com> | 2015-07-01 22:15:06 -0700 |
---|---|---|
committer | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2015-07-04 12:26:52 +0300 |
commit | 616986a5f351ed5a014bd25766c12bccbe83d734 (patch) | |
tree | 8209161191589a57df24be10bdc4a32ee7d69d1c | |
parent | b19d273beb2b492fc538e4d9b0bebaf958a206fe (diff) | |
download | micropython-616986a5f351ed5a014bd25766c12bccbe83d734.tar.gz micropython-616986a5f351ed5a014bd25766c12bccbe83d734.zip |
extmod: Add a2b_base64 and b2a_base64 functions to ubinascii.
-rw-r--r-- | extmod/modubinascii.c | 104 | ||||
-rw-r--r-- | extmod/modubinascii.h | 4 | ||||
-rw-r--r-- | py/qstrdefs.h | 2 | ||||
-rw-r--r-- | tests/extmod/ubinascii_a2b_base64.py | 34 | ||||
-rw-r--r-- | tests/extmod/ubinascii_b2a_base64.py | 17 |
5 files changed, 159 insertions, 2 deletions
diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c index 187c2d3d16..e4ae8c1572 100644 --- a/extmod/modubinascii.c +++ b/extmod/modubinascii.c @@ -89,14 +89,114 @@ mp_obj_t mod_binascii_unhexlify(mp_obj_t data) { } MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify); +mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len % 4 != 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "incorrect padding")); + } + + vstr_t vstr; + byte *in = bufinfo.buf; + if (bufinfo.len == 0) { + vstr_init_len(&vstr, 0); + } + else { + vstr_init_len(&vstr, ((bufinfo.len / 4) * 3) - ((in[bufinfo.len-1] == '=') ? ((in[bufinfo.len-2] == '=') ? 2 : 1 ) : 0)); + } + byte *out = (byte*)vstr.buf; + for (mp_uint_t i = bufinfo.len; i; i -= 4) { + char hold[4]; + for (int j = 4; j--;) { + if (in[j] >= 'A' && in[j] <= 'Z') { + hold[j] = in[j] - 'A'; + } else if (in[j] >= 'a' && in[j] <= 'z') { + hold[j] = in[j] - 'a' + 26; + } else if (in[j] >= '0' && in[j] <= '9') { + hold[j] = in[j] - '0' + 52; + } else if (in[j] == '+') { + hold[j] = 62; + } else if (in[j] == '/') { + hold[j] = 63; + } else if (in[j] == '=') { + if (j < 2 || i > 4) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid padding")); + } + hold[j] = 64; + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid character")); + } + } + in += 4; + + *out++ = (hold[0]) << 2 | (hold[1]) >> 4; + if (hold[2] != 64) { + *out++ = (hold[1] & 0x0F) << 4 | hold[2] >> 2; + if (hold[3] != 64) { + *out++ = (hold[2] & 0x03) << 6 | hold[3]; + } + } + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); + +mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); + + vstr_t vstr; + vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + 1); + byte *in = bufinfo.buf, *out = (byte*)vstr.buf; + for (mp_uint_t i = bufinfo.len; i >= 3; i -= 3) { + *out++ = (in[0] & 0xFC) >> 2; + *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4; + *out++ = (in[1] & 0x0F) << 2 | (in[2] & 0xC0) >> 6; + *out++ = in[2] & 0x3F; + in += 3; + } + if (bufinfo.len % 3 != 0) { + *out++ = (in[0] & 0xFC) >> 2; + if (bufinfo.len % 3 == 2) { + *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4; + *out++ = (in[1] & 0x0F) << 2; + } + else { + *out++ = (in[0] & 0x03) << 4; + *out++ = 64; + } + *out++ = 64; + } + out = (byte*)vstr.buf; + for (mp_uint_t i = vstr.len - 1; i--;) { + if (*out < 26) { + *out += 'A'; + } else if (*out < 52) { + *out += 'a' - 26; + } else if (*out < 62) { + *out += '0' - 52; + } else if (*out == 62) { + *out ='+'; + } else if (*out == 63) { + *out = '/'; + } else { + *out = '='; + } + out++; + } + *out = '\n'; + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64); + #if MICROPY_PY_UBINASCII 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_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 }, + { 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 }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); diff --git a/extmod/modubinascii.h b/extmod/modubinascii.h index 36392096c1..94e69b18eb 100644 --- a/extmod/modubinascii.h +++ b/extmod/modubinascii.h @@ -29,8 +29,12 @@ extern mp_obj_t mod_binascii_hexlify(mp_uint_t n_args, const mp_obj_t *args); extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data); +extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data); +extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data); MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj); MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj); +MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj); +MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj); #endif /* MICROPY_EXTMOD_MODUBINASCII */ diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 367aea17bd..48131636f1 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -590,6 +590,8 @@ Q(sha256) Q(ubinascii) Q(hexlify) Q(unhexlify) +Q(a2b_base64) +Q(b2a_base64) #endif #if MICROPY_PY_MACHINE diff --git a/tests/extmod/ubinascii_a2b_base64.py b/tests/extmod/ubinascii_a2b_base64.py new file mode 100644 index 0000000000..1f10b5ab2f --- /dev/null +++ b/tests/extmod/ubinascii_a2b_base64.py @@ -0,0 +1,34 @@ +try: + import ubinascii as binascii +except ImportError: + import binascii + +print(binascii.a2b_base64(b'')) +print(binascii.a2b_base64(b'Zg==')) +print(binascii.a2b_base64(b'Zm8=')) +print(binascii.a2b_base64(b'Zm9v')) +print(binascii.a2b_base64(b'Zm9vYg==')) +print(binascii.a2b_base64(b'Zm9vYmE=')) +print(binascii.a2b_base64(b'Zm9vYmFy')) + +print(binascii.a2b_base64(b'AAECAwQFBgc=')) +print(binascii.a2b_base64(b'CAkKCwwNDg8=')) +print(binascii.a2b_base64(b'f4D/')) +print(binascii.a2b_base64(b'MTIzNEFCQ0RhYmNk')) + +try: + print(binascii.a2b_base64(b'abc')) +except: + print("caught") +try: + print(binascii.a2b_base64(b'abcde=')) +except: + print("caught") +try: + print(binascii.a2b_base64(b'ab*d')) +except: + print("caught") +try: + print(binascii.a2b_base64(b'ab=cdef=')) +except: + print("caught") diff --git a/tests/extmod/ubinascii_b2a_base64.py b/tests/extmod/ubinascii_b2a_base64.py new file mode 100644 index 0000000000..343c28da22 --- /dev/null +++ b/tests/extmod/ubinascii_b2a_base64.py @@ -0,0 +1,17 @@ +try: + import ubinascii as binascii +except ImportError: + import binascii + +print(binascii.b2a_base64(b'')) +print(binascii.b2a_base64(b'f')) +print(binascii.b2a_base64(b'fo')) +print(binascii.b2a_base64(b'foo')) +print(binascii.b2a_base64(b'foob')) +print(binascii.b2a_base64(b'fooba')) +print(binascii.b2a_base64(b'foobar')) + +print(binascii.b2a_base64(b'\x00\x01\x02\x03\x04\x05\x06\x07')) +print(binascii.b2a_base64(b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')) +print(binascii.b2a_base64(b'\x7f\x80\xff')) +print(binascii.b2a_base64(b'1234ABCDabcd')) |