Skip to content

Commit fd8dd71

Browse files
casperisfinebyroot
authored andcommitted
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>
1 parent 201fd57 commit fd8dd71

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

ext/stringio/stringio.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,48 @@ strio_read(int argc, VALUE *argv, VALUE self)
15831583
return str;
15841584
}
15851585

1586+
/*
1587+
* call-seq:
1588+
* pread(maxlen, offset) -> string
1589+
* pread(maxlen, offset, out_string) -> string
1590+
*
1591+
* See IO#pread.
1592+
*/
1593+
static VALUE
1594+
strio_pread(int argc, VALUE *argv, VALUE self)
1595+
{
1596+
VALUE rb_len, rb_offset, rb_buf;
1597+
rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf);
1598+
long len = NUM2LONG(rb_len);
1599+
long offset = NUM2LONG(rb_offset);
1600+
1601+
if (len < 0) {
1602+
rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
1603+
}
1604+
1605+
if (offset < 0) {
1606+
rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
1607+
}
1608+
1609+
struct StringIO *ptr = readable(self);
1610+
1611+
if (offset >= RSTRING_LEN(ptr->string)) {
1612+
rb_eof_error();
1613+
}
1614+
1615+
if (NIL_P(rb_buf)) {
1616+
return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
1617+
}
1618+
1619+
long rest = RSTRING_LEN(ptr->string) - offset;
1620+
if (len > rest) len = rest;
1621+
rb_str_resize(rb_buf, len);
1622+
rb_enc_associate(rb_buf, rb_ascii8bit_encoding());
1623+
MEMCPY(RSTRING_PTR(rb_buf), RSTRING_PTR(ptr->string) + offset, char, len);
1624+
return rb_buf;
1625+
}
1626+
1627+
15861628
/*
15871629
* call-seq:
15881630
* strio.sysread(integer[, outbuf]) -> string
@@ -1843,6 +1885,7 @@ Init_stringio(void)
18431885
rb_define_method(StringIO, "gets", strio_gets, -1);
18441886
rb_define_method(StringIO, "readlines", strio_readlines, -1);
18451887
rb_define_method(StringIO, "read", strio_read, -1);
1888+
rb_define_method(StringIO, "pread", strio_pread, -1);
18461889

18471890
rb_define_method(StringIO, "write", strio_write_m, -1);
18481891
rb_define_method(StringIO, "putc", strio_putc, 1);

test/stringio/test_stringio.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,25 @@ def test_sysread
729729
assert_equal Encoding::ASCII_8BIT, f.sysread(3).encoding
730730
end
731731

732+
def test_pread
733+
f = StringIO.new("pread")
734+
f.read
735+
736+
assert_equal "pre".b, f.pread(3, 0)
737+
assert_equal "read".b, f.pread(4, 1)
738+
assert_equal Encoding::ASCII_8BIT, f.pread(4, 1).encoding
739+
740+
buf = "".b
741+
f.pread(3, 0, buf)
742+
assert_equal "pre".b, buf
743+
f.pread(4, 1, buf)
744+
assert_equal "read".b, buf
745+
746+
assert_raise(EOFError) { f.pread(1, 5) }
747+
assert_raise(ArgumentError) { f.pread(-1, 0) }
748+
assert_raise(Errno::EINVAL) { f.pread(3, -1) }
749+
end
750+
732751
def test_size
733752
f = StringIO.new("1234")
734753
assert_equal(4, f.size)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy