summaryrefslogtreecommitdiff
path: root/ext/stringio
diff options
context:
space:
mode:
authorJean byroot Boussier <jean.boussier+github@shopify.com>2023-06-08 05:27:04 +0200
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2023-08-02 18:18:17 +0900
commitfd8dd7199665ed26818a140de945cca71d6fc84b (patch)
tree01e7363f8c2ef43f62db5bf7ceb7d55b211821da /ext/stringio
parent201fd5751897618eb2a9a91f6f14241f0bad4744 (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.c43
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);