From 57a4b4f178698435b584892f69db5d5f2ea396dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Apr 2014 22:29:21 +0100 Subject: [PATCH] py: Add typecode to buffer protocol. When querying an object that supports the buffer protocol, that object must now return a typecode (as per binary.[ch]). This does not have to be honoured by the caller, but can be useful for determining element size. --- py/modstruct.c | 2 +- py/obj.c | 10 +++++----- py/obj.h | 24 ++++++++++-------------- py/objarray.c | 3 ++- py/objfun.c | 2 +- py/objint.c | 2 +- py/objstr.c | 6 ++++-- 7 files changed, 24 insertions(+), 25 deletions(-) diff --git a/py/modstruct.c b/py/modstruct.c index 3b9679a4c2..945f4fe461 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -55,7 +55,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) { char fmt_type = get_fmt_type(&fmt); uint size = calcsize_items(fmt); mp_obj_tuple_t *res = mp_obj_new_tuple(size, NULL); - buffer_info_t bufinfo; + mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo); byte *p = bufinfo.buf; diff --git a/py/obj.c b/py/obj.c index 514a6941b9..e0a712cb01 100644 --- a/py/obj.c +++ b/py/obj.c @@ -357,20 +357,20 @@ mp_obj_t mp_identity(mp_obj_t self) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); -bool mp_get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) { +bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo) { mp_obj_type_t *type = mp_obj_get_type(obj); if (type->buffer_p.get_buffer == NULL) { return false; } - type->buffer_p.get_buffer(obj, bufinfo, BUFFER_READ); - if (bufinfo->buf == NULL) { + int ret = type->buffer_p.get_buffer(obj, bufinfo, MP_BUFFER_READ); + if (ret != 0 || bufinfo->buf == NULL) { return false; } return true; } -void mp_get_buffer_raise(mp_obj_t obj, buffer_info_t *bufinfo) { +void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo) { if (!mp_get_buffer(obj, bufinfo)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Object with buffer protocol required")); + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object with buffer protocol required")); } } diff --git a/py/obj.h b/py/obj.h index 0330857d0b..969f2fcb29 100644 --- a/py/obj.h +++ b/py/obj.h @@ -189,32 +189,28 @@ typedef struct _mp_method_t { } mp_method_t; // Buffer protocol -typedef struct _buffer_info_t { +typedef struct _mp_buffer_info_t { // if we'd bother to support various versions of structure // (with different number of fields), we can distinguish // them with ver = sizeof(struct). Cons: overkill for *micro*? //int ver; // ? void *buf; - machine_int_t len; - - // Rationale: have array.array and have SIMD operations on them - // Cons: users can pass item size to processing functions themselves, - // though that's not "plug&play" - // int itemsize; + machine_int_t len; // in bytes + int typecode; // as per binary.h // Rationale: to load arbitrary-sized sprites directly to LCD // Cons: a bit adhoc usecase // int stride; -} buffer_info_t; -#define BUFFER_READ (1) -#define BUFFER_WRITE (2) -#define BUFFER_RW (BUFFER_READ | BUFFER_WRITE) +} mp_buffer_info_t; +#define MP_BUFFER_READ (1) +#define MP_BUFFER_WRITE (2) +#define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE) typedef struct _mp_buffer_p_t { - machine_int_t (*get_buffer)(mp_obj_t obj, buffer_info_t *bufinfo, int flags); + machine_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags); } mp_buffer_p_t; -bool mp_get_buffer(mp_obj_t obj, buffer_info_t *bufinfo); -void mp_get_buffer_raise(mp_obj_t obj, buffer_info_t *bufinfo); +bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo); +void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo); // Stream protocol typedef struct _mp_stream_p_t { diff --git a/py/objarray.c b/py/objarray.c index bfd048ebb9..c6da45728a 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -151,10 +151,11 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value } } -STATIC machine_int_t array_get_buffer(mp_obj_t o_in, buffer_info_t *bufinfo, int flags) { +STATIC machine_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, int flags) { mp_obj_array_t *o = o_in; bufinfo->buf = o->items; bufinfo->len = o->len * mp_binary_get_size(o->typecode); + bufinfo->typecode = o->typecode; return 0; } diff --git a/py/objfun.c b/py/objfun.c index c9d40e55a3..633f5d0cae 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -426,7 +426,7 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { mp_obj_list_get(obj, &len, &items); return (machine_uint_t)items; } else { - buffer_info_t bufinfo; + mp_buffer_info_t bufinfo; if (mp_get_buffer(obj, &bufinfo)) { // supports the buffer protocol, return a pointer to the data return (machine_uint_t)bufinfo.buf; diff --git a/py/objint.c b/py/objint.c index 2c71f51cd1..8bec4a3e3f 100644 --- a/py/objint.c +++ b/py/objint.c @@ -272,7 +272,7 @@ STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) { // TODO: Support signed param (assumes signed=False at the moment) // get the buffer info - buffer_info_t bufinfo; + mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo); // convert the bytes to an integer diff --git a/py/objstr.c b/py/objstr.c index e444ec7d41..a682144b8f 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1326,16 +1326,18 @@ STATIC mp_obj_t str_encode(uint n_args, const mp_obj_t *args) { } #endif -STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, int flags) { - if (flags == BUFFER_READ) { +STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) { + if (flags == MP_BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); bufinfo->buf = (void*)str_data; bufinfo->len = str_len; + bufinfo->typecode = 'b'; return 0; } else { // can't write to a string bufinfo->buf = NULL; bufinfo->len = 0; + bufinfo->typecode = -1; return 1; } }