Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013-2017 Damien P. George
7 : : *
8 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : * of this software and associated documentation files (the "Software"), to deal
10 : : * in the Software without restriction, including without limitation the rights
11 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : * copies of the Software, and to permit persons to whom the Software is
13 : : * furnished to do so, subject to the following conditions:
14 : : *
15 : : * The above copyright notice and this permission notice shall be included in
16 : : * all copies or substantial portions of the Software.
17 : : *
18 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 : : * THE SOFTWARE.
25 : : */
26 : :
27 : : #include <stdio.h>
28 : : #include <string.h>
29 : : #include <stdlib.h>
30 : :
31 : : #include "py/runtime.h"
32 : : #include "py/stream.h"
33 : : #include "py/reader.h"
34 : : #include "extmod/vfs.h"
35 : :
36 : : #if MICROPY_READER_VFS
37 : :
38 : : #ifndef MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE
39 : : #define MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE (2 * MICROPY_BYTES_PER_GC_BLOCK - offsetof(mp_reader_vfs_t, buf))
40 : : #endif
41 : : #define MICROPY_READER_VFS_MIN_BUFFER_SIZE (MICROPY_BYTES_PER_GC_BLOCK - offsetof(mp_reader_vfs_t, buf))
42 : : #define MICROPY_READER_VFS_MAX_BUFFER_SIZE (255)
43 : :
44 : : typedef struct _mp_reader_vfs_t {
45 : : mp_obj_t file;
46 : : uint8_t bufpos;
47 : : uint8_t buflen;
48 : : uint8_t bufsize;
49 : : byte buf[];
50 : : } mp_reader_vfs_t;
51 : :
52 : 4452554 : static mp_uint_t mp_reader_vfs_readbyte(void *data) {
53 : 4452554 : mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data;
54 [ + + ]: 4452554 : if (reader->bufpos >= reader->buflen) {
55 [ + + ]: 89082 : if (reader->buflen < reader->bufsize) {
56 : : return MP_READER_EOF;
57 : : } else {
58 : 82062 : int errcode;
59 : 82062 : reader->buflen = mp_stream_rw(reader->file, reader->buf, reader->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
60 [ + - ]: 82062 : if (errcode != 0) {
61 : : // TODO handle errors properly
62 : 52 : return MP_READER_EOF;
63 : : }
64 [ + + ]: 82062 : if (reader->buflen == 0) {
65 : : return MP_READER_EOF;
66 : : }
67 : 82010 : reader->bufpos = 0;
68 : : }
69 : : }
70 : 4445482 : return reader->buf[reader->bufpos++];
71 : : }
72 : :
73 : 3729 : static void mp_reader_vfs_close(void *data) {
74 : 3729 : mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data;
75 : 3729 : mp_stream_close(reader->file);
76 : 3729 : m_del_obj(mp_reader_vfs_t, reader);
77 : 3729 : }
78 : :
79 : 3741 : void mp_reader_new_file(mp_reader_t *reader, qstr filename) {
80 : 3741 : mp_obj_t args[2] = {
81 : 3741 : MP_OBJ_NEW_QSTR(filename),
82 : : MP_OBJ_NEW_QSTR(MP_QSTR_rb),
83 : : };
84 : 3741 : mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map);
85 : :
86 : 3737 : const mp_stream_p_t *stream_p = mp_get_stream(file);
87 : 3737 : int errcode = 0;
88 : :
89 : : #if MICROPY_VFS_ROM
90 : : // Check if the stream can be memory mapped.
91 : 3737 : mp_buffer_info_t bufinfo;
92 [ + + ]: 3737 : if (mp_get_buffer(file, &bufinfo, MP_BUFFER_READ)) {
93 : 8 : mp_reader_new_mem(reader, bufinfo.buf, bufinfo.len, MP_READER_IS_ROM);
94 : 8 : return;
95 : : }
96 : : #endif
97 : :
98 : : // Determine how big the input buffer should be, if the stream requests a certain size or not.
99 : 3729 : mp_uint_t bufsize = stream_p->ioctl(file, MP_STREAM_GET_BUFFER_SIZE, 0, &errcode);
100 [ + + ]: 3729 : if (bufsize == MP_STREAM_ERROR || bufsize == 0) {
101 : : // bufsize == 0 is included here to support mpremote v1.21 and older where mount file ioctl
102 : : // returned 0 by default.
103 : : bufsize = MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE;
104 : : } else {
105 [ + + ]: 12 : bufsize = MIN(MICROPY_READER_VFS_MAX_BUFFER_SIZE, MAX(MICROPY_READER_VFS_MIN_BUFFER_SIZE, bufsize));
106 : : }
107 : :
108 : : // Create the reader.
109 : 3729 : mp_reader_vfs_t *rf = m_new_obj_var(mp_reader_vfs_t, buf, byte, bufsize);
110 : 3729 : rf->file = file;
111 : 3729 : rf->bufsize = bufsize;
112 : 3729 : rf->buflen = mp_stream_rw(rf->file, rf->buf, rf->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
113 [ - + ]: 3729 : if (errcode != 0) {
114 : 0 : mp_raise_OSError(errcode);
115 : : }
116 : 3729 : rf->bufpos = 0;
117 : 3729 : reader->data = rf;
118 : 3729 : reader->readbyte = mp_reader_vfs_readbyte;
119 : 3729 : reader->close = mp_reader_vfs_close;
120 : : }
121 : :
122 : : #endif // MICROPY_READER_VFS
|