Skip to content

Commit 616986a

Browse files
galenhzpfalcon
authored andcommitted
extmod: Add a2b_base64 and b2a_base64 functions to ubinascii.
1 parent b19d273 commit 616986a

5 files changed

Lines changed: 159 additions & 2 deletions

File tree

extmod/modubinascii.c

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,114 @@ mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
8989
}
9090
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify);
9191

92+
mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
93+
mp_buffer_info_t bufinfo;
94+
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
95+
if (bufinfo.len % 4 != 0) {
96+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "incorrect padding"));
97+
}
98+
99+
vstr_t vstr;
100+
byte *in = bufinfo.buf;
101+
if (bufinfo.len == 0) {
102+
vstr_init_len(&vstr, 0);
103+
}
104+
else {
105+
vstr_init_len(&vstr, ((bufinfo.len / 4) * 3) - ((in[bufinfo.len-1] == '=') ? ((in[bufinfo.len-2] == '=') ? 2 : 1 ) : 0));
106+
}
107+
byte *out = (byte*)vstr.buf;
108+
for (mp_uint_t i = bufinfo.len; i; i -= 4) {
109+
char hold[4];
110+
for (int j = 4; j--;) {
111+
if (in[j] >= 'A' && in[j] <= 'Z') {
112+
hold[j] = in[j] - 'A';
113+
} else if (in[j] >= 'a' && in[j] <= 'z') {
114+
hold[j] = in[j] - 'a' + 26;
115+
} else if (in[j] >= '0' && in[j] <= '9') {
116+
hold[j] = in[j] - '0' + 52;
117+
} else if (in[j] == '+') {
118+
hold[j] = 62;
119+
} else if (in[j] == '/') {
120+
hold[j] = 63;
121+
} else if (in[j] == '=') {
122+
if (j < 2 || i > 4) {
123+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid padding"));
124+
}
125+
hold[j] = 64;
126+
} else {
127+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid character"));
128+
}
129+
}
130+
in += 4;
131+
132+
*out++ = (hold[0]) << 2 | (hold[1]) >> 4;
133+
if (hold[2] != 64) {
134+
*out++ = (hold[1] & 0x0F) << 4 | hold[2] >> 2;
135+
if (hold[3] != 64) {
136+
*out++ = (hold[2] & 0x03) << 6 | hold[3];
137+
}
138+
}
139+
}
140+
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
141+
}
142+
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
143+
144+
mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
145+
mp_buffer_info_t bufinfo;
146+
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
147+
148+
vstr_t vstr;
149+
vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + 1);
150+
byte *in = bufinfo.buf, *out = (byte*)vstr.buf;
151+
for (mp_uint_t i = bufinfo.len; i >= 3; i -= 3) {
152+
*out++ = (in[0] & 0xFC) >> 2;
153+
*out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
154+
*out++ = (in[1] & 0x0F) << 2 | (in[2] & 0xC0) >> 6;
155+
*out++ = in[2] & 0x3F;
156+
in += 3;
157+
}
158+
if (bufinfo.len % 3 != 0) {
159+
*out++ = (in[0] & 0xFC) >> 2;
160+
if (bufinfo.len % 3 == 2) {
161+
*out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
162+
*out++ = (in[1] & 0x0F) << 2;
163+
}
164+
else {
165+
*out++ = (in[0] & 0x03) << 4;
166+
*out++ = 64;
167+
}
168+
*out++ = 64;
169+
}
170+
out = (byte*)vstr.buf;
171+
for (mp_uint_t i = vstr.len - 1; i--;) {
172+
if (*out < 26) {
173+
*out += 'A';
174+
} else if (*out < 52) {
175+
*out += 'a' - 26;
176+
} else if (*out < 62) {
177+
*out += '0' - 52;
178+
} else if (*out == 62) {
179+
*out ='+';
180+
} else if (*out == 63) {
181+
*out = '/';
182+
} else {
183+
*out = '=';
184+
}
185+
out++;
186+
}
187+
*out = '\n';
188+
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
189+
}
190+
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
191+
92192
#if MICROPY_PY_UBINASCII
93193

94194
STATIC const mp_map_elem_t mp_module_binascii_globals_table[] = {
95195
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii) },
96196
{ MP_OBJ_NEW_QSTR(MP_QSTR_hexlify), (mp_obj_t)&mod_binascii_hexlify_obj },
97197
{ MP_OBJ_NEW_QSTR(MP_QSTR_unhexlify), (mp_obj_t)&mod_binascii_unhexlify_obj },
98-
// { MP_OBJ_NEW_QSTR(MP_QSTR_a2b_base64), (mp_obj_t)&mod_binascii_a2b_base64_obj },
99-
// { MP_OBJ_NEW_QSTR(MP_QSTR_b2a_base64), (mp_obj_t)&mod_binascii_b2a_base64_obj },
198+
{ MP_OBJ_NEW_QSTR(MP_QSTR_a2b_base64), (mp_obj_t)&mod_binascii_a2b_base64_obj },
199+
{ MP_OBJ_NEW_QSTR(MP_QSTR_b2a_base64), (mp_obj_t)&mod_binascii_b2a_base64_obj },
100200
};
101201

102202
STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);

extmod/modubinascii.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@
2929

3030
extern mp_obj_t mod_binascii_hexlify(mp_uint_t n_args, const mp_obj_t *args);
3131
extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data);
32+
extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data);
33+
extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data);
3234

3335
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj);
3436
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj);
37+
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj);
38+
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj);
3539

3640
#endif /* MICROPY_EXTMOD_MODUBINASCII */

py/qstrdefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,8 @@ Q(sha256)
590590
Q(ubinascii)
591591
Q(hexlify)
592592
Q(unhexlify)
593+
Q(a2b_base64)
594+
Q(b2a_base64)
593595
#endif
594596

595597
#if MICROPY_PY_MACHINE
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
try:
2+
import ubinascii as binascii
3+
except ImportError:
4+
import binascii
5+
6+
print(binascii.a2b_base64(b''))
7+
print(binascii.a2b_base64(b'Zg=='))
8+
print(binascii.a2b_base64(b'Zm8='))
9+
print(binascii.a2b_base64(b'Zm9v'))
10+
print(binascii.a2b_base64(b'Zm9vYg=='))
11+
print(binascii.a2b_base64(b'Zm9vYmE='))
12+
print(binascii.a2b_base64(b'Zm9vYmFy'))
13+
14+
print(binascii.a2b_base64(b'AAECAwQFBgc='))
15+
print(binascii.a2b_base64(b'CAkKCwwNDg8='))
16+
print(binascii.a2b_base64(b'f4D/'))
17+
print(binascii.a2b_base64(b'MTIzNEFCQ0RhYmNk'))
18+
19+
try:
20+
print(binascii.a2b_base64(b'abc'))
21+
except:
22+
print("caught")
23+
try:
24+
print(binascii.a2b_base64(b'abcde='))
25+
except:
26+
print("caught")
27+
try:
28+
print(binascii.a2b_base64(b'ab*d'))
29+
except:
30+
print("caught")
31+
try:
32+
print(binascii.a2b_base64(b'ab=cdef='))
33+
except:
34+
print("caught")
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
try:
2+
import ubinascii as binascii
3+
except ImportError:
4+
import binascii
5+
6+
print(binascii.b2a_base64(b''))
7+
print(binascii.b2a_base64(b'f'))
8+
print(binascii.b2a_base64(b'fo'))
9+
print(binascii.b2a_base64(b'foo'))
10+
print(binascii.b2a_base64(b'foob'))
11+
print(binascii.b2a_base64(b'fooba'))
12+
print(binascii.b2a_base64(b'foobar'))
13+
14+
print(binascii.b2a_base64(b'\x00\x01\x02\x03\x04\x05\x06\x07'))
15+
print(binascii.b2a_base64(b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'))
16+
print(binascii.b2a_base64(b'\x7f\x80\xff'))
17+
print(binascii.b2a_base64(b'1234ABCDabcd'))

0 commit comments

Comments
 (0)