Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixes to almost make 1.9 spec run green again.

* Implement IO#getc/chars/each_char/readchar properly
* Fix bad boolean logic for # strings in String#inspect
  • Loading branch information...
commit de86b5a319d3c2503e0ad6d61d5a24c4dcf49bb8 1 parent b30b46a
@headius headius authored
View
1  spec/tags/1.9/ruby/core/io/getc_tags.txt
@@ -1 +0,0 @@
-fails:IO#getc returns the next character from the stream
View
131 src/org/jruby/RubyIO.java
@@ -2363,22 +2363,6 @@ public IRubyObject getc() {
return getRuntime().newFixnum(c);
}
-
- private ByteList fromEncodedBytes(Ruby runtime, Encoding enc, int value) {
- int n;
- try {
- n = value < 0 ? 0 : enc.codeToMbcLength(value);
- } catch (EncodingException ee) {
- n = 0;
- }
-
- if (n <= 0) throw runtime.newRangeError(this.toString() + " out of char range");
-
- ByteList bytes = new ByteList(n);
- enc.codeToMbc(value, bytes.getUnsafeBytes(), 0);
- bytes.setRealSize(n);
- return bytes;
- }
@JRubyMethod(name = "readchar", compat = RUBY1_9)
public IRubyObject readchar19(ThreadContext context) {
@@ -2407,25 +2391,85 @@ public IRubyObject readbyte(ThreadContext context) {
@JRubyMethod(name = "getc", compat = RUBY1_9)
public IRubyObject getc19(ThreadContext context) {
Ruby runtime = context.getRuntime();
- int c = getcCommon();
- if (c == -1) {
- // CRuby checks ferror(f) and retry getc for non-blocking IO
- // read. We checks readability first if possible so retry should
- // not be needed I believe.
- return runtime.getNil();
- }
+ try {
+ OpenFile myOpenFile = getOpenFileChecked();
- Encoding external = getExternalEncoding(runtime);
- ByteList bytes = fromEncodedBytes(runtime, external, (int) c);
- Encoding internal = getInternalEncoding(runtime);
-
- if (internal != null) {
- bytes = RubyString.transcode(context, bytes, external, internal, runtime.getNil());
- }
+ myOpenFile.checkReadable(getRuntime());
+ myOpenFile.setReadBuffered();
+
+ Stream stream = myOpenFile.getMainStreamSafe();
+
+ readCheck(stream);
+ waitReadable(stream);
+ stream.clearerr();
+
+ int c = stream.fgetc();
- // TODO: This should be optimized like RubyInteger.chr is for ascii values
- return RubyString.newStringNoCopy(runtime, bytes, external, 0);
+ if (c == -1) {
+ // CRuby checks ferror(f) and retry getc for non-blocking IO
+ // read. We checks readability first if possible so retry should
+ // not be needed I believe.
+ return runtime.getNil();
+ }
+
+ Encoding external = getExternalEncoding(runtime);
+ Encoding internal = getInternalEncoding(runtime);
+ ByteList bytes = null;
+ boolean shared = false;
+ int cr = 0;
+
+ if (Encoding.isAscii(c)) {
+ if (internal == ASCIIEncoding.INSTANCE) {
+ bytes = RubyInteger.SINGLE_CHAR_BYTELISTS[(int)c];
+ shared = true;
+ } else {
+ bytes = new ByteList(new byte[]{(byte)c}, external, false);
+ shared = false;
+ cr = StringSupport.CR_7BIT;
+ }
+ } else {
+ // potential MBC
+ int len = external.length((byte)c);
+ byte[] byteAry = new byte[len];
+
+ byteAry[0] = (byte)c;
+ for (int i = 1; i < len; i++) {
+ c = (byte)stream.fgetc();
+ if (c == -1) {
+ bytes = new ByteList(byteAry, 0, i - 1, external, false);
+ cr = StringSupport.CR_BROKEN;
+ }
+ byteAry[i] = (byte)c;
+ }
+
+ if (bytes == null) {
+ cr = StringSupport.CR_VALID;
+ bytes = new ByteList(byteAry, external, false);
+ }
+ }
+
+ if (cr != StringSupport.CR_BROKEN && external != internal) {
+ bytes = RubyString.transcode(context, bytes, external, internal, runtime.getNil());
+ }
+
+ if (internal == null) internal = external;
+
+ if (shared) {
+ return RubyString.newStringShared(runtime, bytes, cr);
+ } else {
+ return RubyString.newStringNoCopy(runtime, bytes, internal, cr);
+ }
+
+ } catch (InvalidValueException ex) {
+ throw getRuntime().newErrnoEINVALError();
+ } catch (BadDescriptorException e) {
+ throw getRuntime().newErrnoEBADFError();
+ } catch (EOFException e) {
+ throw getRuntime().newEOFError();
+ } catch (IOException e) {
+ throw getRuntime().newIOErrorFromException(e);
+ }
}
public int getcCommon() {
@@ -3105,16 +3149,35 @@ public IRubyObject each_charInternal(final ThreadContext context, final Block bl
return this;
}
- @JRubyMethod
+ public IRubyObject each_charInternal19(final ThreadContext context, final Block block) {
+ IRubyObject ch;
+
+ while(!(ch = getc19(context)).isNil()) {
+ block.yield(context, ch);
+ }
+ return this;
+ }
+
+ @JRubyMethod(compat = RUBY1_8)
public IRubyObject each_char(final ThreadContext context, final Block block) {
return block.isGiven() ? each_charInternal(context, block) : enumeratorize(context.getRuntime(), this, "each_char");
}
- @JRubyMethod
+ @JRubyMethod(name = "each_char", compat = RUBY1_9)
+ public IRubyObject each_char19(final ThreadContext context, final Block block) {
+ return block.isGiven() ? each_charInternal19(context, block) : enumeratorize(context.getRuntime(), this, "each_char");
+ }
+
+ @JRubyMethod(compat = RUBY1_8)
public IRubyObject chars(final ThreadContext context, final Block block) {
return block.isGiven() ? each_charInternal(context, block) : enumeratorize(context.getRuntime(), this, "chars");
}
+ @JRubyMethod(name = "chars", compat = RUBY1_9)
+ public IRubyObject chars19(final ThreadContext context, final Block block) {
+ return block.isGiven() ? each_charInternal19(context, block) : enumeratorize(context.getRuntime(), this, "chars");
+ }
+
@JRubyMethod
public IRubyObject codepoints(final ThreadContext context, final Block block) {
return eachCodePointCommon(context, block, "codepoints");
View
4 src/org/jruby/RubyString.java
@@ -2414,7 +2414,7 @@ public IRubyObject inspect19() {
result.cat('"');
int prev = p;
while (p < end) {
- int cc;
+ int cc = 0;
int n = StringSupport.preciseLength(enc, bytes, p, end);
if (n <= 0) {
@@ -2432,7 +2432,7 @@ public IRubyObject inspect19() {
if ((enc.isAsciiCompatible() || isUnicode) &&
(c == '"' || c == '\\' ||
(c == '#' && p < end && (StringSupport.preciseLength(enc, bytes, p, end) > 0) &&
- (cc = codePoint(runtime, enc, bytes, p, end)) == '$' && cc == '@' && cc == '{'))) {
+ (cc = codePoint(runtime, enc, bytes, p, end)) == '$' || cc == '@' || cc == '{'))) {
if (p - n > prev) result.cat(bytes, prev, p - n - prev);
result.cat('\\');
if (enc.isAsciiCompatible() || enc == resultEnc) {
Please sign in to comment.
Something went wrong with that request. Please try again.