diff --git a/py/obj.h b/py/obj.h index d0284e6d21..4745b76443 100644 --- a/py/obj.h +++ b/py/obj.h @@ -228,13 +228,14 @@ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags); void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags); // Stream protocol +#define MP_STREAM_ERROR (-1) typedef struct _mp_stream_p_t { - // On error, functions should return -1 and fill in *errcode (values are - // implementation-dependent, but will be exposed to user, e.g. via exception). - mp_int_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); - mp_int_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode); + // On error, functions should return MP_STREAM_ERROR and fill in *errcode (values + // are implementation-dependent, but will be exposed to user, e.g. via exception). + mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); + mp_uint_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode); // add seek() ? - int is_bytes : 1; + int is_text : 1; // default is bytes, set this for text stream } mp_stream_p_t; struct _mp_obj_type_t { diff --git a/py/objstringio.c b/py/objstringio.c index bffdf2cf79..70f0c68dd4 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -51,7 +51,7 @@ STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void print(env, self->base.type == &mp_type_stringio ? "" : "", self->vstr); } -STATIC mp_int_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_stringio_t *o = o_in; mp_uint_t remaining = o->vstr->len - o->pos; if (size > remaining) { @@ -62,7 +62,7 @@ STATIC mp_int_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *err return size; } -STATIC mp_int_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_stringio_t *o = o_in; mp_uint_t remaining = o->vstr->alloc - o->pos; if (size > remaining) { @@ -137,12 +137,12 @@ STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); STATIC const mp_stream_p_t stringio_stream_p = { .read = stringio_read, .write = stringio_write, + .is_text = true, }; STATIC const mp_stream_p_t bytesio_stream_p = { .read = stringio_read, .write = stringio_write, - .is_bytes = true, }; const mp_obj_type_t mp_type_stringio = { diff --git a/py/stream.c b/py/stream.c index ad5855c706..09c39bdf4a 100644 --- a/py/stream.c +++ b/py/stream.c @@ -58,7 +58,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in); #define is_nonblocking_error(errno) (0) #endif -#define STREAM_CONTENT_TYPE(stream) (((stream)->is_bytes) ? &mp_type_bytes : &mp_type_str) +#define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes) STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; @@ -76,7 +76,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { } #if MICROPY_PY_BUILTINS_STR_UNICODE - if (!o->type->stream_p->is_bytes) { + if (o->type->stream_p->is_text) { // We need to read sz number of unicode characters. Because we don't have any // buffering, and because the stream API can only read bytes, we must read here // in units of bytes and must never over read. If we want sz chars, then reading @@ -96,8 +96,8 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory")); } int error; - mp_int_t out_sz = o->type->stream_p->read(o, p, more_bytes, &error); - if (out_sz == -1) { + mp_uint_t out_sz = o->type->stream_p->read(o, p, more_bytes, &error); + if (out_sz == MP_STREAM_ERROR) { vstr_cut_tail_bytes(&vstr, more_bytes); if (is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. @@ -113,7 +113,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } - if ((mp_uint_t)out_sz < more_bytes) { + if (out_sz < more_bytes) { // Finish reading. // TODO what if we have read only half a non-ASCII char? vstr_cut_tail_bytes(&vstr, more_bytes - out_sz); @@ -168,8 +168,8 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { byte *buf = m_new(byte, sz); int error; - mp_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error); - if (out_sz == -1) { + mp_uint_t out_sz = o->type->stream_p->read(o, buf, sz, &error); + if (out_sz == MP_STREAM_ERROR) { if (is_nonblocking_error(error)) { // https://docs.python.org/3.4/library/io.html#io.RawIOBase.read // "If the object is in non-blocking mode and no bytes are available, @@ -194,8 +194,8 @@ mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t len) { } int error; - mp_int_t out_sz = o->type->stream_p->write(self_in, buf, len, &error); - if (out_sz == -1) { + mp_uint_t out_sz = o->type->stream_p->write(self_in, buf, len, &error); + if (out_sz == MP_STREAM_ERROR) { if (is_nonblocking_error(error)) { // http://docs.python.org/3/library/io.html#io.RawIOBase.write // "None is returned if the raw stream is set not to block and @@ -230,8 +230,8 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { int error; int current_read = DEFAULT_BUFFER_SIZE; while (true) { - mp_int_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error); - if (out_sz == -1) { + mp_uint_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error); + if (out_sz == MP_STREAM_ERROR) { if (is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. // If we read nothing, return None, just like read(). @@ -292,16 +292,15 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory")); } - mp_int_t out_sz = o->type->stream_p->read(o, p, 1, &error); - if (out_sz == -1) { + mp_uint_t out_sz = o->type->stream_p->read(o, p, 1, &error); + if (out_sz == MP_STREAM_ERROR) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } if (out_sz == 0) { // Back out previously added byte - // TODO: This is a bit hacky, does it supported by vstr API contract? // Consider, what's better - read a char and get OutOfMemory (so read // char is lost), or allocate first as we do. - vstr_add_len(vstr, -1); + vstr_cut_tail_bytes(vstr, 1); break; } if (*p == '\n') { diff --git a/stmhal/file.c b/stmhal/file.c index c1a2924903..db6d08e5e5 100644 --- a/stmhal/file.c +++ b/stmhal/file.c @@ -73,24 +73,24 @@ void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, m print(env, "", mp_obj_get_type_str(self_in), self_in); } -STATIC mp_int_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { pyb_file_obj_t *self = self_in; UINT sz_out; FRESULT res = f_read(&self->fp, buf, size, &sz_out); if (res != FR_OK) { *errcode = fresult_to_errno_table[res]; - return -1; + return MP_STREAM_ERROR; } return sz_out; } -STATIC mp_int_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { pyb_file_obj_t *self = self_in; UINT sz_out; FRESULT res = f_write(&self->fp, buf, size, &sz_out); if (res != FR_OK) { *errcode = fresult_to_errno_table[res]; - return -1; + return MP_STREAM_ERROR; } return sz_out; } @@ -240,7 +240,6 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); STATIC const mp_stream_p_t fileio_stream_p = { .read = file_obj_read, .write = file_obj_write, - .is_bytes = true, }; const mp_obj_type_t mp_type_fileio = { @@ -258,6 +257,7 @@ const mp_obj_type_t mp_type_fileio = { STATIC const mp_stream_p_t textio_stream_p = { .read = file_obj_read, .write = file_obj_write, + .is_text = true, }; const mp_obj_type_t mp_type_textio = { diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c index 9846ce0453..88f47d1b44 100644 --- a/stmhal/pybstdio.c +++ b/stmhal/pybstdio.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "mpconfig.h" #include "misc.h" @@ -109,7 +110,7 @@ void stdio_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, print(env, "", self->fd); } -STATIC mp_int_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { pyb_stdio_obj_t *self = self_in; if (self->fd == STDIO_FD_IN) { for (uint i = 0; i < size; i++) { @@ -119,23 +120,21 @@ STATIC mp_int_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *err } ((byte*)buf)[i] = c; } - *errcode = 0; return size; } else { - *errcode = 1; - return 0; + *errcode = EPERM; + return MP_STREAM_ERROR; } } -STATIC mp_int_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { pyb_stdio_obj_t *self = self_in; if (self->fd == STDIO_FD_OUT || self->fd == STDIO_FD_ERR) { stdout_tx_strn_cooked(buf, size); - *errcode = 0; return size; } else { - *errcode = 1; - return 0; + *errcode = EPERM; + return MP_STREAM_ERROR; } } @@ -162,6 +161,7 @@ STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); STATIC const mp_stream_p_t stdio_obj_stream_p = { .read = stdio_read, .write = stdio_write, + .is_text = true, }; STATIC const mp_obj_type_t stdio_obj_type = { diff --git a/unix/file.c b/unix/file.c index 7cf0a51932..cdec1ad1af 100644 --- a/unix/file.c +++ b/unix/file.c @@ -66,22 +66,24 @@ STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *e print(env, "", mp_obj_get_type_str(self), self->fd); } -STATIC mp_int_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = o_in; check_fd_is_open(o); mp_int_t r = read(o->fd, buf, size); if (r == -1) { *errcode = errno; + return MP_STREAM_ERROR; } return r; } -STATIC mp_int_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = o_in; check_fd_is_open(o); mp_int_t r = write(o->fd, buf, size); if (r == -1) { *errcode = errno; + return MP_STREAM_ERROR; } return r; } @@ -190,7 +192,6 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); STATIC const mp_stream_p_t fileio_stream_p = { .read = fdfile_read, .write = fdfile_write, - .is_bytes = true, }; const mp_obj_type_t mp_type_fileio = { @@ -208,6 +209,7 @@ const mp_obj_type_t mp_type_fileio = { STATIC const mp_stream_p_t textio_stream_p = { .read = fdfile_read, .write = fdfile_write, + .is_text = true, }; const mp_obj_type_t mp_type_textio = { diff --git a/unix/modsocket.c b/unix/modsocket.c index 160a1dcc02..a3380fb89a 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -91,20 +91,22 @@ STATIC void socket_print(void (*print)(void *env, const char *fmt, ...), void *e print(env, "<_socket %d>", self->fd); } -STATIC mp_int_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = o_in; mp_int_t r = read(o->fd, buf, size); if (r == -1) { *errcode = errno; + return MP_STREAM_ERROR; } return r; } -STATIC mp_int_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = o_in; mp_int_t r = write(o->fd, buf, size); if (r == -1) { *errcode = errno; + return MP_STREAM_ERROR; } return r; }