file.c 2.82 KB
Newer Older
mux's avatar
mux committed
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
#include <stdio.h>
#include <stm32f4xx.h>

#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "file.h"
#include "ff.h"

typedef struct _pyb_file_obj_t {
    mp_obj_base_t base;
    FIL fp;
} pyb_file_obj_t;

void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
    printf("<file %p>", self_in);
}

mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) {
    pyb_file_obj_t *self = self_in;
    int n = mp_obj_get_int(arg);
    byte *buf = m_new(byte, n);
    UINT n_out;
    f_read(&self->fp, buf, n, &n_out);
    return mp_obj_new_str(buf, n_out, false);
}

mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) {
    pyb_file_obj_t *self = self_in;
    uint l;
32
    const char *s = mp_obj_str_get_data(arg, &l);
mux's avatar
mux committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    UINT n_out;
    FRESULT res = f_write(&self->fp, s, l, &n_out);
    if (res != FR_OK) {
        printf("File error: could not write to file; error code %d\n", res);
    } else if (n_out != l) {
        printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, l);
    }
    return mp_const_none;
}

mp_obj_t file_obj_close(mp_obj_t self_in) {
    pyb_file_obj_t *self = self_in;
    f_close(&self->fp);
    return mp_const_none;
}

static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read);
static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write);
static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close);

// TODO gc hook to close the file if not already closed

static const mp_method_t file_methods[] = {
56
57
58
59
    { MP_QSTR_read, &file_obj_read_obj },
    { MP_QSTR_write, &file_obj_write_obj },
    { MP_QSTR_close, &file_obj_close_obj },
    { MP_QSTR_NULL, NULL },
mux's avatar
mux committed
60
61
62
};

static const mp_obj_type_t file_obj_type = {
63
    { &mp_type_type },
64
    .name = MP_QSTR_File,
mux's avatar
mux committed
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
    .print = file_obj_print,
    .methods = file_methods,
};

mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
    const char *filename = mp_obj_str_get_str(o_filename);
    const char *mode = mp_obj_str_get_str(o_mode);
    pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
    self->base.type = &file_obj_type;
    if (mode[0] == 'r') {
        // open for reading
        FRESULT res = f_open(&self->fp, filename, FA_READ);
        if (res != FR_OK) {
            printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename);
            return mp_const_none;
        }
    } else if (mode[0] == 'w') {
        // open for writing, truncate the file first
        FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS);
        if (res != FR_OK) {
            printf("?FileError: could not create file: '%s'\n", filename);
            return mp_const_none;
        }
    } else {
        printf("ValueError: invalid mode: '%s'\n", mode);
        return mp_const_none;
    }
    return self;
}