From 57a4b4f178698435b584892f69db5d5f2ea396dc Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
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 3b9679a4c..945f4fe46 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 514a6941b..e0a712cb0 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 0330857d0..969f2fcb2 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 bfd048ebb..c6da45728 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 c9d40e55a..633f5d0ca 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 2c71f51cd..8bec4a3e3 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 e444ec7d4..a682144b8 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;
     }
 }
-- 
GitLab