Merge pull request #173 from pfalcon/file-readall

Generic implementation if stream readall() method, immediately reused in unix io.FileIO implementation
This commit is contained in:
Damien George 2014-01-14 15:35:50 -08:00
commit 11cc694aa0
7 changed files with 93 additions and 6 deletions

View File

@ -614,7 +614,7 @@ mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_strea
lex->num_indent_level = 1;
lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
lex->indent_level[0] = 0;
vstr_init(&lex->vstr);
vstr_init(&lex->vstr, 32);
// preload characters
lex->chr0 = stream_next_char(stream_data);

View File

@ -59,15 +59,19 @@ typedef struct _vstr_t {
bool had_error;
} vstr_t;
void vstr_init(vstr_t *vstr);
void vstr_init(vstr_t *vstr, int alloc);
void vstr_clear(vstr_t *vstr);
vstr_t *vstr_new(void);
vstr_t *vstr_new_size(int alloc);
void vstr_free(vstr_t *vstr);
void vstr_reset(vstr_t *vstr);
bool vstr_had_error(vstr_t *vstr);
char *vstr_str(vstr_t *vstr);
int vstr_len(vstr_t *vstr);
void vstr_hint_size(vstr_t *vstr, int size);
char *vstr_extend(vstr_t *vstr, int size);
bool vstr_set_size(vstr_t *vstr, int size);
bool vstr_shrink(vstr_t *vstr);
char *vstr_add_len(vstr_t *vstr, int len);
void vstr_add_byte(vstr_t *vstr, byte v);
void vstr_add_char(vstr_t *vstr, unichar chr);

View File

@ -51,5 +51,47 @@ static mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
}
}
// TODO: should be in mpconfig.h
#define READ_SIZE 256
static mp_obj_t stream_readall(mp_obj_t self_in) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
if (o->type->stream_p.read == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported"));
}
int total_size = 0;
vstr_t *vstr = vstr_new_size(READ_SIZE);
char *buf = vstr_str(vstr);
char *p = buf;
int error;
int current_read = READ_SIZE;
while (true) {
machine_int_t out_sz = o->type->stream_p.read(self_in, p, current_read, &error);
if (out_sz == -1) {
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error));
}
if (out_sz == 0) {
break;
}
total_size += out_sz;
if (out_sz < current_read) {
current_read -= out_sz;
p += out_sz;
} else {
current_read = READ_SIZE;
p = vstr_extend(vstr, current_read);
if (p == NULL) {
// TODO
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory"));
}
}
}
vstr_set_size(vstr, total_size + 1); // TODO: for \0
buf[total_size] = 0;
return mp_obj_new_str(qstr_from_str_take(buf, total_size + 1));
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_read_obj, stream_read);
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write);

View File

@ -1,2 +1,3 @@
extern const mp_obj_fun_native_t mp_stream_read_obj;
extern const mp_obj_fun_native_t mp_stream_readall_obj;
extern const mp_obj_fun_native_t mp_stream_write_obj;

View File

@ -6,8 +6,8 @@
// returned value is always at least 1 greater than argument
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
void vstr_init(vstr_t *vstr) {
vstr->alloc = 32;
void vstr_init(vstr_t *vstr, int alloc) {
vstr->alloc = alloc;
vstr->len = 0;
vstr->buf = m_new(char, vstr->alloc);
if (vstr->buf == NULL) {
@ -28,7 +28,16 @@ vstr_t *vstr_new(void) {
if (vstr == NULL) {
return NULL;
}
vstr_init(vstr);
vstr_init(vstr, 32);
return vstr;
}
vstr_t *vstr_new_size(int alloc) {
vstr_t *vstr = m_new(vstr_t, 1);
if (vstr == NULL) {
return NULL;
}
vstr_init(vstr, alloc);
return vstr;
}
@ -63,6 +72,36 @@ int vstr_len(vstr_t *vstr) {
return vstr->len;
}
// Extend vstr strictly to by requested size, return pointer to newly added chunk
char *vstr_extend(vstr_t *vstr, int size) {
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
if (new_buf == NULL) {
vstr->had_error = true;
return NULL;
}
char *p = new_buf + vstr->alloc;
vstr->alloc += size;
vstr->buf = new_buf;
return p;
}
// Shrink vstr to be given size
bool vstr_set_size(vstr_t *vstr, int size) {
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, size);
if (new_buf == NULL) {
vstr->had_error = true;
return false;
}
vstr->buf = new_buf;
vstr->alloc = vstr->len = size;
return true;
}
// Shrink vstr allocation to its actual length
bool vstr_shrink(vstr_t *vstr) {
return vstr_set_size(vstr, vstr->len);
}
bool vstr_ensure_extra(vstr_t *vstr, int size) {
if (vstr->len + size + 1 > vstr->alloc) {
int new_alloc = ROUND_ALLOC((vstr->len + size + 1) * 2);

View File

@ -390,7 +390,7 @@ void do_repl(void) {
stdout_tx_str("Type \"help()\" for more information.\r\n");
vstr_t line;
vstr_init(&line);
vstr_init(&line, 32);
for (;;) {
vstr_reset(&line);

View File

@ -90,6 +90,7 @@ static mp_obj_t fdfile_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *ar
static const mp_method_t rawfile_type_methods[] = {
{ "read", &mp_stream_read_obj },
{ "readall", &mp_stream_readall_obj },
{ "write", &mp_stream_write_obj },
{ "close", &fdfile_close_obj },
{ NULL, NULL },