py: Factor out persistent-code reader into separate files.

Implementations of persistent-code reader are provided for POSIX systems
and systems using FatFS.  Macros to use these are MICROPY_READER_POSIX and
MICROPY_READER_FATFS respectively.  If an alternative implementation is
needed then a port can define the function mp_reader_new_file.
This commit is contained in:
Damien George
2016-11-16 16:04:57 +11:00
parent 6810f2c134
commit 6b239c271c
14 changed files with 316 additions and 121 deletions

View File

@@ -29,6 +29,7 @@
#include <string.h>
#include <assert.h>
#include "py/reader.h"
#include "py/emitglue.h"
#include "py/persistentcode.h"
#include "py/bc.h"
@@ -98,19 +99,19 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_
#include "py/bc0.h"
STATIC int read_byte(mp_reader_t *reader) {
return reader->read_byte(reader->data);
return reader->readbyte(reader->data);
}
STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) {
while (len-- > 0) {
*buf++ = reader->read_byte(reader->data);
*buf++ = reader->readbyte(reader->data);
}
}
STATIC mp_uint_t read_uint(mp_reader_t *reader) {
mp_uint_t unum = 0;
for (;;) {
byte b = reader->read_byte(reader->data);
byte b = reader->readbyte(reader->data);
unum = (unum << 7) | (b & 0x7f);
if ((b & 0x80) == 0) {
break;
@@ -214,128 +215,28 @@ mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
if (header[2] != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits()) {
mp_raise_ValueError("incompatible .mpy file");
}
return load_raw_code(reader);
}
typedef struct _mp_mem_reader_t {
const byte *cur;
const byte *end;
} mp_mem_reader_t;
STATIC mp_uint_t mp_mem_reader_next_byte(void *br_in) {
mp_mem_reader_t *br = br_in;
if (br->cur < br->end) {
return *br->cur++;
} else {
return (mp_uint_t)-1;
}
mp_raw_code_t *rc = load_raw_code(reader);
reader->close(reader->data);
return rc;
}
mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
mp_mem_reader_t mr = {buf, buf + len};
mp_reader_t reader = {&mr, mp_mem_reader_next_byte};
mp_reader_t reader;
if (!mp_reader_new_mem(&reader, buf, len, 0)) {
m_malloc_fail(BYTES_PER_WORD); // we need to raise a MemoryError
}
return mp_raw_code_load(&reader);
}
// here we define mp_raw_code_load_file depending on the port
// TODO abstract this away properly
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(__unix__)
// unix file reader
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
typedef struct _mp_lexer_file_buf_t {
int fd;
byte buf[20];
mp_uint_t len;
mp_uint_t pos;
} mp_lexer_file_buf_t;
STATIC mp_uint_t file_buf_next_byte(void *fb_in) {
mp_lexer_file_buf_t *fb = fb_in;
if (fb->pos >= fb->len) {
if (fb->len == 0) {
return (mp_uint_t)-1;
} else {
int n = read(fb->fd, fb->buf, sizeof(fb->buf));
if (n <= 0) {
fb->len = 0;
return (mp_uint_t)-1;
}
fb->len = n;
fb->pos = 0;
}
}
return fb->buf[fb->pos++];
}
mp_raw_code_t *mp_raw_code_load_file(const char *filename) {
mp_lexer_file_buf_t fb;
fb.fd = open(filename, O_RDONLY, 0644);
int n = read(fb.fd, fb.buf, sizeof(fb.buf));
fb.len = n;
fb.pos = 0;
mp_reader_t reader;
reader.data = &fb;
reader.read_byte = file_buf_next_byte;
mp_raw_code_t *rc = mp_raw_code_load(&reader);
close(fb.fd);
return rc;
}
#elif defined(__thumb2__) || defined(__xtensa__)
// fatfs file reader (assume thumb2 arch uses fatfs...)
#include "lib/fatfs/ff.h"
typedef struct _mp_lexer_file_buf_t {
FIL fp;
byte buf[20];
uint16_t len;
uint16_t pos;
} mp_lexer_file_buf_t;
STATIC mp_uint_t file_buf_next_byte(void *fb_in) {
mp_lexer_file_buf_t *fb = fb_in;
if (fb->pos >= fb->len) {
if (fb->len < sizeof(fb->buf)) {
return (mp_uint_t)-1;
} else {
UINT n;
f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n);
if (n == 0) {
return (mp_uint_t)-1;
}
fb->len = n;
fb->pos = 0;
}
int ret = mp_reader_new_file(&reader, filename);
if (ret != 0) {
mp_raise_OSError(ret);
}
return fb->buf[fb->pos++];
return mp_raw_code_load(&reader);
}
mp_raw_code_t *mp_raw_code_load_file(const char *filename) {
mp_lexer_file_buf_t fb;
/*FRESULT res =*/ f_open(&fb.fp, filename, FA_READ);
UINT n;
f_read(&fb.fp, fb.buf, sizeof(fb.buf), &n);
fb.len = n;
fb.pos = 0;
mp_reader_t reader;
reader.data = &fb;
reader.read_byte = file_buf_next_byte;
mp_raw_code_t *rc = mp_raw_code_load(&reader);
f_close(&fb.fp);
return rc;
}
#endif
#endif // MICROPY_PERSISTENT_CODE_LOAD
#if MICROPY_PERSISTENT_CODE_SAVE