Skip to content
Snippets Groups Projects
Commit 838eb1fa authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

stream: Implement seek operation support via ioctl, wrapped in generic method.

Also, implement for unix port.
parent f4a6a577
No related branches found
No related tags found
No related merge requests found
......@@ -231,8 +231,6 @@ void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flag
// Stream protocol
#define MP_STREAM_ERROR (-1)
#define MP_STREAM_FLUSH (1)
#define MP_STREAM_POLL (2)
typedef struct _mp_stream_p_t {
// 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).
......@@ -242,6 +240,17 @@ typedef struct _mp_stream_p_t {
mp_uint_t is_text : 1; // default is bytes, set this for text stream
} mp_stream_p_t;
// Stream ioctl request codes
#define MP_STREAM_FLUSH (1)
#define MP_STREAM_SEEK (2)
#define MP_STREAM_POLL (3)
// Argument structure for MP_STREAM_SEEK
struct mp_stream_seek_t {
mp_off_t offset;
int whence;
};
struct _mp_obj_type_t {
mp_obj_base_t base;
qstr name;
......
......@@ -455,6 +455,7 @@ Q(readall)
Q(readinto)
Q(readline)
Q(readlines)
Q(seek)
Q(FileIO)
Q(TextIOWrapper)
Q(StringIO)
......
......@@ -380,6 +380,32 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
return MP_OBJ_STOP_ITERATION;
}
STATIC mp_obj_t stream_seek(mp_uint_t n_args, const mp_obj_t *args) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
struct mp_stream_seek_t seek_s;
// TODO: Could be uint64
seek_s.offset = mp_obj_get_int(args[1]);
seek_s.whence = 0;
if (n_args == 3) {
seek_s.whence = mp_obj_get_int(args[2]);
}
int error;
mp_uint_t res = o->type->stream_p->ioctl(o, MP_STREAM_SEEK, (mp_uint_t)&seek_s, &error);
if (res == MP_STREAM_ERROR) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error)));
}
// TODO: Could be uint64
return mp_obj_new_int_from_uint(seek_s.offset);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj, 2, 3, stream_seek);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto);
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
......
......@@ -30,6 +30,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_stream_readall_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readline_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readlines_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_write_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_stream_seek_obj);
// Iterator which uses mp_stream_unbuffered_readline_obj
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);
......
......@@ -88,6 +88,23 @@ STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
return r;
}
STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
mp_obj_fdfile_t *o = o_in;
if (request == MP_STREAM_SEEK) {
struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;
off_t off = lseek(o->fd, s->offset, s->whence);
if (off == (off_t)-1) {
*errcode = errno;
return MP_STREAM_ERROR;
}
s->offset = off;
return 0;
} else {
*errcode = EINVAL;
return MP_STREAM_ERROR;
}
}
STATIC mp_obj_t fdfile_flush(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
check_fd_is_open(self);
......@@ -192,6 +209,7 @@ STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_readlines), (mp_obj_t)&mp_stream_unbuffered_readlines_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_seek), (mp_obj_t)&mp_stream_seek_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flush), (mp_obj_t)&fdfile_flush_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&fdfile_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
......@@ -204,6 +222,7 @@ 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,
.ioctl = fdfile_ioctl,
};
const mp_obj_type_t mp_type_fileio = {
......
......@@ -122,6 +122,13 @@ typedef unsigned int mp_uint_t; // must be pointer size
#define BYTES_PER_WORD sizeof(mp_int_t)
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
typedef long long mp_off_t;
#else
typedef long mp_off_t;
#endif
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment