diff --git a/examples/unix/sock-client.py b/examples/unix/sock-client.py index d5d5021475..08a39b196a 100644 --- a/examples/unix/sock-client.py +++ b/examples/unix/sock-client.py @@ -1,22 +1,32 @@ -mod = rawsocket -s = mod.socket() +try: + import rawsocket as _socket +except: + import _socket + + +s = _socket.socket() if 1: - ai = mod.getaddrinfo("google.com", 80) + ai = _socket.getaddrinfo("google.com", 80) print("Address infos:", ai) addr = ai[0][4] else: - # Deprecated way to construct connection address - addr = mod.sockaddr_in() + # Deprecated ways to construct connection address + addr = _socket.sockaddr_in() addr.sin_family = 2 #addr.sin_addr = (0x0100 << 16) + 0x007f #addr.sin_addr = (0x7f00 << 16) + 0x0001 - #addr.sin_addr = mod.inet_aton("127.0.0.1") - addr.sin_addr = mod.gethostbyname("google.com") - addr.sin_port = mod.htons(80) + #addr.sin_addr = _socket.inet_aton("127.0.0.1") + addr.sin_addr = _socket.gethostbyname("google.com") + addr.sin_port = _socket.htons(80) print("Connect address:", addr) s.connect(addr) -s.write("GET / HTTP/1.0\n\n") -print(s.readall()) +if 0: + # MicroPython rawsocket module supports file interface directly + s.write("GET / HTTP/1.0\n\n") + print(s.readall()) +else: + s.send(b"GET / HTTP/1.0\n\n") + print(s.recv(4096)) diff --git a/examples/unix/sock-server.py b/examples/unix/sock-server.py index c39a0af21c..ed14b7f31e 100644 --- a/examples/unix/sock-server.py +++ b/examples/unix/sock-server.py @@ -1,7 +1,18 @@ -mod = rawsocket -s = mod.socket() +try: + import rawsocket as socket +except: + import socket -ai = mod.getaddrinfo("127.0.0.1", 8080) + +CONTENT = """\ +HTTP/1.0 200 OK + +Hello #{} from MicroPython! +""" + +s = socket.socket() + +ai = socket.getaddrinfo("127.0.0.1", 8080) print("Bind address info:", ai) addr = ai[0][4] @@ -17,12 +28,13 @@ while True: print("Client address:", client_addr) print("Client socket:", client_s) print("Request:") - print(client_s.read(4096)) - #print(client_s.readall()) - client_s.write("""\ -HTTP/1.0 200 OK - -Hello #{} from MicroPython! -""".format(counter)) + if 0: + # MicroPython rawsocket module supports file interface directly + print(client_s.read(4096)) + #print(client_s.readall()) + client_s.write(CONTENT.format(counter)) + else: + print(client_s.recv(4096)) + client_s.send(bytes(CONTENT.format(counter), "ascii")) client_s.close() counter += 1 diff --git a/py/builtin.c b/py/builtin.c index 8340ad3045..9cbc037677 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -350,3 +350,15 @@ static mp_obj_t mp_builtin_str(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_str_obj, mp_builtin_str); + +// TODO: This should be type, this is just quick CPython compat hack +static mp_obj_t mp_builtin_bytes(uint n_args, const mp_obj_t *args) { + if (!MP_OBJ_IS_QSTR(args[0]) && !MP_OBJ_IS_TYPE(args[0], &str_type)) { + assert(0); + } + // Currently, MicroPython strings are mix between CPython byte and unicode + // strings. So, conversion is null so far. + return args[0]; +} + +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_bytes_obj, 1, 3, mp_builtin_bytes); diff --git a/py/builtin.h b/py/builtin.h index 050a2161c1..4257de5bdb 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -5,6 +5,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bytes_obj); // Temporary hack MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj); diff --git a/py/obj.c b/py/obj.c index 5a6c08332a..8a073f4710 100644 --- a/py/obj.c +++ b/py/obj.c @@ -28,6 +28,8 @@ mp_obj_t mp_obj_get_type(mp_obj_t o_in) { const char *mp_obj_get_type_str(mp_obj_t o_in) { if (MP_OBJ_IS_SMALL_INT(o_in)) { return "int"; + } else if (MP_OBJ_IS_QSTR(o_in)) { + return "str"; } else { mp_obj_base_t *o = o_in; return o->type->name; @@ -222,7 +224,9 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { #endif qstr mp_obj_get_qstr(mp_obj_t arg) { - if (MP_OBJ_IS_TYPE(arg, &str_type)) { + if (MP_OBJ_IS_QSTR(arg)) { + return MP_OBJ_QSTR_VALUE(arg); + } else if (MP_OBJ_IS_TYPE(arg, &str_type)) { return mp_obj_str_get(arg); } else { assert(0); @@ -286,3 +290,9 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { } return MP_OBJ_NEW_SMALL_INT(len); } + +// Return input argument. Useful as .getiter for objects which are +// their own iterators, etc. +mp_obj_t mp_identity(mp_obj_t self) { + return self; +} diff --git a/py/obj.h b/py/obj.h index faf0231474..c2ce32588a 100644 --- a/py/obj.h +++ b/py/obj.h @@ -351,6 +351,8 @@ extern const mp_obj_type_t fun_native_type; extern const mp_obj_type_t fun_bc_type; void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code); +mp_obj_t mp_identity(mp_obj_t self); + // generator extern const mp_obj_type_t gen_instance_type; @@ -374,3 +376,6 @@ typedef struct _mp_obj_classmethod_t { mp_obj_base_t base; mp_obj_t fun; } mp_obj_classmethod_t; + +// sequence helpers +void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest); diff --git a/py/objlist.c b/py/objlist.c index bc363d38fd..2e9a8705ff 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -153,13 +153,8 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { return NULL; } int n = MP_OBJ_SMALL_INT_VALUE(rhs); - int len = o->len; - mp_obj_list_t *s = list_new(len * n); - mp_obj_t *dest = s->items; - for (int i = 0; i < n; i++) { - memcpy(dest, o->items, sizeof(mp_obj_t) * len); - dest += len; - } + mp_obj_list_t *s = list_new(o->len * n); + mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return s; } case RT_COMPARE_OP_EQUAL: diff --git a/py/objstr.c b/py/objstr.c index 3552058430..f4dc857398 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -65,9 +65,8 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // TODO: need predicate to check for int-like type (bools are such for example) // ["no", "yes"][1 == 2] is common idiom if (MP_OBJ_IS_SMALL_INT(rhs_in)) { - // TODO: This implements byte string access for single index so far - // TODO: Handle negative indexes. - return mp_obj_new_int(lhs_data[mp_obj_get_int(rhs_in)]); + uint index = mp_get_index(lhs->base.type, lhs_len, rhs_in); + return mp_obj_new_str(qstr_from_strn((const char*)lhs_data + index, 1)); #if MICROPY_ENABLE_SLICE } else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) { machine_int_t start, stop, step; @@ -122,6 +121,16 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return mp_const_false; } break; + case RT_BINARY_OP_MULTIPLY: + { + if (!MP_OBJ_IS_SMALL_INT(rhs_in)) { + return NULL; + } + int n = MP_OBJ_SMALL_INT_VALUE(rhs_in); + char *s = m_new(char, lhs_len * n); + mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, s); + return MP_OBJ_NEW_QSTR(qstr_from_strn_take(s, lhs_len * n, lhs_len * n)); + } } return MP_OBJ_NULL; // op not supported @@ -184,6 +193,45 @@ bad_arg: nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's")); } +#define is_ws(c) ((c) == ' ' || (c) == '\t') + +static mp_obj_t str_split(uint n_args, const mp_obj_t *args) { + int splits = -1; + mp_obj_t sep = mp_const_none; + if (n_args > 1) { + sep = args[1]; + if (n_args > 2) { + splits = MP_OBJ_SMALL_INT_VALUE(args[2]); + } + } + assert(sep == mp_const_none); + (void)sep; // unused; to hush compiler warning + mp_obj_t res = mp_obj_new_list(0, NULL); + const char *s = qstr_str(mp_obj_str_get(args[0])); + const char *start; + + // Initial whitespace is not counted as split, so we pre-do it + while (is_ws(*s)) s++; + while (*s && splits != 0) { + start = s; + while (*s != 0 && !is_ws(*s)) s++; + rt_list_append(res, MP_OBJ_NEW_QSTR(qstr_from_strn(start, s - start))); + if (*s == 0) { + break; + } + while (is_ws(*s)) s++; + if (splits > 0) { + splits--; + } + } + + if (*s != 0) { + rt_list_append(res, MP_OBJ_NEW_QSTR(qstr_from_str(s))); + } + + return res; +} + static bool chr_in_str(const char* const str, const size_t str_len, const char c) { for (size_t i = 0; i < str_len; i++) { if (str[i] == c) { @@ -195,16 +243,8 @@ static bool chr_in_str(const char* const str, const size_t str_len, const char c static mp_obj_t str_find(uint n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 4); - assert(MP_OBJ_IS_TYPE(args[0], &str_type)); - if (!MP_OBJ_IS_TYPE(args[1], &str_type)) { - nlr_jump(mp_obj_new_exception_msg_1_arg( - MP_QSTR_TypeError, - "Can't convert '%s' object to str implicitly", - mp_obj_get_type_str(args[1]))); - } - - const char* haystack = qstr_str(((mp_obj_str_t*)args[0])->qstr); - const char* needle = qstr_str(((mp_obj_str_t*)args[1])->qstr); + const char* haystack = qstr_str(mp_obj_str_get(args[0])); + const char* needle = qstr_str(mp_obj_str_get(args[1])); size_t haystack_len = strlen(haystack); size_t needle_len = strlen(needle); @@ -242,14 +282,11 @@ mp_obj_t str_strip(uint n_args, const mp_obj_t *args) { if (n_args == 1) { chars_to_del = whitespace; } else { - assert(MP_OBJ_IS_TYPE(args[1], &str_type)); - mp_obj_str_t *chars_to_del_obj = args[1]; - chars_to_del = qstr_str(chars_to_del_obj->qstr); + chars_to_del = qstr_str(mp_obj_str_get(args[1])); } const size_t chars_to_del_len = strlen(chars_to_del); - mp_obj_str_t *self = args[0]; - const char *orig_str = qstr_str(self->qstr); + const char *orig_str = qstr_str(mp_obj_str_get(args[0])); const size_t orig_str_len = strlen(orig_str); size_t first_good_char_pos = 0; @@ -307,12 +344,14 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) { static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format); static const mp_method_t str_type_methods[] = { { "find", &str_find_obj }, { "join", &str_join_obj }, + { "split", &str_split_obj }, { "strip", &str_strip_obj }, { "format", &str_format_obj }, { NULL, NULL }, // end-of-list sentinel @@ -335,9 +374,15 @@ mp_obj_t mp_obj_new_str(qstr qstr) { } qstr mp_obj_str_get(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &str_type)); - mp_obj_str_t *self = self_in; - return self->qstr; + if (MP_OBJ_IS_QSTR(self_in)) { + return MP_OBJ_QSTR_VALUE(self_in); + } + if (MP_OBJ_IS_TYPE(self_in, &str_type)) { + mp_obj_str_t *self = self_in; + return self->qstr; + } + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly", + mp_obj_get_type_str(self_in))); } /******************************************************************************/ diff --git a/py/py.mk b/py/py.mk index 72013ef999..75394b3615 100644 --- a/py/py.mk +++ b/py/py.mk @@ -97,6 +97,7 @@ PY_O_BASENAME = \ objtuple.o \ objtype.o \ objzip.o \ + sequence.o \ stream.o \ builtin.o \ builtinimport.o \ diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 10b1fc0d39..9bc01c5851 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -40,6 +40,7 @@ Q(any) Q(array) Q(bool) Q(bytearray) +Q(bytes) Q(callable) Q(chr) Q(complex) diff --git a/py/runtime.c b/py/runtime.c index 210047ac0a..ccd3d7d0af 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -130,6 +130,7 @@ void rt_init(void) { mp_map_add_qstr(&map_builtins, MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_bytes, (mp_obj_t)&mp_builtin_bytes_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj); diff --git a/py/sequence.c b/py/sequence.c new file mode 100644 index 0000000000..56718c6f85 --- /dev/null +++ b/py/sequence.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "map.h" +#include "runtime0.h" +#include "runtime.h" + +// Helpers for sequence types + +// Implements backend of sequence * integer operation. Assumes elements are +// memory-adjacent in sequence. +void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest) { + for (int i = 0; i < times; i++) { + uint copy_sz = item_sz * len; + memcpy(dest, items, copy_sz); + dest = (char*)dest + copy_sz; + } +} diff --git a/py/stream.c b/py/stream.c index 88ddc5e6c9..be560d3c22 100644 --- a/py/stream.c +++ b/py/stream.c @@ -30,7 +30,8 @@ static mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); } else { // TODO don't intern this string - return mp_obj_new_str(qstr_from_strn_take(buf, sz, out_sz)); + buf = m_realloc(buf, sz, out_sz); + return mp_obj_new_str(qstr_from_strn_take(buf, out_sz, out_sz)); } } @@ -134,9 +135,18 @@ static mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { } // TODO don't intern this string vstr_shrink(vstr); - return mp_obj_new_str(qstr_from_strn_take(vstr_str(vstr), vstr->alloc, vstr_len(vstr))); + return MP_OBJ_NEW_QSTR(qstr_from_strn_take(vstr_str(vstr), vstr->alloc, vstr_len(vstr))); } +mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) { + mp_obj_t l_in = stream_unbuffered_readline(1, &self); + const char *l = qstr_str(MP_OBJ_QSTR_VALUE(l_in)); + // TODO: \0 + if (*l != 0) { + return l_in; + } + return mp_const_stop_iteration; +} MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read); MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall); diff --git a/py/stream.h b/py/stream.h index 58e8072549..a0cc34797b 100644 --- a/py/stream.h +++ b/py/stream.h @@ -2,3 +2,6 @@ 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_unbuffered_readline_obj; extern const mp_obj_fun_native_t mp_stream_write_obj; + +// Iterator which uses mp_stream_unbuffered_readline_obj +mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self); diff --git a/tests/basics/string1.py b/tests/basics/string1.py index 3fecf799be..074b04ef8f 100644 --- a/tests/basics/string1.py +++ b/tests/basics/string1.py @@ -8,6 +8,19 @@ print(x) print('123' + "456") +print('123' * 5) + +print('abc'[1]) +print('abc'[-1]) +try: + 'abc'[100] +except IndexError: + print('caught') +try: + 'abc'[-4] +except IndexError: + print('caught2') + # iter print(list('str')) diff --git a/tests/basics/string_split.py b/tests/basics/string_split.py new file mode 100644 index 0000000000..f73cb4291e --- /dev/null +++ b/tests/basics/string_split.py @@ -0,0 +1,7 @@ +print("a b".split()) +print(" a b ".split(None)) +print(" a b ".split(None, 1)) +print(" a b ".split(None, 2)) +print(" a b c ".split(None, 1)) +print(" a b c ".split(None, 0)) +print(" a b c ".split(None, -1)) diff --git a/tests/io/file-iter.py b/tests/io/file-iter.py new file mode 100644 index 0000000000..48e8739966 --- /dev/null +++ b/tests/io/file-iter.py @@ -0,0 +1,3 @@ +f = open("io/data/file1") +for l in f: + print(l) diff --git a/tests/run-tests b/tests/run-tests index ef1368725f..752138ccc6 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -10,7 +10,14 @@ numpassed=0 numfailed=0 namefailed= -for infile in basics/*.py io/*.py +if [ $# -eq 0 ] +then + tests="basics/*.py io/*.py" +else + tests="$@" +fi + +for infile in $tests do basename=`basename $infile .py` outfile=${basename}.out diff --git a/unix/file.c b/unix/file.c index 72c56ca100..3181c08b69 100644 --- a/unix/file.c +++ b/unix/file.c @@ -8,6 +8,7 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "runtime.h" #include "stream.h" typedef struct _mp_obj_fdfile_t { @@ -15,6 +16,8 @@ typedef struct _mp_obj_fdfile_t { int fd; } mp_obj_fdfile_t; +static const mp_obj_type_t rawfile_type; + static void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_fdfile_t *self = self_in; print(env, "", self->fd); @@ -45,6 +48,13 @@ static mp_obj_t fdfile_close(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close); +static mp_obj_fdfile_t *fdfile_new(int fd) { + mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t); + o->base.type = &rawfile_type; + o->fd = fd; + return o; +} + static mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t); o->base.type = type_in; @@ -81,11 +91,11 @@ static mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const } } - o->fd = open(fname, mode, 0644); - if (o->fd == -1) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_OSError, "[Errno %d]", (const char *)(machine_int_t)errno)); + int fd = open(fname, mode, 0644); + if (fd == -1) { + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno)); } - return o; + return fdfile_new(fd); } static const mp_method_t rawfile_type_methods[] = { @@ -102,8 +112,8 @@ static const mp_obj_type_t rawfile_type = { "io.FileIO", .print = fdfile_print, .make_new = fdfile_make_new, - .getiter = NULL, - .iternext = NULL, + .getiter = mp_identity, + .iternext = mp_stream_unbuffered_iter, .stream_p = { .read = fdfile_read, .write = fdfile_write, @@ -117,3 +127,12 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) { return fdfile_make_new((mp_obj_t)&rawfile_type, n_args, 0, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open); + +void file_init() { + rt_store_name(MP_QSTR_open, (mp_obj_t)&mp_builtin_open_obj); + + mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys); + rt_store_attr(m_sys, MP_QSTR_stdin, fdfile_new(STDIN_FILENO)); + rt_store_attr(m_sys, MP_QSTR_stdout, fdfile_new(STDOUT_FILENO)); + rt_store_attr(m_sys, MP_QSTR_stderr, fdfile_new(STDERR_FILENO)); +} diff --git a/unix/main.c b/unix/main.c index 74e903c2ef..facc250a78 100644 --- a/unix/main.c +++ b/unix/main.c @@ -22,6 +22,7 @@ #endif extern const mp_obj_fun_native_t mp_builtin_open_obj; +void file_init(); void rawsocket_init(); static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { @@ -222,7 +223,8 @@ int main(int argc, char **argv) { rt_store_attr(m_sys, MP_QSTR_argv, py_argv); rt_store_name(qstr_from_str("test"), test_obj_new(42)); - rt_store_name(MP_QSTR_open, (mp_obj_t)&mp_builtin_open_obj); + + file_init(); rawsocket_init(); // Here is some example code to create a class and instance of that class. diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h index 3178f0a826..a470e5dab0 100644 --- a/unix/qstrdefsport.h +++ b/unix/qstrdefsport.h @@ -3,6 +3,9 @@ Q(sys) Q(argv) Q(open) +Q(stdin) +Q(stdout) +Q(stderr) Q(rawsocket) Q(socket) Q(sockaddr_in) diff --git a/unix/socket.c b/unix/socket.c index e43695c6b6..ae87ba4656 100644 --- a/unix/socket.c +++ b/unix/socket.c @@ -127,6 +127,41 @@ static mp_obj_t socket_accept(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); +static mp_obj_t socket_recv(uint n_args, const mp_obj_t *args) { + mp_obj_socket_t *self = args[0]; + int sz = MP_OBJ_SMALL_INT_VALUE(args[1]); + int flags = 0; + + if (n_args > 2) { + flags = MP_OBJ_SMALL_INT_VALUE(args[2]); + } + + char *buf = m_new(char, sz); + int out_sz = recv(self->fd, buf, sz, flags); + RAISE_ERRNO(out_sz, errno); + + buf = m_realloc(buf, sz, out_sz); + return MP_OBJ_NEW_QSTR(qstr_from_strn_take(buf, out_sz, out_sz)); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv); + +static mp_obj_t socket_send(uint n_args, const mp_obj_t *args) { + mp_obj_socket_t *self = args[0]; + int flags = 0; + + if (n_args > 2) { + flags = MP_OBJ_SMALL_INT_VALUE(args[2]); + } + + const char *buf = qstr_str(mp_obj_str_get(args[1])); + int sz = strlen(buf); + int out_sz = send(self->fd, buf, sz, flags); + RAISE_ERRNO(out_sz, errno); + + return MP_OBJ_NEW_SMALL_INT((machine_int_t)out_sz); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send); + static mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { int family = AF_INET; int type = SOCK_STREAM; @@ -159,6 +194,8 @@ static const mp_method_t rawsocket_type_methods[] = { { "bind", &socket_bind_obj }, { "listen", &socket_listen_obj }, { "accept", &socket_accept_obj }, + { "recv", &socket_recv_obj }, + { "send", &socket_send_obj }, { "close", &socket_close_obj }, #if MICROPY_SOCKET_EXTRA { "recv", &mp_stream_read_obj }, @@ -280,5 +317,4 @@ void rawsocket_init() { STORE_INT_CONST(m, SOCK_STREAM); STORE_INT_CONST(m, SOCK_DGRAM); STORE_INT_CONST(m, SOCK_RAW); - rt_store_name(MP_QSTR_rawsocket, m); }