py: Make 'bytes' be a proper type, support standard constructor args.
This commit is contained in:
parent
be020c27a8
commit
1ecea7c753
12
py/builtin.c
12
py/builtin.c
@ -375,18 +375,6 @@ STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *k
|
|||||||
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
|
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
|
||||||
|
|
||||||
// TODO: This should be type, this is just quick CPython compat hack
|
|
||||||
STATIC mp_obj_t mp_builtin_bytes(uint n_args, const mp_obj_t *args) {
|
|
||||||
if (!MP_OBJ_IS_QSTR(args[0]) && !MP_OBJ_IS_TYPE(args[0], &str_type)) {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
// Currently, MicroPython strings are mix between CPython byte and unicode
|
|
||||||
// strings. So, conversion is null so far.
|
|
||||||
return args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_bytes_obj, 1, 3, mp_builtin_bytes);
|
|
||||||
|
|
||||||
STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
|
STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
|
||||||
return mp_obj_new_int((machine_int_t)o_in);
|
return mp_obj_new_int((machine_int_t)o_in);
|
||||||
}
|
}
|
||||||
|
77
py/objstr.c
77
py/objstr.c
@ -17,6 +17,8 @@ typedef struct _mp_obj_str_t {
|
|||||||
const byte *data;
|
const byte *data;
|
||||||
} mp_obj_str_t;
|
} mp_obj_str_t;
|
||||||
|
|
||||||
|
const mp_obj_t mp_const_empty_bytes;
|
||||||
|
|
||||||
// use this macro to extract the string hash
|
// use this macro to extract the string hash
|
||||||
#define GET_STR_HASH(str_obj_in, str_hash) uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
|
#define GET_STR_HASH(str_obj_in, str_hash) uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
|
||||||
|
|
||||||
@ -113,6 +115,75 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||||
|
if (n_args == 0) {
|
||||||
|
return mp_const_empty_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MP_OBJ_IS_STR(args[0])) {
|
||||||
|
if (n_args < 2 || n_args > 3) {
|
||||||
|
goto wrong_args;
|
||||||
|
}
|
||||||
|
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||||
|
GET_STR_HASH(args[0], str_hash);
|
||||||
|
mp_obj_str_t *o = str_new(&bytes_type, NULL, str_len);
|
||||||
|
o->data = str_data;
|
||||||
|
o->hash = str_hash;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_args > 1) {
|
||||||
|
goto wrong_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MP_OBJ_IS_SMALL_INT(args[0])) {
|
||||||
|
uint len = MP_OBJ_SMALL_INT_VALUE(args[0]);
|
||||||
|
byte *data;
|
||||||
|
|
||||||
|
mp_obj_t o = mp_obj_str_builder_start(&bytes_type, len, &data);
|
||||||
|
memset(data, 0, len);
|
||||||
|
return mp_obj_str_builder_end(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
byte *data;
|
||||||
|
vstr_t *vstr = NULL;
|
||||||
|
mp_obj_t o = NULL;
|
||||||
|
// Try to create array of exact len if initializer len is known
|
||||||
|
mp_obj_t len_in = mp_obj_len_maybe(args[0]);
|
||||||
|
if (len_in == MP_OBJ_NULL) {
|
||||||
|
len = -1;
|
||||||
|
vstr = vstr_new();
|
||||||
|
} else {
|
||||||
|
len = MP_OBJ_SMALL_INT_VALUE(len_in);
|
||||||
|
o = mp_obj_str_builder_start(&bytes_type, len, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t iterable = rt_getiter(args[0]);
|
||||||
|
mp_obj_t item;
|
||||||
|
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
|
||||||
|
if (len == -1) {
|
||||||
|
vstr_add_char(vstr, MP_OBJ_SMALL_INT_VALUE(item));
|
||||||
|
} else {
|
||||||
|
*data++ = MP_OBJ_SMALL_INT_VALUE(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == -1) {
|
||||||
|
vstr_shrink(vstr);
|
||||||
|
// TODO: Optimize, borrow buffer from vstr
|
||||||
|
len = vstr_len(vstr);
|
||||||
|
o = mp_obj_str_builder_start(&bytes_type, len, &data);
|
||||||
|
memcpy(data, vstr_str(vstr), len);
|
||||||
|
vstr_free(vstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mp_obj_str_builder_end(o);
|
||||||
|
|
||||||
|
wrong_args:
|
||||||
|
nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments"));
|
||||||
|
}
|
||||||
|
|
||||||
// like strstr but with specified length and allows \0 bytes
|
// like strstr but with specified length and allows \0 bytes
|
||||||
// TODO replace with something more efficient/standard
|
// TODO replace with something more efficient/standard
|
||||||
STATIC const byte *find_subbytes(const byte *haystack, uint hlen, const byte *needle, uint nlen) {
|
STATIC const byte *find_subbytes(const byte *haystack, uint hlen, const byte *needle, uint nlen) {
|
||||||
@ -666,11 +737,16 @@ const mp_obj_type_t bytes_type = {
|
|||||||
{ &mp_type_type },
|
{ &mp_type_type },
|
||||||
.name = MP_QSTR_bytes,
|
.name = MP_QSTR_bytes,
|
||||||
.print = str_print,
|
.print = str_print,
|
||||||
|
.make_new = bytes_make_new,
|
||||||
.binary_op = str_binary_op,
|
.binary_op = str_binary_op,
|
||||||
.getiter = mp_obj_new_bytes_iterator,
|
.getiter = mp_obj_new_bytes_iterator,
|
||||||
.methods = str_type_methods,
|
.methods = str_type_methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// the zero-length bytes
|
||||||
|
STATIC const mp_obj_str_t empty_bytes_obj = {{&bytes_type}, 0, 0, NULL};
|
||||||
|
const mp_obj_t mp_const_empty_bytes = (mp_obj_t)&empty_bytes_obj;
|
||||||
|
|
||||||
mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **data) {
|
mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **data) {
|
||||||
mp_obj_str_t *o = m_new_obj(mp_obj_str_t);
|
mp_obj_str_t *o = m_new_obj(mp_obj_str_t);
|
||||||
o->base.type = type;
|
o->base.type = type;
|
||||||
@ -682,7 +758,6 @@ mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **da
|
|||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t mp_obj_str_builder_end(mp_obj_t o_in) {
|
mp_obj_t mp_obj_str_builder_end(mp_obj_t o_in) {
|
||||||
assert(MP_OBJ_IS_STR(o_in));
|
|
||||||
mp_obj_str_t *o = o_in;
|
mp_obj_str_t *o = o_in;
|
||||||
o->hash = qstr_compute_hash(o->data, o->len);
|
o->hash = qstr_compute_hash(o->data, o->len);
|
||||||
byte *p = (byte*)o->data;
|
byte *p = (byte*)o->data;
|
||||||
|
@ -89,6 +89,7 @@ STATIC const mp_builtin_elem_t builtin_table[] = {
|
|||||||
|
|
||||||
// built-in types
|
// built-in types
|
||||||
{ MP_QSTR_bool, (mp_obj_t)&bool_type },
|
{ MP_QSTR_bool, (mp_obj_t)&bool_type },
|
||||||
|
{ MP_QSTR_bytes, (mp_obj_t)&bytes_type },
|
||||||
#if MICROPY_ENABLE_FLOAT
|
#if MICROPY_ENABLE_FLOAT
|
||||||
{ MP_QSTR_complex, (mp_obj_t)&mp_type_complex },
|
{ MP_QSTR_complex, (mp_obj_t)&mp_type_complex },
|
||||||
#endif
|
#endif
|
||||||
@ -115,7 +116,6 @@ STATIC const mp_builtin_elem_t builtin_table[] = {
|
|||||||
{ MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj },
|
{ MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj },
|
||||||
{ MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj },
|
{ MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj },
|
||||||
{ MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj },
|
{ MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj },
|
||||||
{ MP_QSTR_bytes, (mp_obj_t)&mp_builtin_bytes_obj },
|
|
||||||
{ MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj },
|
{ MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj },
|
||||||
{ MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj },
|
{ MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj },
|
||||||
{ MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj },
|
{ MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj },
|
||||||
|
@ -4,8 +4,36 @@ print(str(a))
|
|||||||
print(repr(a))
|
print(repr(a))
|
||||||
print(a[0], a[2])
|
print(a[0], a[2])
|
||||||
print(a[-1])
|
print(a[-1])
|
||||||
|
print(str(a, "utf-8"))
|
||||||
|
print(str(a, "utf-8", "ignore"))
|
||||||
|
try:
|
||||||
|
str(a, "utf-8", "ignore", "toomuch")
|
||||||
|
except TypeError:
|
||||||
|
print("TypeError")
|
||||||
|
|
||||||
s = 0
|
s = 0
|
||||||
for i in a:
|
for i in a:
|
||||||
s += i
|
s += i
|
||||||
print(s)
|
print(s)
|
||||||
|
|
||||||
|
|
||||||
|
print(bytes("abc", "utf-8"))
|
||||||
|
print(bytes("abc", "utf-8", "replace"))
|
||||||
|
try:
|
||||||
|
bytes("abc")
|
||||||
|
except TypeError:
|
||||||
|
print("TypeError")
|
||||||
|
try:
|
||||||
|
bytes("abc", "utf-8", "replace", "toomuch")
|
||||||
|
except TypeError:
|
||||||
|
print("TypeError")
|
||||||
|
|
||||||
|
print(bytes(3))
|
||||||
|
|
||||||
|
print(bytes([3, 2, 1]))
|
||||||
|
print(bytes(range(5)))
|
||||||
|
|
||||||
|
def gen():
|
||||||
|
for i in range(4):
|
||||||
|
yield i
|
||||||
|
print(bytes(gen()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user