diff options
Diffstat (limited to 'py')
| -rw-r--r-- | py/modio.c | 2 | ||||
| -rw-r--r-- | py/objstringio.c | 2 | ||||
| -rw-r--r-- | py/proto.c | 50 | ||||
| -rw-r--r-- | py/proto.h | 43 | ||||
| -rw-r--r-- | py/py.mk | 1 | ||||
| -rw-r--r-- | py/stream.c | 11 | ||||
| -rw-r--r-- | py/stream.h | 4 |
7 files changed, 106 insertions, 7 deletions
diff --git a/py/modio.c b/py/modio.c index d7c1a58a8..17840a6d8 100644 --- a/py/modio.c +++ b/py/modio.c @@ -90,6 +90,7 @@ STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, in } STATIC const mp_stream_p_t iobase_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = iobase_read, .write = iobase_write, .ioctl = iobase_ioctl, @@ -185,6 +186,7 @@ STATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table); STATIC const mp_stream_p_t bufwriter_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .write = bufwriter_write, }; diff --git a/py/objstringio.c b/py/objstringio.c index d2ca6decd..178e6446c 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -240,6 +240,7 @@ STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); STATIC const mp_stream_p_t stringio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, @@ -247,6 +248,7 @@ STATIC const mp_stream_p_t stringio_stream_p = { }; STATIC const mp_stream_p_t bytesio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, diff --git a/py/proto.c b/py/proto.c new file mode 100644 index 000000000..030b62674 --- /dev/null +++ b/py/proto.c @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/proto.h" +#include "py/runtime.h" + +#ifndef MICROPY_UNSAFE_PROTO +const void *mp_proto_get(uint16_t name, mp_const_obj_t obj) { + mp_obj_type_t *type = mp_obj_get_type(obj); + if (!type->protocol) return NULL; + uint16_t proto_name = *(const uint16_t*) type->protocol; + if (proto_name == name) { + return type->protocol; + } + return NULL; +} +#endif + +const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj) { + const void *proto = mp_proto_get(name, obj); + if (proto) { + return proto; + } + mp_raise_TypeError_varg(translate("'%s' object does not support '%s'"), + mp_obj_get_type_str(obj), qstr_str(name)); +} diff --git a/py/proto.h b/py/proto.h new file mode 100644 index 000000000..2d4f80565 --- /dev/null +++ b/py/proto.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_PY_PROTO_H +#define MICROPY_INCLUDED_PY_PROTO_H + +#ifdef MICROPY_UNSAFE_PROTO +#define MP_PROTOCOL_HEAD /* NOTHING */ +#define MP_PROTO_IMPLEMENT(name) /* NOTHING */ +static inline void *mp_proto_get(uint16_t name, mp_const_obj_type_t obj) { return mp_obj_get_type(obj)->protocol; } +#else +#define MP_PROTOCOL_HEAD \ + uint16_t name; // The name of this protocol, a qstr +#define MP_PROTO_IMPLEMENT(n) .name = n, +const void *mp_proto_get(uint16_t name, mp_const_obj_t obj); +const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj); +#endif + +#endif + @@ -214,6 +214,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objtype.o \ objzip.o \ opmethods.o \ + proto.o \ reload.o \ sequence.o \ stream.o \ diff --git a/py/stream.c b/py/stream.c index 1d25f6470..2ff2b76a6 100644 --- a/py/stream.c +++ b/py/stream.c @@ -86,8 +86,7 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { - mp_obj_type_t *type = mp_obj_get_type(self_in); - const mp_stream_p_t *stream_p = type->protocol; + const mp_stream_p_t *stream_p = mp_proto_get(MP_QSTR_protocol_stream, self_in); if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) @@ -522,7 +521,7 @@ int mp_stream_errno; ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); mp_uint_t out_sz = stream_p->write(stream, buf, len, &mp_stream_errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -533,7 +532,7 @@ ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); mp_uint_t out_sz = stream_p->read(stream, buf, len, &mp_stream_errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -544,7 +543,7 @@ ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { const mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; @@ -557,7 +556,7 @@ off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { int mp_stream_posix_fsync(mp_obj_t stream) { mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_FLUSH, 0, &mp_stream_errno); if (res == MP_STREAM_ERROR) { return -1; diff --git a/py/stream.h b/py/stream.h index 03e24c746..543fe8c82 100644 --- a/py/stream.h +++ b/py/stream.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_STREAM_H #include "py/obj.h" +#include "py/proto.h" #include "py/mperrno.h" #define MP_STREAM_ERROR ((mp_uint_t)-1) @@ -64,6 +65,7 @@ struct mp_stream_seek_t { // Stream protocol typedef struct _mp_stream_p_t { + MP_PROTOCOL_HEAD // 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); @@ -93,7 +95,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj); // Object is assumed to have a non-NULL stream protocol with valid r/w/ioctl methods static inline const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) { - return (const mp_stream_p_t*)((const mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type->protocol; + return mp_proto_get(MP_QSTR_protocol_stream, self); } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags); |
