diff --git a/ext/java/org/jruby/ext/stringio/StringIO.java b/ext/java/org/jruby/ext/stringio/StringIO.java index fcabc4eb..ed929b54 100644 --- a/ext/java/org/jruby/ext/stringio/StringIO.java +++ b/ext/java/org/jruby/ext/stringio/StringIO.java @@ -95,9 +95,19 @@ static class StringIOData { private byte flags; // MRI: get_strio, StringIO macro - private StringIOData getPtr() { + private StringIOData getPtrForWrite() { // equivalent to rb_io_taint_check without tainting checkFrozen(); + + checkInitialized(); + + return ptr; + } + + // MRI: get_strio, StringIO macro + private StringIOData getPtrForRead() { + checkInitialized(); + return ptr; } @@ -143,7 +153,7 @@ public static RubyClass createStringIOClass(final Ruby runtime) { // mri: get_enc public Encoding getEncoding() { - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForRead(); Encoding enc = ptr.enc; if (enc != null) { return enc; @@ -158,7 +168,7 @@ public Encoding getEncoding() { } public void setEncoding(Encoding enc) { - getPtr().enc = enc; + getPtrForWrite().enc = enc; } @JRubyMethod(name = "new", rest = true, meta = true) @@ -258,7 +268,7 @@ private static IRubyObject yieldOrReturn(ThreadContext context, Block block, Str try { val = block.yield(context, strio); } finally { - strio.getPtr().string = null; + strio.getPtrForWrite().string = null; strio.flags &= ~STRIO_READWRITE; } } @@ -272,7 +282,7 @@ protected StringIO(Ruby runtime, RubyClass klass) { @JRubyMethod(visibility = PRIVATE, keywords = true) public IRubyObject initialize(ThreadContext context) { - if (getPtr() == null) { + if (ptr == null) { ptr = new StringIOData(); } @@ -284,7 +294,7 @@ public IRubyObject initialize(ThreadContext context) { @JRubyMethod(visibility = PRIVATE, keywords = true) public IRubyObject initialize(ThreadContext context, IRubyObject arg0) { - if (getPtr() == null) { + if (ptr == null) { ptr = new StringIOData(); } @@ -296,7 +306,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject arg0) { @JRubyMethod(visibility = PRIVATE, keywords = true) public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1) { - if (getPtr() == null) { + if (ptr == null) { ptr = new StringIOData(); } @@ -308,7 +318,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObje @JRubyMethod(visibility = PRIVATE, keywords = true) public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { - if (getPtr() == null) { + if (ptr == null) { ptr = new StringIOData(); } @@ -324,7 +334,7 @@ private void strioInit(ThreadContext context, int argc, IRubyObject arg0, IRubyO IRubyObject string = context.nil; IRubyObject vmode = context.nil; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -412,7 +422,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject other) { if (this == otherIO) return this; - ptr = otherIO.getPtr(); + ptr = otherIO.getPtrForRead(); flags = (byte) (flags & ~STRIO_READWRITE | otherIO.flags & STRIO_READWRITE); return this; @@ -420,7 +430,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject other) { @JRubyMethod public IRubyObject binmode(ThreadContext context) { - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); ptr.enc = EncodingUtils.ascii8bitEncoding(context.runtime); if (writable()) ptr.string.setEncoding(ptr.enc); @@ -479,7 +489,7 @@ public IRubyObject closed_p() { public IRubyObject close_read(ThreadContext context) { // ~ checkReadable() : checkInitialized(); - if ( (getPtr().flags & OpenFile.READABLE) == 0 ) { + if ( (getPtrForWrite().flags & OpenFile.READABLE) == 0 ) { throw context.runtime.newIOError("not opened for reading"); } int flags = this.flags; @@ -499,7 +509,7 @@ public IRubyObject closed_read_p() { public IRubyObject close_write(ThreadContext context) { // ~ checkWritable() : checkInitialized(); - if ( (getPtr().flags & OpenFile.WRITABLE) == 0 ) { + if ( (getPtrForWrite().flags & OpenFile.WRITABLE) == 0 ) { throw context.runtime.newIOError("not opened for writing"); } int flags = this.flags; @@ -616,7 +626,7 @@ public IRubyObject each_byte(ThreadContext context, Block block) { if (!block.isGiven()) return enumeratorize(runtime, this, "each_byte"); checkReadable(); - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -650,7 +660,7 @@ public IRubyObject each_char(final ThreadContext context, final Block block) { @JRubyMethod(name = {"eof", "eof?"}) public IRubyObject eof(ThreadContext context) { checkReadable(); - StringIOData ptr = getPtr(); + StringIOData ptr = this.getPtrForRead(); if (!isEndOfString()) return context.fals; return context.tru; } @@ -660,7 +670,7 @@ private boolean isEndOfString() { } private boolean isOutside(int pos) { - StringIOData ptr = getPtr(); + StringIOData ptr = getPtrForRead(); return ptr.string == null || pos >= ptr.string.size(); } @@ -670,7 +680,7 @@ public IRubyObject getc(ThreadContext context) { if (isEndOfString()) return context.nil; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -693,7 +703,7 @@ public IRubyObject getbyte(ThreadContext context) { if (isEndOfString()) return context.nil; int c; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { c = ptr.string.getByteList().get(ptr.pos++) & 0xFF; @@ -707,7 +717,7 @@ public IRubyObject getbyte(ThreadContext context) { // MRI: strio_substr // must be called under lock private RubyString strioSubstr(Ruby runtime, int pos, int len, Encoding enc) { - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForRead(); final RubyString string = ptr.string; int rlen = string.size() - pos; @@ -758,25 +768,25 @@ private static int bm_search(byte[] little, int lstart, int llen, byte[] big, in @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) public IRubyObject gets(ThreadContext context) { - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; return Getline.getlineCall(context, GETLINE, this, getEncoding()); } @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) public IRubyObject gets(ThreadContext context, IRubyObject arg0) { - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0); } @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) public IRubyObject gets(ThreadContext context, IRubyObject arg0, IRubyObject arg1) { - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0, arg1); } @JRubyMethod(name = "gets", writes = FrameField.LASTLINE) public IRubyObject gets(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0, arg1, arg2); } @@ -800,7 +810,7 @@ public IRubyObject gets(ThreadContext context, IRubyObject[] args) { self.checkReadable(); if (limit == 0) { - if (self.getPtr().string == null) return context.nil; + if (self.getPtrForWrite().string == null) return context.nil; return RubyString.newEmptyString(context.runtime, self.getEncoding()); } @@ -816,7 +826,7 @@ public IRubyObject gets(ThreadContext context, IRubyObject[] args) { private static final Getline.Callback GETLINE_YIELD = (context, self, rs, limit, chomp, block) -> { IRubyObject line; - StringIOData ptr = self.getPtr(); + StringIOData ptr = self.getPtrForWrite(); if (ptr.string == null || ptr.pos > ptr.string.size()) { return self; } @@ -839,7 +849,7 @@ public IRubyObject gets(ThreadContext context, IRubyObject[] args) { RubyArray ary = (RubyArray) context.runtime.newArray(); IRubyObject line; - StringIOData ptr = self.getPtr(); + StringIOData ptr = self.getPtrForWrite(); if (ptr.string == null || ptr.pos > ptr.string.size()) { return null; } @@ -871,7 +881,7 @@ private IRubyObject getline(ThreadContext context, final IRubyObject rs, int lim return context.nil; } - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); Encoding enc = getEncoding(); boolean locked = lock(context, ptr); @@ -975,19 +985,19 @@ private static int chompNewlineWidth(byte[] bytes, int s, int e) { @JRubyMethod(name = {"length", "size"}) public IRubyObject length(ThreadContext context) { checkInitialized(); - RubyString myString = getPtr().string; + RubyString myString = getPtrForRead().string; if (myString == null) return RubyFixnum.zero(context.runtime); return getRuntime().newFixnum(myString.size()); } @JRubyMethod(name = "lineno") public IRubyObject lineno(ThreadContext context) { - return context.runtime.newFixnum(getPtr().lineno); + return context.runtime.newFixnum(getPtrForRead().lineno); } @JRubyMethod(name = "lineno=", required = 1) public IRubyObject set_lineno(ThreadContext context, IRubyObject arg) { - getPtr().lineno = RubyNumeric.fix2int(arg); + getPtrForWrite().lineno = RubyNumeric.fix2int(arg); return context.nil; } @@ -996,7 +1006,7 @@ public IRubyObject set_lineno(ThreadContext context, IRubyObject arg) { public IRubyObject pos(ThreadContext context) { checkInitialized(); - return context.runtime.newFixnum(getPtr().pos); + return context.runtime.newFixnum(getPtrForRead().pos); } @JRubyMethod(name = "pos=", required = 1) @@ -1009,13 +1019,13 @@ public IRubyObject set_pos(IRubyObject arg) { if (p > Integer.MAX_VALUE) throw getRuntime().newArgumentError("JRuby does not support StringIO larger than " + Integer.MAX_VALUE + " bytes"); - getPtr().pos = (int)p; + getPtrForWrite().pos = (int)p; return arg; } private void strioExtend(ThreadContext context, int pos, int len) { - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1054,12 +1064,12 @@ public IRubyObject putc(ThreadContext context, IRubyObject ch) { checkModifiable(); if (ch instanceof RubyString) { - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; str = substrString((RubyString) ch, str, runtime); } else { byte c = RubyNumeric.num2chr(ch); - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; str = RubyString.newString(runtime, new byte[]{c}); } write(context, str); @@ -1091,7 +1101,7 @@ private IRubyObject readCommon(ThreadContext context, int argc, IRubyObject arg0 IRubyObject str = context.nil; boolean binary = false; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); int pos = ptr.pos; boolean locked = lock(context, ptr); @@ -1187,7 +1197,7 @@ public IRubyObject pread(ThreadContext context, IRubyObject arg0, IRubyObject ar @SuppressWarnings("fallthrough") private RubyString preadCommon(ThreadContext context, int argc, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { IRubyObject str = context.nil; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForRead(); Ruby runtime = context.runtime; int offset; final RubyString string; @@ -1294,6 +1304,8 @@ public IRubyObject readlines(ThreadContext context, IRubyObject[] args) { // MRI: strio_reopen @JRubyMethod(name = "reopen", keywords = true) public IRubyObject reopen(ThreadContext context) { + checkFrozen(); + // reset the state strioInit(context, 0, null, null, null); return this; @@ -1302,7 +1314,7 @@ public IRubyObject reopen(ThreadContext context) { // MRI: strio_reopen @JRubyMethod(name = "reopen", keywords = true) public IRubyObject reopen(ThreadContext context, IRubyObject arg0) { - checkModifiable(); + checkFrozen(); if (!(arg0 instanceof RubyString)) { return initialize_copy(context, arg0); @@ -1316,7 +1328,7 @@ public IRubyObject reopen(ThreadContext context, IRubyObject arg0) { // MRI: strio_reopen @JRubyMethod(name = "reopen", keywords = true) public IRubyObject reopen(ThreadContext context, IRubyObject arg0, IRubyObject arg1) { - checkModifiable(); + checkFrozen(); // reset the state strioInit(context, 2, arg0, arg1, null); @@ -1326,7 +1338,7 @@ public IRubyObject reopen(ThreadContext context, IRubyObject arg0, IRubyObject a // MRI: strio_reopen @JRubyMethod(name = "reopen", keywords = true) public IRubyObject reopen(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { - checkModifiable(); + checkFrozen(); // reset the state strioInit(context, 3, arg0, arg1, arg2); @@ -1337,7 +1349,7 @@ public IRubyObject reopen(ThreadContext context, IRubyObject arg0, IRubyObject a public IRubyObject rewind(ThreadContext context) { checkInitialized(); - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1370,7 +1382,7 @@ private RubyFixnum seekCommon(ThreadContext context, int argc, IRubyObject arg0, whence = arg1; } - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); checkOpen(); @@ -1405,8 +1417,7 @@ private RubyFixnum seekCommon(ThreadContext context, int argc, IRubyObject arg0, @JRubyMethod(name = "string=", required = 1) public IRubyObject set_string(ThreadContext context, IRubyObject arg) { - checkFrozen(); - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1423,7 +1434,7 @@ public IRubyObject set_string(ThreadContext context, IRubyObject arg) { @JRubyMethod(name = "string") public IRubyObject string(ThreadContext context) { - RubyString string = getPtr().string; + RubyString string = getPtrForRead().string; if (string == null) return context.nil; return string; @@ -1440,7 +1451,7 @@ public IRubyObject truncate(ThreadContext context, IRubyObject len) { checkWritable(); int l = RubyFixnum.fix2int(len); - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); RubyString string = ptr.string; boolean locked = lock(context, ptr); @@ -1472,7 +1483,7 @@ public IRubyObject ungetc(ThreadContext context, IRubyObject arg) { checkModifiable(); checkReadable(); - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; if (arg.isNil()) return arg; if (arg instanceof RubyInteger) { @@ -1499,7 +1510,7 @@ public IRubyObject ungetc(ThreadContext context, IRubyObject arg) { } private void ungetbyteCommon(ThreadContext context, int c) { - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1530,7 +1541,7 @@ private void ungetbyteCommon(ThreadContext context, RubyString ungetBytes) { private void ungetbyteCommon(ThreadContext context, byte[] ungetBytes, int cp, int cl) { if (cl == 0) return; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1585,7 +1596,7 @@ public IRubyObject ungetbyte(ThreadContext context, IRubyObject arg) { if (arg.isNil()) return arg; checkModifiable(); - if (getPtr().string == null) return context.nil; + if (getPtrForWrite().string == null) return context.nil; if (arg instanceof RubyInteger) { ungetbyteCommon(context, ((RubyInteger) ((RubyInteger) arg).op_mod(context, 256)).getIntValue()); @@ -1699,7 +1710,7 @@ private long stringIOWrite(ThreadContext context, Ruby runtime, IRubyObject arg) RubyString str = arg.asString(); int len, olen; - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1810,7 +1821,7 @@ public IRubyObject set_encoding(ThreadContext context, IRubyObject ext_enc) { } } - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -1846,7 +1857,7 @@ public IRubyObject set_encoding(ThreadContext context, IRubyObject enc, IRubyObj @JRubyMethod public IRubyObject set_encoding_by_bom(ThreadContext context) { - StringIOData ptr = getPtr(); + StringIOData ptr = getPtrForWrite(); if (setEncodingByBOM(context, ptr) == null) return context.nil; @@ -1929,7 +1940,7 @@ public IRubyObject each_codepoint(ThreadContext context, Block block) { checkReadable(); - StringIOData ptr = this.getPtr(); + StringIOData ptr = this.getPtrForWrite(); boolean locked = lock(context, ptr); try { @@ -2179,17 +2190,17 @@ public IRubyObject puts(ThreadContext context, IRubyObject[] args) { private boolean readable() { return (flags & STRIO_READABLE) != 0 - && (getPtr().flags & OpenFile.READABLE) != 0; + && (ptr.flags & OpenFile.READABLE) != 0; } private boolean writable() { return (flags & STRIO_WRITABLE) != 0 - && (getPtr().flags & OpenFile.WRITABLE) != 0; + && (ptr.flags & OpenFile.WRITABLE) != 0; } private boolean closed() { return !((flags & STRIO_READWRITE) != 0 - && (getPtr().flags & OpenFile.READWRITE) != 0); + && (ptr.flags & OpenFile.READWRITE) != 0); } /* rb: readable */ @@ -2211,7 +2222,7 @@ private void checkWritable() { } private void checkModifiable() { - final RubyString string = getPtr().string; + final RubyString string = getPtrForWrite().string; if (string == null) { /* Null device StringIO */ } else if (string.isFrozen()) { @@ -2222,7 +2233,7 @@ private void checkModifiable() { } private void checkInitialized() { - if (getPtr() == null) { + if (ptr == null) { throw getRuntime().newIOError("uninitialized stream"); } } diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index c9d7a9f5..bde80b7f 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -62,6 +62,7 @@ struct StringIO { int count; }; +static struct StringIO *get_strio_for_read(VALUE self); static VALUE strio_init(int, VALUE *, struct StringIO *, VALUE); static VALUE strio_unget_bytes(struct StringIO *, const char *, long); static long strio_write(VALUE self, VALUE str); @@ -126,8 +127,14 @@ static const rb_data_type_t strio_data_type = { static struct StringIO* get_strio(VALUE self) { - struct StringIO *ptr = check_strio(rb_io_taint_check(self)); + rb_check_frozen(self); + return get_strio_for_read(self); +} +static struct StringIO* +get_strio_for_read(VALUE self) +{ + struct StringIO *ptr = check_strio(self); if (!ptr) { rb_raise(rb_eIOError, "uninitialized stream"); } @@ -155,6 +162,7 @@ strio_substr(struct StringIO *ptr, long pos, long len, rb_encoding *enc) } #define StringIO(obj) get_strio(obj) +#define StringIOForRead(obj) get_strio_for_read(obj) #define STRIO_READABLE FL_USER4 #define STRIO_WRITABLE FL_USER5 @@ -182,7 +190,7 @@ static VALUE sym_exception; static struct StringIO* readable(VALUE strio) { - struct StringIO *ptr = StringIO(strio); + struct StringIO *ptr = StringIOForRead(strio); if (!READABLE(strio)) { rb_raise(rb_eIOError, "not opened for reading"); } @@ -387,7 +395,8 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self) static VALUE strio_finalize(VALUE self) { - struct StringIO *ptr = StringIO(self); + struct StringIO *ptr = check_strio(self); + if (!ptr) return Qnil; RB_OBJ_WRITE(self, &ptr->string, Qnil); ptr->flags &= ~FMODE_READWRITE; return self; @@ -439,7 +448,7 @@ strio_s_new(int argc, VALUE *argv, VALUE klass) static VALUE strio_false(VALUE self) { - StringIO(self); + StringIOForRead(self); return Qfalse; } @@ -449,7 +458,7 @@ strio_false(VALUE self) static VALUE strio_nil(VALUE self) { - StringIO(self); + StringIOForRead(self); return Qnil; } @@ -459,7 +468,7 @@ strio_nil(VALUE self) static VALUE strio_self(VALUE self) { - StringIO(self); + StringIOForRead(self); return self; } @@ -469,7 +478,7 @@ strio_self(VALUE self) static VALUE strio_0(VALUE self) { - StringIO(self); + StringIOForRead(self); return INT2FIX(0); } @@ -479,7 +488,7 @@ strio_0(VALUE self) static VALUE strio_first(VALUE self, VALUE arg) { - StringIO(self); + StringIOForRead(self); return arg; } @@ -489,7 +498,7 @@ strio_first(VALUE self, VALUE arg) static VALUE strio_unimpl(int argc, VALUE *argv, VALUE self) { - StringIO(self); + StringIOForRead(self); rb_notimplement(); UNREACHABLE; @@ -517,7 +526,7 @@ strio_unimpl(int argc, VALUE *argv, VALUE self) static VALUE strio_get_string(VALUE self) { - return StringIO(self)->string; + return StringIOForRead(self)->string; } /* @@ -650,7 +659,7 @@ strio_close_write(VALUE self) static VALUE strio_closed(VALUE self) { - StringIO(self); + StringIOForRead(self); if (!CLOSED(self)) return Qfalse; return Qtrue; } @@ -671,7 +680,7 @@ strio_closed(VALUE self) static VALUE strio_closed_read(VALUE self) { - StringIO(self); + StringIOForRead(self); if (READABLE(self)) return Qfalse; return Qtrue; } @@ -692,7 +701,7 @@ strio_closed_read(VALUE self) static VALUE strio_closed_write(VALUE self) { - StringIO(self); + StringIOForRead(self); if (WRITABLE(self)) return Qfalse; return Qtrue; } @@ -738,7 +747,7 @@ strio_copy(VALUE copy, VALUE orig) orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio"); if (copy == orig) return copy; - ptr = StringIO(orig); + ptr = StringIOForRead(orig); old_ptr = check_strio(copy); if (old_ptr) { old_string = old_ptr->string; @@ -762,7 +771,7 @@ strio_copy(VALUE copy, VALUE orig) static VALUE strio_get_lineno(VALUE self) { - return LONG2NUM(StringIO(self)->lineno); + return LONG2NUM(StringIOForRead(self)->lineno); } /* @@ -850,7 +859,7 @@ strio_reopen(int argc, VALUE *argv, VALUE self) static VALUE strio_get_pos(VALUE self) { - return LONG2NUM(StringIO(self)->pos); + return LONG2NUM(StringIOForRead(self)->pos); } /* @@ -942,7 +951,7 @@ strio_seek(int argc, VALUE *argv, VALUE self) static VALUE strio_get_sync(VALUE self) { - StringIO(self); + StringIOForRead(self); return Qtrue; } @@ -1863,7 +1872,7 @@ strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self) static VALUE strio_size(VALUE self) { - VALUE string = StringIO(self)->string; + VALUE string = StringIOForRead(self)->string; if (NIL_P(string)) { return INT2FIX(0); } @@ -1915,7 +1924,7 @@ strio_truncate(VALUE self, VALUE len) static VALUE strio_external_encoding(VALUE self) { - struct StringIO *ptr = StringIO(self); + struct StringIO *ptr = StringIOForRead(self); return rb_enc_from_encoding(get_enc(ptr)); } diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 02490626..656c0bb9 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -359,6 +359,9 @@ def test_open def test_isatty assert_equal(false, StringIO.new("").isatty) + assert_equal(false, StringIO.new("").tty?) + assert_nothing_raised { StringIO.new("").freeze.isatty} + assert_nothing_raised { StringIO.new("").freeze.tty?} end def test_fsync @@ -368,6 +371,7 @@ def test_fsync def test_sync assert_equal(true, StringIO.new("").sync) assert_equal(false, StringIO.new("").sync = false) + assert_nothing_raised { StringIO.new("").freeze.sync} end def test_set_fcntl @@ -420,8 +424,8 @@ def test_closed assert_equal(false, f.closed?) f.close assert_equal(true, f.closed?) - ensure - f.close unless f.closed? + f.freeze + assert_nothing_raised { f.closed? } end def test_closed_read @@ -431,8 +435,8 @@ def test_closed_read assert_equal(false, f.closed_read?) f.close_read assert_equal(true, f.closed_read?) - ensure - f.close unless f.closed? + f.freeze + assert_nothing_raised { f.closed_read? } end def test_closed_write @@ -442,8 +446,8 @@ def test_closed_write assert_equal(false, f.closed_write?) f.close_write assert_equal(true, f.closed_write?) - ensure - f.close unless f.closed? + f.freeze + assert_nothing_raised { f.closed_write? } end def test_dup @@ -469,8 +473,8 @@ def test_lineno f.lineno = 1000 assert_equal([1000, "baz\n"], [f.lineno, f.gets]) assert_equal([1001, nil], [f.lineno, f.gets]) - ensure - f.close unless f.closed? + f.freeze + assert_nothing_raised { f.lineno } end def test_pos @@ -483,8 +487,8 @@ def test_pos assert_equal([4, "bar\n"], [f.pos, f.gets]) assert_equal([8, "baz\n"], [f.pos, f.gets]) assert_equal([12, nil], [f.pos, f.gets]) - ensure - f.close unless f.closed? + f.freeze + assert_nothing_raised { f.pos } end def test_reopen @@ -508,13 +512,10 @@ def test_seek assert_raise(Errno::EINVAL) { f.seek(1, 3) } f.close assert_raise(IOError) { f.seek(0) } - ensure - f.close unless f.closed? - end - - def test_seek_frozen_string f = StringIO.new(-"1234") assert_equal(0, f.seek(1)) + ensure + f.close unless f.closed? end def test_each_byte @@ -837,11 +838,17 @@ def test_pread buf = "stale".b assert_equal "stale".b, StringIO.new("").pread(0, 0, buf) assert_equal "stale".b, buf + + assert_nothing_raised { StringIO.new("pread").freeze.pread(3, 0)} end def test_size f = StringIO.new("1234") assert_equal(4, f.size) + assert_equal(4, f.length) + f.freeze + assert_nothing_raised { f.size } + assert_nothing_raised { f.length } end # This test is should in ruby/test_method.rb @@ -1105,6 +1112,65 @@ def test_chilled_string_set_enocoding end end + def test_eof + f = StringIO.new + assert_equal(true, f.eof) + assert_equal(true, f.eof?) + f.ungetc("1234") + assert_equal(false, f.eof) + assert_equal(false, f.eof?) + f.freeze + assert_nothing_raised { f.eof } + assert_nothing_raised { f.eof? } + end + + def test_pid + f = StringIO.new + assert_equal(nil, f.pid) + f.freeze + assert_nothing_raised { f.pid } + end + + def test_fileno + f = StringIO.new + assert_equal(nil, f.fileno) + f.freeze + assert_nothing_raised { f.fileno } + end + + def test_external_encoding + f = StringIO.new + assert_equal(Encoding.find("external"), f.external_encoding) + f = StringIO.new("1234".encode("UTF-16BE")) + assert_equal(Encoding::UTF_16BE, f.external_encoding) + f.freeze + assert_nothing_raised { f.external_encoding } + end + + def test_string + f = StringIO.new + assert_equal("", f.string) + f = StringIO.new("1234") + assert_equal("1234", f.string) + f.freeze + assert_nothing_raised { f.string } + end + + def test_initialize_copy + f = StringIO.new("1234") + f.read(1) + f2 = f.dup + assert_equal(1, f2.pos) + f.read(1) + assert_equal(2, f2.pos) + f.ungetc("56") + assert_equal(0, f2.pos) + assert_equal("5634", f2.string) + f.freeze + f2 = f.dup + assert_not_predicate(f2, :frozen?) + end + private def assert_string(content, encoding, str, mesg = nil)