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>
This commit is contained in:
parent
201fd57518
commit
fd8dd71996
@ -1583,6 +1583,48 @@ strio_read(int argc, VALUE *argv, VALUE self)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -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);
|
||||
|
@ -729,6 +729,25 @@ class TestStringIO < Test::Unit::TestCase
|
||||
assert_equal Encoding::ASCII_8BIT, f.sysread(3).encoding
|
||||
end
|
||||
|
||||
def test_pread
|
||||
f = StringIO.new("pread")
|
||||
f.read
|
||||
|
||||
assert_equal "pre".b, f.pread(3, 0)
|
||||
assert_equal "read".b, f.pread(4, 1)
|
||||
assert_equal Encoding::ASCII_8BIT, f.pread(4, 1).encoding
|
||||
|
||||
buf = "".b
|
||||
f.pread(3, 0, buf)
|
||||
assert_equal "pre".b, buf
|
||||
f.pread(4, 1, buf)
|
||||
assert_equal "read".b, buf
|
||||
|
||||
assert_raise(EOFError) { f.pread(1, 5) }
|
||||
assert_raise(ArgumentError) { f.pread(-1, 0) }
|
||||
assert_raise(Errno::EINVAL) { f.pread(3, -1) }
|
||||
end
|
||||
|
||||
def test_size
|
||||
f = StringIO.new("1234")
|
||||
assert_equal(4, f.size)
|
||||
|
Loading…
x
Reference in New Issue
Block a user