diff options
| author | Rubyist <[email protected]> | 2015-07-25 00:24:31 -0700 |
|---|---|---|
| committer | Rubyist <[email protected]> | 2015-07-25 00:24:31 -0700 |
| commit | f80a4fd0e8781b78091028aeddfd50042874ea56 (patch) | |
| tree | ed4fefa733a6f07572d203e0a9e43e18150e368e /src/socket.c | |
| parent | 4ab922044de80da5e6167799d070cec2e73b4204 (diff) | |
| download | mruby-f80a4fd0e8781b78091028aeddfd50042874ea56.tar.gz mruby-f80a4fd0e8781b78091028aeddfd50042874ea56.zip | |
Added functioning read for Win32
Diffstat (limited to 'src/socket.c')
| -rw-r--r-- | src/socket.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/socket.c b/src/socket.c index fc2abed5b..7203db979 100644 --- a/src/socket.c +++ b/src/socket.c @@ -664,6 +664,86 @@ mrb_win32_basicsocket_close(mrb_state *mrb, mrb_value self) } static mrb_value +mrb_win32_basicsocket_read(mrb_state *mrb, mrb_value self) +{ +#define BUF_LEN 4096 + char buf[BUF_LEN]; + int sd, bytes_read; + mrb_int read_len; + mrb_value str = mrb_str_new(mrb, NULL, 0); + mrb_value len_arg = mrb_nil_value(); + + /* For compatibility with IO::read, we accept an object instead of just + * an mrb_int. Then we raise an exception if it isn't an mrb_int or nil. + */ + mrb_get_args(mrb, "|o", &len_arg); + if (mrb_fixnum_p(len_arg)) { + read_len = mrb_fixnum(len_arg); + if (read_len < 0) { + mrb_str_cat_cstr(mrb, str, "negative length: "); + mrb_str_append(mrb, str, len_arg); + mrb_str_cat_cstr(mrb, str, " given"); + mrb_raise(mrb, E_ARGUMENT_ERROR, mrb_string_value_cstr(mrb, &str)); + return mrb_nil_value(); + } else if (read_len == 0) { + return str; + } + } else if (mrb_nil_p(len_arg)) { + read_len = 0; + } else { + mrb_str_cat_cstr(mrb, str, "can't convert "); + mrb_str_append(mrb, str, len_arg); + mrb_str_cat_cstr(mrb, str, " into Integer"); + mrb_raise(mrb, E_TYPE_ERROR, mrb_string_value_cstr(mrb, &str)); + return mrb_nil_value(); + } + + sd = socket_fd(mrb, self); + bytes_read = 0; + + /* Behavior of positive integer argument: read until length bytes have been + * read, or until the socket has closed. */ + if (read_len > 0) { + int n = 0; + int max_read_len = BUF_LEN; + int keep_reading = 1; + while (keep_reading) { + if (max_read_len > (read_len - bytes_read)) + max_read_len = read_len - bytes_read; + n = recv(sd, buf, max_read_len, 0); + + if (n == SOCKET_ERROR) { + mrb_sys_fail(mrb, "recv"); + } else if (n == 0) { + keep_reading = 0; + } else { + mrb_str_cat(mrb, str, buf, n); + bytes_read += n; + if (bytes_read >= read_len) + keep_reading = 0; + } + } + } + /* Behavior of nil/default argument: read until socket has closed */ + else { + int keep_reading = 1; + while (keep_reading) { + bytes_read = recv(sd, buf, BUF_LEN, 0); + if (bytes_read == SOCKET_ERROR) { + mrb_sys_fail(mrb, "recv"); + } else if (bytes_read == 0) { + keep_reading = 0; + } else { + mrb_str_cat(mrb, str, buf, bytes_read); + } + } + } + + return str; +#undef BUF_LEN +} + +static mrb_value mrb_win32_basicsocket_write(mrb_state *mrb, mrb_value self) { int n; @@ -762,6 +842,7 @@ mrb_mruby_socket_gem_init(mrb_state* mrb) /* Windows IO Method Overrides on BasicSocket */ #ifdef _WIN32 mrb_define_method(mrb, bsock, "close", mrb_win32_basicsocket_close, MRB_ARGS_NONE()); + mrb_define_method(mrb, bsock, "read", mrb_win32_basicsocket_read, MRB_ARGS_OPT(1)); mrb_define_method(mrb, bsock, "write", mrb_win32_basicsocket_write, MRB_ARGS_REQ(1)); #endif |
