extmod/os_dupterm: Let mp_os_dupterm_tx_strn() return num bytes written.

In case of multiple outputs, the minimum successful write length is
returned.  In line with this, in case any output has a write error, zero is
returned.

In case of no outputs, -1 is returned.

The return value can be used to assess whether writes were attempted, and
if so, whether they succeeded.

Signed-off-by: Maarten van der Schrieck <maarten@thingsconnected.nl>
This commit is contained in:
Maarten van der Schrieck 2023-10-24 23:10:45 +02:00 committed by Damien George
parent 5d28bb4adb
commit 91ee8ac894
2 changed files with 21 additions and 5 deletions

View File

@ -39,10 +39,12 @@ bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream);
void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached); void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags); uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags);
int mp_os_dupterm_rx_chr(void); int mp_os_dupterm_rx_chr(void);
void mp_os_dupterm_tx_strn(const char *str, size_t len); int mp_os_dupterm_tx_strn(const char *str, size_t len);
void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc); void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
#else #else
#define mp_os_dupterm_tx_strn(s, l) static inline int mp_os_dupterm_tx_strn(const char *s, size_t l) {
return -1;
}
#endif #endif
#endif // MICROPY_INCLUDED_EXTMOD_MISC_H #endif // MICROPY_INCLUDED_EXTMOD_MISC_H

View File

@ -169,29 +169,43 @@ int mp_os_dupterm_rx_chr(void) {
return ret; return ret;
} }
void mp_os_dupterm_tx_strn(const char *str, size_t len) { int mp_os_dupterm_tx_strn(const char *str, size_t len) {
// Returns the minimum successful write length, or -1 if no write is attempted.
int ret = len;
bool did_write = false;
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
continue; continue;
} }
did_write = true;
#if MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM #if MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM
if (mp_os_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) { if (mp_os_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
int errcode = 0; int errcode = 0;
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx])); const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode); mp_uint_t written = stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode);
int write_res = MAX(0, written);
ret = MIN(write_res, ret);
continue; continue;
} }
#endif #endif
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE); mp_obj_t written = mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
if (written == mp_const_none) {
ret = 0;
} else if (mp_obj_is_small_int(written)) {
int written_int = MAX(0, MP_OBJ_SMALL_INT_VALUE(written));
ret = MIN(written_int, ret);
}
nlr_pop(); nlr_pop();
} else { } else {
mp_os_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val)); mp_os_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
ret = 0;
} }
} }
return did_write ? ret : -1;
} }
STATIC mp_obj_t mp_os_dupterm(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t mp_os_dupterm(size_t n_args, const mp_obj_t *args) {