Skip to content

Instantly share code, notes, and snippets.

@headius
Created December 2, 2025 02:52
Show Gist options
  • Select an option

  • Save headius/3f7a8ad94daf573de0afbfb243e452bb to your computer and use it in GitHub Desktop.

Select an option

Save headius/3f7a8ad94daf573de0afbfb243e452bb to your computer and use it in GitHub Desktop.
Removing ptr from StringIO, which is not compatible with dup'ing
diff --git a/ext/java/org/jruby/ext/stringio/StringIO.java b/ext/java/org/jruby/ext/stringio/StringIO.java
index f3ab1cf..9c58077 100644
--- a/ext/java/org/jruby/ext/stringio/StringIO.java
+++ b/ext/java/org/jruby/ext/stringio/StringIO.java
@@ -79,27 +79,17 @@ import static org.jruby.util.RubyStringBuilder.types;
@JRubyClass(name="StringIO")
@SuppressWarnings("serial")
public class StringIO extends RubyObject implements EncodingCapable, DataType {
- static class StringIOData {
- /**
- * ATTN: the value of internal might be reset to null
- * (during StringIO.open with block), so watch out for that.
- */
- RubyString string;
- Encoding enc;
- int pos;
- int lineno;
- int flags;
- volatile Object owner;
- }
- private StringIOData ptr;
- private byte flags;
+ private RubyString string;
+ private Encoding enc;
+ private int pos;
+ private int lineno;
+ private int flags;
+ private volatile Object owner;
+ private StringIO ptr;
+
+ private byte strioFlags;
// MRI: get_strio, StringIO macro
- private StringIOData getPtr() {
- // equivalent to rb_io_taint_check without tainting
- checkFrozen();
- return ptr;
- }
private static final String
STRINGIO_VERSION = "3.1.10";
@@ -108,7 +98,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
private static final byte STRIO_WRITABLE = 2;
private static final byte STRIO_READWRITE = (STRIO_READABLE | STRIO_WRITABLE);
- private static final AtomicReferenceFieldUpdater<StringIOData, Object> LOCKED_UPDATER = AtomicReferenceFieldUpdater.newUpdater(StringIOData.class, Object.class, "owner");
+ private static final AtomicReferenceFieldUpdater<StringIO, Object> LOCKED_UPDATER = AtomicReferenceFieldUpdater.newUpdater(StringIO.class, Object.class, "owner");
private static final ThreadLocal<Object> VMODE_VPERM_TL = ThreadLocal.withInitial(() -> EncodingUtils.vmodeVperm(null, null));
private static final ThreadLocal<int[]> FMODE_TL = ThreadLocal.withInitial(() -> new int[]{0});
@@ -143,13 +133,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
// mri: get_enc
public Encoding getEncoding() {
- StringIOData ptr = this.getPtr();
- Encoding enc = ptr.enc;
+ checkFrozen();
+ Encoding enc = this.enc;
if (enc != null) {
return enc;
}
- RubyString string = ptr.string;
+ RubyString string = this.string;
if (string != null) {
return string.getEncoding();
}
@@ -158,7 +148,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
public void setEncoding(Encoding enc) {
- getPtr().enc = enc;
+ checkFrozen();
+ StringIO stringIO = ptr;
+ stringIO.enc = enc;
}
@JRubyMethod(name = "new", rest = true, meta = true)
@@ -258,7 +250,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
try {
val = block.yield(context, strio);
} finally {
- strio.getPtr().string = null;
+ strio.checkFrozen();
+ strio.ptr.string = null;
strio.flags &= ~STRIO_READWRITE;
}
}
@@ -272,8 +265,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(visibility = PRIVATE, keywords = true)
public IRubyObject initialize(ThreadContext context) {
- if (getPtr() == null) {
- ptr = new StringIOData();
+ checkFrozen();
+ if (ptr == null) {
+ ptr = this;
}
// does not dispatch quite right and is not really necessary for us
@@ -284,8 +278,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(visibility = PRIVATE, keywords = true)
public IRubyObject initialize(ThreadContext context, IRubyObject arg0) {
- if (getPtr() == null) {
- ptr = new StringIOData();
+ checkFrozen();
+ if (ptr == null) {
+ ptr = this;
}
// does not dispatch quite right and is not really necessary for us
@@ -296,8 +291,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(visibility = PRIVATE, keywords = true)
public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
- if (getPtr() == null) {
- ptr = new StringIOData();
+ checkFrozen();
+ if (ptr == null) {
+ ptr = this;
}
// does not dispatch quite right and is not really necessary for us
@@ -308,8 +304,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(visibility = PRIVATE, keywords = true)
public IRubyObject initialize(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
- if (getPtr() == null) {
- ptr = new StringIOData();
+ checkFrozen();
+ if (ptr == null) {
+ ptr = this;
}
// does not dispatch quite right and is not really necessary for us
@@ -324,7 +321,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
IRubyObject string = context.nil;
IRubyObject vmode = context.nil;
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
@@ -362,7 +359,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
// switch to per-use oflags if it is ever used in the future
EncodingUtils.extractModeEncoding(context, ioEncodable, vmodeAndVpermP, maybeOptions, OFLAGS_UNUSED, fmode);
- ptr.flags = fmode[0];
+ this.flags = fmode[0];
vmode = EncodingUtils.vmode(vmodeAndVpermP);
// clear shared vmodeVperm
@@ -380,25 +377,25 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
} else {
if (vmode.isNil()) {
- ptr.flags |= OpenFile.WRITABLE;
+ this.flags = this.flags | OpenFile.WRITABLE;
}
}
if (!string.isNil() && (ptr.flags & OpenFile.TRUNC) != 0) {
((RubyString) string).clear();
}
if (string instanceof RubyString) {
- ptr.string = (RubyString) string;
+ this.string = (RubyString) string;
}
if (argc == 1 && !string.isNil()) {
- ptr.enc = ((RubyString) string).getEncoding();
+ this.enc = ((RubyString) string).getEncoding();
} else {
- ptr.enc = ioEncodable.enc;
+ this.enc = ioEncodable.enc;
}
- ptr.pos = 0;
- ptr.lineno = 0;
+ this.pos = 0;
+ this.lineno = 0;
if ((ptr.flags & OpenFile.SETENC_BY_BOM) != 0) set_encoding_by_bom(context);
// funky way of shifting readwrite flags into object flags
- flags |= (ptr.flags & OpenFile.READWRITE) * (STRIO_READABLE / OpenFile.READABLE);
+ strioFlags |= (ptr.flags & OpenFile.READWRITE) * (STRIO_READABLE / OpenFile.READABLE);
} finally {
if (locked) unlock(ptr);
}
@@ -412,17 +409,23 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (this == otherIO) return this;
- ptr = otherIO.getPtr();
- flags = (byte) (flags & ~STRIO_READWRITE | otherIO.flags & STRIO_READWRITE);
+ otherIO.checkFrozen();
+ this.string = otherIO.string;
+ this.enc = otherIO.enc;
+ this.pos = otherIO.pos;
+ this.lineno = otherIO.lineno;
+ this.flags = otherIO.flags;
+ this.ptr = this;
+ strioFlags = (byte) (strioFlags & ~STRIO_READWRITE | otherIO.strioFlags & STRIO_READWRITE);
return this;
}
@JRubyMethod
public IRubyObject binmode(ThreadContext context) {
- StringIOData ptr = this.getPtr();
- ptr.enc = EncodingUtils.ascii8bitEncoding(context.runtime);
- if (writable()) ptr.string.setEncoding(ptr.enc);
+ checkFrozen();
+ this.enc = EncodingUtils.ascii8bitEncoding(context.runtime);
+ if (writable()) this.string.setEncoding(ptr.enc);
return this;
}
@@ -464,7 +467,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if ( closed() ) return context.nil;
// NOTE: This is 2.0 behavior to allow dup'ed StringIO to remain open when original is closed
- flags &= ~STRIO_READWRITE;
+ strioFlags &= ~STRIO_READWRITE;
return context.nil;
}
@@ -479,12 +482,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
public IRubyObject close_read(ThreadContext context) {
// ~ checkReadable() :
checkInitialized();
- if ( (getPtr().flags & OpenFile.READABLE) == 0 ) {
+ checkFrozen();
+ if ( (ptr.flags & OpenFile.READABLE) == 0 ) {
throw context.runtime.newIOError("not opened for reading");
}
- int flags = this.flags;
+ int strioFlags = this.strioFlags;
if ( ( flags & STRIO_READABLE ) != 0 ) {
- this.flags = (byte) (flags & ~STRIO_READABLE);
+ this.strioFlags = (byte) (strioFlags & ~STRIO_READABLE);
}
return context.nil;
}
@@ -499,12 +503,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
public IRubyObject close_write(ThreadContext context) {
// ~ checkWritable() :
checkInitialized();
- if ( (getPtr().flags & OpenFile.WRITABLE) == 0 ) {
+ checkFrozen();
+ if ( (ptr.flags & OpenFile.WRITABLE) == 0 ) {
throw context.runtime.newIOError("not opened for writing");
}
- int flags = this.flags;
+ int strioFlags = this.strioFlags;
if ( ( flags & STRIO_WRITABLE ) != 0 ) {
- this.flags = (byte) (flags & ~STRIO_WRITABLE);
+ this.strioFlags = (byte) (strioFlags & ~STRIO_WRITABLE);
}
return context.nil;
}
@@ -616,11 +621,11 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (!block.isGiven()) return enumeratorize(runtime, this, "each_byte");
checkReadable();
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- ByteList bytes = ptr.string.getByteList();
+ ByteList bytes = this.string.getByteList();
// Check the length every iteration, since
// the block can modify this string.
@@ -650,7 +655,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(name = {"eof", "eof?"})
public IRubyObject eof(ThreadContext context) {
checkReadable();
- StringIOData ptr = getPtr();
+ checkFrozen();
if (!isEndOfString()) return context.fals;
return context.tru;
}
@@ -660,8 +665,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
private boolean isOutside(int pos) {
- StringIOData ptr = getPtr();
- return ptr.string == null || pos >= ptr.string.size();
+ checkFrozen();
+ return this.string == null || pos >= this.string.size();
}
@JRubyMethod(name = "getc")
@@ -670,15 +675,15 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (isEndOfString()) return context.nil;
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- int start = ptr.pos;
- RubyString string = ptr.string;
+ int start = this.pos;
+ RubyString string = this.string;
int total = 1 + StringSupport.bytesToFixBrokenTrailingCharacter(string.getByteList(), start + 1);
- ptr.pos += total;
+ this.pos = this.pos + total;
return context.runtime.newString(string.getByteList().makeShared(start, total));
} finally {
@@ -693,10 +698,10 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (isEndOfString()) return context.nil;
int c;
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- c = ptr.string.getByteList().get(ptr.pos++) & 0xFF;
+ c = this.string.getByteList().get(ptr.pos++) & 0xFF;
} finally {
if (locked) unlock(ptr);
}
@@ -707,9 +712,9 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
// MRI: strio_substr
// must be called under lock
private RubyString strioSubstr(Ruby runtime, int pos, int len, Encoding enc) {
- StringIOData ptr = this.getPtr();
+ checkFrozen();
- final RubyString string = ptr.string;
+ final RubyString string = this.string;
int rlen = string.size() - pos;
if (len > rlen) len = rlen;
@@ -758,25 +763,29 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(name = "gets", writes = FrameField.LASTLINE)
public IRubyObject gets(ThreadContext context) {
- if (getPtr().string == null) return context.nil;
+ checkFrozen();
+ if (ptr.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;
+ checkFrozen();
+ if (ptr.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;
+ checkFrozen();
+ if (ptr.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;
+ checkFrozen();
+ if (ptr.string == null) return context.nil;
return Getline.getlineCall(context, GETLINE, this, getEncoding(), arg0, arg1, arg2);
}
@@ -800,7 +809,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
self.checkReadable();
if (limit == 0) {
- if (self.getPtr().string == null) return context.nil;
+ self.checkFrozen();
+ if (self.ptr.string == null) return context.nil;
return RubyString.newEmptyString(context.runtime, self.getEncoding());
}
@@ -816,8 +826,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
private static final Getline.Callback<StringIO, StringIO> GETLINE_YIELD = (context, self, rs, limit, chomp, block) -> {
IRubyObject line;
- StringIOData ptr = self.getPtr();
- if (ptr.string == null || ptr.pos > ptr.string.size()) {
+ self.checkFrozen();
+ if (self.string == null || self.pos > self.string.size()) {
return self;
}
@@ -839,8 +849,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
RubyArray<IRubyObject> ary = (RubyArray<IRubyObject>) context.runtime.newArray();
IRubyObject line;
- StringIOData ptr = self.getPtr();
- if (ptr.string == null || ptr.pos > ptr.string.size()) {
+ self.checkFrozen();
+ if (self.string == null || self.pos > self.string.size()) {
return null;
}
@@ -871,15 +881,15 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
return context.nil;
}
- StringIOData ptr = this.getPtr();
+ checkFrozen();
Encoding enc = getEncoding();
boolean locked = lock(context, ptr);
try {
- final ByteList string = ptr.string.getByteList();
+ final ByteList string = this.string.getByteList();
final byte[] stringBytes = string.getUnsafeBytes();
int begin = string.getBegin();
- int pos = ptr.pos;
+ int pos = this.pos;
int s = begin + pos;
int e = begin + string.getRealSize();
int p;
@@ -955,8 +965,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
str = strioSubstr(runtime, pos, e - s - w, enc);
}
- ptr.pos = e - begin;
- ptr.lineno++;
+ this.pos = e - begin;
+ this.lineno = this.lineno + 1;
} finally {
if (locked) unlock(ptr);
}
@@ -975,19 +985,24 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(name = {"length", "size"})
public IRubyObject length(ThreadContext context) {
checkInitialized();
- RubyString myString = getPtr().string;
+ checkFrozen();
+ RubyString myString = this.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);
+ checkFrozen();
+ return context.runtime.newFixnum(ptr.lineno);
}
@JRubyMethod(name = "lineno=", required = 1)
public IRubyObject set_lineno(ThreadContext context, IRubyObject arg) {
- getPtr().lineno = RubyNumeric.fix2int(arg);
+ checkFrozen();
+ StringIO stringIO = ptr;
+ int lineno1 = RubyNumeric.fix2int(arg);
+ stringIO.lineno = lineno1;
return context.nil;
}
@@ -996,7 +1011,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
public IRubyObject pos(ThreadContext context) {
checkInitialized();
- return context.runtime.newFixnum(getPtr().pos);
+ checkFrozen();
+ return context.runtime.newFixnum(ptr.pos);
}
@JRubyMethod(name = "pos=", required = 1)
@@ -1009,17 +1025,19 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (p > Integer.MAX_VALUE) throw getRuntime().newArgumentError("JRuby does not support StringIO larger than " + Integer.MAX_VALUE + " bytes");
- getPtr().pos = (int)p;
+ checkFrozen();
+ StringIO stringIO = ptr;
+ stringIO.pos = (int)p;
return arg;
}
private void strioExtend(ThreadContext context, int pos, int len) {
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- RubyString string = ptr.string;
+ RubyString string = this.string;
final int olen = string.size();
long newSize = (long) pos + len;
if (newSize > Integer.MAX_VALUE) {
@@ -1054,12 +1072,14 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
checkModifiable();
if (ch instanceof RubyString) {
- if (getPtr().string == null) return context.nil;
+ checkFrozen();
+ if (ptr.string == null) return context.nil;
str = substrString((RubyString) ch, str, runtime);
}
else {
byte c = RubyNumeric.num2chr(ch);
- if (getPtr().string == null) return context.nil;
+ checkFrozen();
+ if (ptr.string == null) return context.nil;
str = RubyString.newString(runtime, new byte[]{c});
}
write(context, str);
@@ -1091,8 +1111,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
IRubyObject str = context.nil;
boolean binary = false;
- StringIOData ptr = this.getPtr();
- int pos = ptr.pos;
+ checkFrozen();
+ int pos = this.pos;
boolean locked = lock(context, ptr);
try {
@@ -1120,11 +1140,11 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
break;
}
case 0:
- RubyString myString = ptr.string;
+ RubyString myString = this.string;
if (myString == null) {
return context.nil;
}
- len = ptr.string.size();
+ len = this.string.size();
if (len <= pos) {
Encoding enc = binary ? ASCIIEncoding.INSTANCE : getEncoding();
if (str.isNil()) {
@@ -1147,7 +1167,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
string = strioSubstr(runtime, pos, len, enc);
} else {
string = (RubyString) str;
- RubyString myString = ptr.string;
+ RubyString myString = this.string;
int rest = myString.size() - pos;
if (len > rest) len = rest;
string.resize(len);
@@ -1161,7 +1181,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
}
- ptr.pos += string.size();
+ int pos1 = this.pos + string.size();
+ this.pos = pos1;
return string;
} finally {
@@ -1187,7 +1208,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@SuppressWarnings("fallthrough")
private RubyString preadCommon(ThreadContext context, int argc, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
IRubyObject str = context.nil;
- StringIOData ptr = this.getPtr();
+ checkFrozen();
Ruby runtime = context.runtime;
int offset;
final RubyString string;
@@ -1238,7 +1259,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
string = (RubyString) str;
- RubyString myString = ptr.string;
+ RubyString myString = this.string;
int rest = myString.size() - offset;
if (len > rest) len = rest;
string.resize(len);
@@ -1337,12 +1358,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
public IRubyObject rewind(ThreadContext context) {
checkInitialized();
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- ptr.pos = 0;
- ptr.lineno = 0;
+ this.pos = 0;
+ this.lineno = 0;
} finally {
if (locked) unlock(ptr);
}
@@ -1370,7 +1391,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
whence = arg1;
}
- StringIOData ptr = this.getPtr();
+ checkFrozen();
checkOpen();
@@ -1380,13 +1401,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
case 0:
break;
case 1:
- offset += ptr.pos;
+ offset += this.pos;
break;
case 2:
if (ptr.string == null) {
offset += 0;
} else {
- offset += ptr.string.size();
+ offset += this.string.size();
}
break;
default:
@@ -1395,7 +1416,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (offset < 0) throw runtime.newErrnoEINVALError("invalid seek value");
- ptr.pos = offset;
+ this.pos = offset;
} finally {
if (locked) unlock(ptr);
}
@@ -1406,16 +1427,18 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(name = "string=", required = 1)
public IRubyObject set_string(ThreadContext context, IRubyObject arg) {
checkFrozen();
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- ptr.flags &= ~OpenFile.READWRITE;
+ int flags2 = this.flags & ~OpenFile.READWRITE;
+ this.flags = flags2;
RubyString str = arg.convertToString();
- ptr.flags = str.isFrozen() ? OpenFile.READABLE : OpenFile.READWRITE;
- ptr.pos = 0;
- ptr.lineno = 0;
- return ptr.string = str;
+ int flags1 = str.isFrozen() ? OpenFile.READABLE : OpenFile.READWRITE;
+ this.flags = flags1;
+ this.pos = 0;
+ this.lineno = 0;
+ return this.string = str;
} finally {
if (locked) unlock(ptr);
}
@@ -1423,7 +1446,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod(name = "string")
public IRubyObject string(ThreadContext context) {
- RubyString string = getPtr().string;
+ checkFrozen();
+ RubyString string = this.string;
if (string == null) return context.nil;
return string;
@@ -1440,8 +1464,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
checkWritable();
int l = RubyFixnum.fix2int(len);
- StringIOData ptr = this.getPtr();
- RubyString string = ptr.string;
+ checkFrozen();
+ RubyString string = this.string;
boolean locked = lock(context, ptr);
try {
@@ -1472,7 +1496,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
checkModifiable();
checkReadable();
- if (getPtr().string == null) return context.nil;
+ checkFrozen();
+ if (ptr.string == null) return context.nil;
if (arg.isNil()) return arg;
if (arg instanceof RubyInteger) {
@@ -1499,13 +1524,13 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
private void ungetbyteCommon(ThreadContext context, int c) {
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- RubyString string = ptr.string;
+ RubyString string = this.string;
string.modify();
- ptr.pos--;
+ this.pos = this.pos - 1;
ByteList bytes = string.getByteList();
@@ -1513,7 +1538,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (ptr.pos == -1) {
bytes.prepend((byte) c);
- ptr.pos = 0;
+ this.pos = 0;
} else {
bytes.set(ptr.pos, c);
}
@@ -1530,12 +1555,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
private void ungetbyteCommon(ThreadContext context, byte[] ungetBytes, int cp, int cl) {
if (cl == 0) return;
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- int pos = ptr.pos, len, rest;
- RubyString str = ptr.string;
+ int pos = this.pos, len, rest;
+ RubyString str = this.string;
ByteList strBytelist;
byte[] strBytes;
int s;
@@ -1571,7 +1596,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
} else {
System.arraycopy(strBytes, s, strBytes, s + pos, cl);
}
- ptr.pos = pos;
+ this.pos = pos;
} finally {
if (locked) unlock(ptr);
}
@@ -1585,7 +1610,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
if (arg.isNil()) return arg;
checkModifiable();
- if (getPtr().string == null) return context.nil;
+ checkFrozen();
+ if (ptr.string == null) return context.nil;
if (arg instanceof RubyInteger) {
ungetbyteCommon(context, ((RubyInteger) ((RubyInteger) arg).op_mod(context, 256)).getIntValue());
@@ -1699,7 +1725,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
RubyString str = arg.asString();
int len, olen;
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
@@ -1718,12 +1744,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
len = str.size();
if (len == 0) return 0;
checkModifiable();
- RubyString myString = ptr.string;
+ RubyString myString = this.string;
olen = myString.size();
if ((ptr.flags & OpenFile.APPEND) != 0) {
- ptr.pos = olen;
+ this.pos = olen;
}
- int pos = ptr.pos;
+ int pos = this.pos;
if (pos == olen) {
if (enc == EncodingUtils.ascii8bitEncoding(runtime) || encStr == EncodingUtils.ascii8bitEncoding(runtime)) {
EncodingUtils.encStrBufCat(runtime, myString, strByteList, enc);
@@ -1736,7 +1762,7 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
ByteList ptrByteList = myString.getByteList();
System.arraycopy(strByteList.getUnsafeBytes(), strByteList.getBegin(), ptrByteList.getUnsafeBytes(), ptrByteList.begin() + pos, len);
}
- ptr.pos = pos + len;
+ this.pos = pos + len;
} finally {
if (locked) unlock(ptr);
}
@@ -1810,14 +1836,14 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
}
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
- ptr.enc = enc;
+ this.enc = enc;
// in read-only mode, StringIO#set_encoding no longer sets the encoding
- RubyString string = ptr.string;
+ RubyString string = this.string;
if (string != null && writable() && string.getEncoding() != enc) {
string.modify();
string.setEncoding(enc);
@@ -1846,22 +1872,22 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
@JRubyMethod
public IRubyObject set_encoding_by_bom(ThreadContext context) {
- StringIOData ptr = getPtr();
+ checkFrozen();
if (setEncodingByBOM(context, ptr) == null) return context.nil;
return context.runtime.getEncodingService().convertEncodingToRubyEncoding(ptr.enc);
}
- private Encoding setEncodingByBOM(ThreadContext context, StringIOData ptr) {
- Encoding enc = detectBOM(context, ptr.string, (ctx, enc2, bomlen) -> {
- ptr.pos = bomlen;
+ private Encoding setEncodingByBOM(ThreadContext context, StringIO ptr) {
+ Encoding enc = detectBOM(context, this.string, (ctx, enc2, bomlen) -> {
+ this.pos = bomlen;
if (writable()) {
- ptr.string.setEncoding(enc2);
+ this.string.setEncoding(enc2);
}
return enc2;
});
- ptr.enc = enc;
+ this.enc = enc;
return enc;
}
@@ -1929,12 +1955,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
checkReadable();
- StringIOData ptr = this.getPtr();
+ checkFrozen();
boolean locked = lock(context, ptr);
try {
final Encoding enc = getEncoding();
- RubyString myString = ptr.string;
+ RubyString myString = this.string;
final ByteList string = myString.getByteList();
final byte[] stringBytes = string.getUnsafeBytes();
int begin = string.getBegin();
@@ -1942,12 +1968,12 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
// check readability for each loop, since it could get closed
checkReadable();
- int pos = ptr.pos;
+ int pos = this.pos;
if (pos >= string.realSize()) return this;
int c = StringSupport.codePoint(runtime, enc, stringBytes, begin + pos, stringBytes.length);
int n = StringSupport.codeLength(enc, c);
- ptr.pos = pos + n;
+ this.pos = pos + n;
block.yield(context, runtime.newFixnum(c));
}
} finally {
@@ -2178,18 +2204,21 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
private boolean readable() {
- return (flags & STRIO_READABLE) != 0
- && (getPtr().flags & OpenFile.READABLE) != 0;
+ if ((strioFlags & STRIO_READABLE) == 0) return false;
+ checkFrozen();
+ return (ptr.flags & OpenFile.READABLE) != 0;
}
private boolean writable() {
- return (flags & STRIO_WRITABLE) != 0
- && (getPtr().flags & OpenFile.WRITABLE) != 0;
+ if ((strioFlags & STRIO_WRITABLE) == 0) return false;
+ checkFrozen();
+ return (ptr.flags & OpenFile.WRITABLE) != 0;
}
private boolean closed() {
- return !((flags & STRIO_READWRITE) != 0
- && (getPtr().flags & OpenFile.READWRITE) != 0);
+ checkFrozen();
+ return !((strioFlags & STRIO_READWRITE) != 0
+ && (ptr.flags & OpenFile.READWRITE) != 0);
}
/* rb: readable */
@@ -2211,7 +2240,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
private void checkModifiable() {
- final RubyString string = getPtr().string;
+ checkFrozen();
+ final RubyString string = this.string;
if (string == null) {
/* Null device StringIO */
} else if (string.isFrozen()) {
@@ -2222,7 +2252,8 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
private void checkInitialized() {
- if (getPtr() == null) {
+ checkFrozen();
+ if (ptr == null) {
throw getRuntime().newIOError("uninitialized stream");
}
}
@@ -2233,13 +2264,14 @@ public class StringIO extends RubyObject implements EncodingCapable, DataType {
}
}
- private static boolean lock(ThreadContext context, StringIOData ptr) {
+ private static boolean lock(ThreadContext context, StringIO ptr) {
if (ptr.owner == context) return false;
while (!LOCKED_UPDATER.compareAndSet(ptr, null, context)); // lock
return true;
}
- private static void unlock(StringIOData ptr) {
+ private static void unlock(StringIO ptr) {
ptr.owner = null; // unlock
}
+
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment