diff options
author | Jean byroot Boussier <jean.boussier+github@shopify.com> | 2023-06-08 05:27:04 +0200 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2023-08-02 18:18:17 +0900 |
commit | fd8dd7199665ed26818a140de945cca71d6fc84b (patch) | |
tree | 01e7363f8c2ef43f62db5bf7ceb7d55b211821da /ext/stringio | |
parent | 201fd5751897618eb2a9a91f6f14241f0bad4744 (diff) |
Implement StringIO#pread (#56)
Both for being closer to real IOs and also because it's a convenient API
in multithreaded scenarios.
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
Diffstat (limited to 'ext/stringio')
-rw-r--r-- | ext/stringio/stringio.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 68306cac4b..f5213f2fc0 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -1584,6 +1584,48 @@ strio_read(int argc, VALUE *argv, VALUE self) } /* + * call-seq: + * pread(maxlen, offset) -> string + * pread(maxlen, offset, out_string) -> string + * + * See IO#pread. + */ +static VALUE +strio_pread(int argc, VALUE *argv, VALUE self) +{ + VALUE rb_len, rb_offset, rb_buf; + rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf); + long len = NUM2LONG(rb_len); + long offset = NUM2LONG(rb_offset); + + if (len < 0) { + rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len); + } + + if (offset < 0) { + rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset)); + } + + struct StringIO *ptr = readable(self); + + if (offset >= RSTRING_LEN(ptr->string)) { + rb_eof_error(); + } + + if (NIL_P(rb_buf)) { + return strio_substr(ptr, offset, len, rb_ascii8bit_encoding()); + } + + long rest = RSTRING_LEN(ptr->string) - offset; + if (len > rest) len = rest; + rb_str_resize(rb_buf, len); + rb_enc_associate(rb_buf, rb_ascii8bit_encoding()); + MEMCPY(RSTRING_PTR(rb_buf), RSTRING_PTR(ptr->string) + offset, char, len); + return rb_buf; +} + + +/* * call-seq: * strio.sysread(integer[, outbuf]) -> string * strio.readpartial(integer[, outbuf]) -> string @@ -1843,6 +1885,7 @@ Init_stringio(void) rb_define_method(StringIO, "gets", strio_gets, -1); rb_define_method(StringIO, "readlines", strio_readlines, -1); rb_define_method(StringIO, "read", strio_read, -1); + rb_define_method(StringIO, "pread", strio_pread, -1); rb_define_method(StringIO, "write", strio_write_m, -1); rb_define_method(StringIO, "putc", strio_putc, 1); |