From 43598baaaffe014f566875371a440c42803bf104 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 29 Sep 2023 18:36:53 -0500 Subject: [PATCH] Start trying to pass test_io_buffer --- .../main/java/org/jruby/FiberScheduler.java | 7 +- core/src/main/java/org/jruby/RubyIO.java | 3 +- .../src/main/java/org/jruby/RubyIOBuffer.java | 75 ++++++++++++++++--- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/jruby/FiberScheduler.java b/core/src/main/java/org/jruby/FiberScheduler.java index a1e239fa878e..4b5b29aae1f7 100644 --- a/core/src/main/java/org/jruby/FiberScheduler.java +++ b/core/src/main/java/org/jruby/FiberScheduler.java @@ -1,5 +1,6 @@ package org.jruby; +import jnr.constants.platform.Errno; import org.jruby.runtime.Helpers; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; @@ -195,11 +196,11 @@ public static int resultApply(ThreadContext context, IRubyObject result) { } } - public static IRubyObject result(Ruby runtime, int result, int error) { + public static IRubyObject result(Ruby runtime, int result, Errno error) { if (result == -1) { - return RubyFixnum.newFixnum(runtime, error); + return RubyFixnum.newFixnum(runtime, error.value()); } else { - return RubyFixnum.newFixnum(runtime, error); + return RubyFixnum.newFixnum(runtime, result); } } } diff --git a/core/src/main/java/org/jruby/RubyIO.java b/core/src/main/java/org/jruby/RubyIO.java index 55ca0416a9b1..9556315d3dcf 100644 --- a/core/src/main/java/org/jruby/RubyIO.java +++ b/core/src/main/java/org/jruby/RubyIO.java @@ -3137,7 +3137,8 @@ IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolean nonblo fptr = getOpenFileChecked(); - final boolean locked = fptr.lock(); int n; + final boolean locked = fptr.lock(); + int n; try { fptr.checkByteReadable(context); diff --git a/core/src/main/java/org/jruby/RubyIOBuffer.java b/core/src/main/java/org/jruby/RubyIOBuffer.java index aea9479ad505..e5f3f0ab51a9 100644 --- a/core/src/main/java/org/jruby/RubyIOBuffer.java +++ b/core/src/main/java/org/jruby/RubyIOBuffer.java @@ -85,9 +85,28 @@ public RubyIOBuffer(Ruby runtime, RubyClass metaClass, ByteBuffer base, int size this.flags = flags; } - @JRubyMethod(name = "for") - public static IRubyObject rbFor(ThreadContext context, IRubyObject self, IRubyObject string) { - return context.nil; + @JRubyMethod(name = "for", meta = true) + public static IRubyObject rbFor(ThreadContext context, IRubyObject self, IRubyObject _string, Block block) { + RubyString string = _string.convertToString(); + + // If the string is frozen, both code paths are okay. + // If the string is not frozen, if a block is not given, it must be frozen. + boolean isGiven = block.isGiven(); + if (!isGiven) { + // This internally returns the source string if it's already frozen. + string = string.newFrozen(); + } + + ByteList bytes = string.getByteList(); + int size = bytes.realSize(); + + RubyIOBuffer buffer = newBuffer(context.runtime, ByteBuffer.wrap(bytes.unsafeBytes(), bytes.begin(), size), size, flagsForSize(size)); + + if (isGiven) { + return block.yieldSpecific(context, buffer); + } + + return buffer; } @JRubyMethod(name = "initialize") @@ -385,7 +404,9 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) { @JRubyMethod(name = "resize") public IRubyObject resize(ThreadContext context, IRubyObject size) { - return context.nil; + resize(context, size.convertToInteger().getIntValue()); + + return this; } // MRI: rb_io_buffer_resize @@ -506,7 +527,7 @@ private boolean freeInternal(ThreadContext context) { return false; } - @JRubyMethod(name = "size_of") + @JRubyMethod(name = "size_of", meta = true) public static IRubyObject size_of(ThreadContext context, IRubyObject self, IRubyObject dataType) { if (dataType instanceof RubyArray) { long total = 0; @@ -905,40 +926,58 @@ private static void setValue(ThreadContext context, ByteBuffer buffer, int size, switch (dataType) { case S8: writeByte(context, buffer, offset, (byte) unwrapLong(value)); + return; case U8: writeUnsignedByte(context, buffer, offset, (int) unwrapLong(value)); + return; case u16: writeUnsignedShort(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, (int) unwrapLong(value)); + return; case U16: writeUnsignedShort(context, buffer, offset, ByteOrder.BIG_ENDIAN, (int) unwrapLong(value)); + return; case s16: writeShort(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, (short) unwrapLong(value)); + return; case S16: writeShort(context, buffer, offset, ByteOrder.BIG_ENDIAN, (short) unwrapLong(value)); + return; case u32: - writeUnsignedInt(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, (long) unwrapLong(value)); + writeUnsignedInt(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, unwrapLong(value)); + return; case U32: - writeUnsignedInt(context, buffer, offset, ByteOrder.BIG_ENDIAN, (long) unwrapLong(value)); + writeUnsignedInt(context, buffer, offset, ByteOrder.BIG_ENDIAN, unwrapLong(value)); + return; case s32: writeInt(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, (int) unwrapLong(value)); + return; case S32: writeInt(context, buffer, offset, ByteOrder.BIG_ENDIAN, (int) unwrapLong(value)); + return; case u64: writeUnsignedLong(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, unwrapUnsignedLong(value)); + return; case U64: writeUnsignedLong(context, buffer, offset, ByteOrder.BIG_ENDIAN, unwrapUnsignedLong(value)); + return; case s64: writeLong(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, unwrapLong(value)); + return; case S64: writeLong(context, buffer, offset, ByteOrder.BIG_ENDIAN, unwrapLong(value)); + return; case f32: writeFloat(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, (float) unwrapDouble(value)); + return; case F32: writeFloat(context, buffer, offset, ByteOrder.BIG_ENDIAN, (float) unwrapDouble(value)); + return; case f64: writeDouble(context, buffer, offset, ByteOrder.LITTLE_ENDIAN, unwrapDouble(value)); + return; case F64: writeDouble(context, buffer, offset, ByteOrder.BIG_ENDIAN, unwrapDouble(value)); + return; } throw context.runtime.newArgumentError("Unknown data_type: " + dataType); // should never happen @@ -1240,7 +1279,7 @@ public IRubyObject op_xor(ThreadContext context, IRubyObject _mask) { return outputBuffer; } - @JRubyMethod(name = "~") + @JRubyMethod(name = "~@") public IRubyObject op_not(ThreadContext context) { ByteBuffer buffer = getBufferForReading(context); @@ -1296,8 +1335,14 @@ public IRubyObject read(ThreadContext context, IRubyObject io, int length, int o } private static IRubyObject readInternal(ThreadContext context, RubyIO io, ByteBuffer base, int offset, int size) { - int result = OpenFile.readInternal(context, io.openFile, io.openFile.fd(), base, offset, size); - return FiberScheduler.result(context.runtime, result, io.openFile.posix.getErrno().value()); + OpenFile fptr = io.getOpenFileChecked(); + final boolean locked = fptr.lock(); + try { + int result = OpenFile.readInternal(context, fptr, fptr.fd(), base, offset, size); + return FiberScheduler.result(context.runtime, result, fptr.errno()); + } finally { + if (locked) fptr.unlock(); + } } @JRubyMethod(name = "pread") @@ -1366,8 +1411,14 @@ public IRubyObject write(ThreadContext context, IRubyObject io, int length, int } private static IRubyObject writeInternal(ThreadContext context, RubyIO io, ByteBuffer base, int offset, int size) { - int result = OpenFile.writeInternal(context, io.openFile, base, offset, size); - return FiberScheduler.result(context.runtime, result, io.openFile.posix.getErrno().value()); + OpenFile fptr = io.getOpenFileChecked(); + final boolean locked = fptr.lock(); + try { + int result = OpenFile.writeInternal(context, fptr, base, offset, size); + return FiberScheduler.result(context.runtime, result, fptr.errno()); + } finally { + if (locked) fptr.unlock(); + } } @JRubyMethod(name = "pwrite")