1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "stream.h"
typedef struct _mp_obj_fdfile_t {
mp_obj_base_t base;
int fd;
} mp_obj_fdfile_t;
STATIC const mp_obj_type_t rawfile_type;
STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_fdfile_t *self = self_in;
print(env, "<io.FileIO %d>", self->fd);
}
STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
mp_obj_fdfile_t *o = o_in;
machine_int_t r = read(o->fd, buf, size);
if (r == -1) {
*errcode = errno;
}
return r;
}
STATIC machine_int_t fdfile_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
mp_obj_fdfile_t *o = o_in;
machine_int_t r = write(o->fd, buf, size);
if (r == -1) {
*errcode = errno;
}
return r;
}
STATIC mp_obj_t fdfile_close(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
close(self->fd);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close);
mp_obj_t fdfile___exit__(uint n_args, const mp_obj_t *args) {
return fdfile_close(args[0]);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___exit__);
STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->fd);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
STATIC mp_obj_fdfile_t *fdfile_new(int fd) {
mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
o->base.type = &rawfile_type;
o->fd = fd;
return o;
}
STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
o->base.type = type_in;
if (MP_OBJ_IS_SMALL_INT(args[0])) {
o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]);
return o;
}
const char *fname = mp_obj_str_get_str(args[0]);
const char *mode_s;
if (n_args > 1) {
mode_s = mp_obj_str_get_str(args[1]);
} else {
mode_s = "r";
}
int mode = 0;
while (*mode_s) {
switch (*mode_s++) {
// Note: these assume O_RDWR = O_RDONLY | O_WRONLY
case 'r':
mode |= O_RDONLY;
break;
case 'w':
mode |= O_WRONLY | O_CREAT | O_TRUNC;
break;
case 'a':
mode |= O_APPEND;
break;
case '+':
mode |= O_RDWR;
break;
}
}
int fd = open(fname, mode, 0644);
if (fd == -1) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
}
return fdfile_new(fd);
}
STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_fileno), (mp_obj_t)&fdfile_fileno_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_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 },
{ MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&fdfile___exit___obj },
};
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
STATIC const mp_stream_p_t rawfile_stream_p = {
.read = fdfile_read,
.write = fdfile_write,
};
STATIC const mp_obj_type_t rawfile_type = {
{ &mp_type_type },
.name = MP_QSTR_FileIO,
.print = fdfile_print,
.make_new = fdfile_make_new,
.getiter = mp_identity,
.iternext = mp_stream_unbuffered_iter,
.stream_p = &rawfile_stream_p,
.locals_dict = (mp_obj_t)&rawfile_locals_dict,
};
// Factory function for I/O stream classes
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) {
// TODO: analyze mode and buffering args and instantiate appropriate type
return fdfile_make_new((mp_obj_t)&rawfile_type, n_args, 0, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);
void file_init() {
mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
mp_store_attr(m_sys, MP_QSTR_stdin, fdfile_new(STDIN_FILENO));
mp_store_attr(m_sys, MP_QSTR_stdout, fdfile_new(STDOUT_FILENO));
mp_store_attr(m_sys, MP_QSTR_stderr, fdfile_new(STDERR_FILENO));
}
|