blob: d3673d1f96398c83cd4a83015ea7cdb7bd03d28a [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
Paul Sokolovskya47b64a2014-05-15 07:28:19 +03007 * Copyright (c) 2014 Paul Sokolovsky
Damien George04b91472014-05-03 23:27:38 +01008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030028#include <stdio.h>
29#include <string.h>
30
Paul Sokolovskyf54bcbf2014-05-02 17:47:01 +030031#include "mpconfig.h"
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030032#include "nlr.h"
33#include "misc.h"
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030034#include "qstr.h"
35#include "obj.h"
36#include "runtime.h"
37#include "stream.h"
Paul Sokolovskya47b64a2014-05-15 07:28:19 +030038#include "objstr.h"
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030039
Damien Georgeee3fd462014-05-24 23:03:12 +010040#if MICROPY_PY_IO
Paul Sokolovsky100cd362014-04-26 20:59:39 +030041
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030042typedef struct _mp_obj_stringio_t {
43 mp_obj_base_t base;
44 vstr_t *vstr;
45 // StringIO has single pointer used for both reading and writing
Damien George40f3c022014-07-03 13:25:24 +010046 mp_uint_t pos;
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030047} mp_obj_stringio_t;
48
49STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
50 mp_obj_stringio_t *self = self_in;
Paul Sokolovskya47b64a2014-05-15 07:28:19 +030051 print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self->vstr);
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030052}
53
Damien Georgeadf0f2a2014-07-27 22:38:58 +010054STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030055 mp_obj_stringio_t *o = o_in;
Damien George40f3c022014-07-03 13:25:24 +010056 mp_uint_t remaining = o->vstr->len - o->pos;
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030057 if (size > remaining) {
58 size = remaining;
59 }
60 memcpy(buf, o->vstr->buf + o->pos, size);
61 o->pos += size;
62 return size;
63}
64
Damien Georgeadf0f2a2014-07-27 22:38:58 +010065STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030066 mp_obj_stringio_t *o = o_in;
Damien George40f3c022014-07-03 13:25:24 +010067 mp_uint_t remaining = o->vstr->alloc - o->pos;
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030068 if (size > remaining) {
69 // Take all what's already allocated...
70 o->vstr->len = o->vstr->alloc;
71 // ... and add more
72 vstr_add_len(o->vstr, size - remaining);
73 }
74 memcpy(o->vstr->buf + o->pos, buf, size);
75 o->pos += size;
76 if (o->pos > o->vstr->len) {
77 o->vstr->len = o->pos;
78 }
79 return size;
80}
81
Paul Sokolovskya47b64a2014-05-15 07:28:19 +030082#define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes)
83
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030084STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) {
85 mp_obj_stringio_t *self = self_in;
Damien Georgef600a6a2014-05-25 22:34:34 +010086 return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte*)self->vstr->buf, self->vstr->len);
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030087}
88STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue);
89
90STATIC mp_obj_t stringio_close(mp_obj_t self_in) {
91 mp_obj_stringio_t *self = self_in;
92 vstr_free(self->vstr);
93 self->vstr = NULL;
94 return mp_const_none;
95}
96STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_close_obj, stringio_close);
97
Damien Georgeecc88e92014-08-30 00:35:11 +010098mp_obj_t stringio___exit__(mp_uint_t n_args, const mp_obj_t *args) {
Paul Sokolovskycb9dc082014-04-26 20:26:14 +030099 return stringio_close(args[0]);
100}
101STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio___exit__);
102
Paul Sokolovskya47b64a2014-05-15 07:28:19 +0300103STATIC mp_obj_stringio_t *stringio_new(mp_obj_t type_in) {
Paul Sokolovskycb9dc082014-04-26 20:26:14 +0300104 mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t);
Paul Sokolovskya47b64a2014-05-15 07:28:19 +0300105 o->base.type = type_in;
Paul Sokolovskycb9dc082014-04-26 20:26:14 +0300106 o->vstr = vstr_new();
107 o->pos = 0;
108 return o;
109}
110
Damien Georgeecc88e92014-08-30 00:35:11 +0100111STATIC mp_obj_t stringio_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
Paul Sokolovskya47b64a2014-05-15 07:28:19 +0300112 mp_obj_stringio_t *o = stringio_new(type_in);
Paul Sokolovskycb9dc082014-04-26 20:26:14 +0300113
114 if (n_args > 0) {
115 mp_buffer_info_t bufinfo;
116 mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
117 stringio_write(o, bufinfo.buf, bufinfo.len, NULL);
118 // Cur ptr is always at the beginning of buffer at the construction
119 o->pos = 0;
120 }
121 return o;
122}
123
124STATIC const mp_map_elem_t stringio_locals_dict_table[] = {
125 { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
126 { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
127 { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
128 { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
129 { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&stringio_close_obj },
130 { MP_OBJ_NEW_QSTR(MP_QSTR_getvalue), (mp_obj_t)&stringio_getvalue_obj },
131 { MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
132 { MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&stringio___exit___obj },
133};
134
135STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table);
136
137STATIC const mp_stream_p_t stringio_stream_p = {
138 .read = stringio_read,
139 .write = stringio_write,
Damien Georgeadf0f2a2014-07-27 22:38:58 +0100140 .is_text = true,
Paul Sokolovskycb9dc082014-04-26 20:26:14 +0300141};
142
Paul Sokolovskya47b64a2014-05-15 07:28:19 +0300143STATIC const mp_stream_p_t bytesio_stream_p = {
144 .read = stringio_read,
145 .write = stringio_write,
Paul Sokolovskya47b64a2014-05-15 07:28:19 +0300146};
147
Paul Sokolovskycb9dc082014-04-26 20:26:14 +0300148const mp_obj_type_t mp_type_stringio = {
149 { &mp_type_type },
150 .name = MP_QSTR_StringIO,
151 .print = stringio_print,
152 .make_new = stringio_make_new,
153 .getiter = mp_identity,
154 .iternext = mp_stream_unbuffered_iter,
155 .stream_p = &stringio_stream_p,
156 .locals_dict = (mp_obj_t)&stringio_locals_dict,
157};
Paul Sokolovsky100cd362014-04-26 20:59:39 +0300158
Damien Georgeee3fd462014-05-24 23:03:12 +0100159#if MICROPY_PY_IO_BYTESIO
Paul Sokolovskya47b64a2014-05-15 07:28:19 +0300160const mp_obj_type_t mp_type_bytesio = {
161 { &mp_type_type },
162 .name = MP_QSTR_BytesIO,
163 .print = stringio_print,
164 .make_new = stringio_make_new,
165 .getiter = mp_identity,
166 .iternext = mp_stream_unbuffered_iter,
167 .stream_p = &bytesio_stream_p,
168 .locals_dict = (mp_obj_t)&stringio_locals_dict,
169};
170#endif
171
Paul Sokolovsky100cd362014-04-26 20:59:39 +0300172#endif