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 /extmod/modubinascii.c | |
parent | b19d273beb2b492fc538e4d9b0bebaf958a206fe (diff) | |
download | micropython-616986a5f351ed5a014bd25766c12bccbe83d734.tar.gz micropython-616986a5f351ed5a014bd25766c12bccbe83d734.zip |
extmod: Add a2b_base64 and b2a_base64 functions to ubinascii.
Diffstat (limited to 'extmod/modubinascii.c')
-rw-r--r-- | extmod/modubinascii.c | 104 |
1 files changed, 102 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); |