Skip to content

Commit

Permalink
Bit masking logic
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Sep 29, 2023
1 parent 9a91238 commit dd70981
Showing 1 changed file with 71 additions and 19 deletions.
90 changes: 71 additions & 19 deletions core/src/main/java/org/jruby/RubyIOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ public static RubyClass createIOBufferClass(Ruby runtime) {
public static final int NETWORK_ENDIAN = BIG_ENDIAN;

public static RubyIOBuffer newBuffer(Ruby runtime, ByteBuffer base, int size, int flags) {
return new RubyIOBuffer(runtime, runtime.getIO(), base, size, flags);
return new RubyIOBuffer(runtime, runtime.getIOBuffer(), base, size, flags);
}

public static RubyIOBuffer newBuffer(Ruby runtime, int size, int flags) {
return new RubyIOBuffer(runtime, runtime.getIOBuffer(), newBufferBase(runtime, size, flags), size, flags);
}

public RubyIOBuffer(Ruby runtime, RubyClass metaClass) {
Expand Down Expand Up @@ -125,17 +129,7 @@ public void initialize(ThreadContext context, byte[] baseBytes, int size, int fl
// If we are provided a pointer, we use it.
base = ByteBuffer.wrap(baseBytes);
} else if (size != 0) {
// If we are provided a non-zero size, we allocate it:
if ((flags & INTERNAL) == INTERNAL) {
base = ByteBuffer.allocate(size);
} else if ((flags & MAPPED) == MAPPED) {
// no support for SHARED, PRIVATE yet
base = ByteBuffer.allocateDirect(size);
}

if (base == null) {
throw context.runtime.newBufferAllocationError("Could not allocate buffer!");
}
base = newBufferBase(context.runtime, size, flags, base);
} else {
// Otherwise we don't do anything.
return;
Expand All @@ -147,6 +141,22 @@ public void initialize(ThreadContext context, byte[] baseBytes, int size, int fl
this.source = source;
}

private static ByteBuffer newBufferBase(Ruby runtime, int size, int flags) {
ByteBuffer base;

// If we are provided a non-zero size, we allocate it:
if ((flags & INTERNAL) == INTERNAL) {
base = ByteBuffer.allocate(size);
} else if ((flags & MAPPED) == MAPPED) {
// no support for SHARED, PRIVATE yet
base = ByteBuffer.allocateDirect(size);
} else {
throw runtime.newBufferAllocationError("Could not allocate buffer!");
}

return base;
}

// MRI: io_flags_for_size
private static int flagsForSize(int size) {
if (size >= PAGE_SIZE) {
Expand Down Expand Up @@ -1185,23 +1195,65 @@ public IRubyObject set_string(ThreadContext context, IRubyObject _string, IRubyO
}

@JRubyMethod(name = "&")
public IRubyObject op_and(ThreadContext context, IRubyObject mask) {
return context.nil;
public IRubyObject op_and(ThreadContext context, IRubyObject _mask) {
ByteBuffer buffer = getBufferForReading(context);

int mask = _mask.convertToInteger().getIntValue();

RubyIOBuffer outputBuffer = newBuffer(context.runtime, size, flags);
ByteBuffer output = outputBuffer.base;

for (int i = 0; i < buffer.capacity(); i++) {
output.put(i, (byte) (buffer.get(i) & mask));
}

return outputBuffer;
}

@JRubyMethod(name = "|")
public IRubyObject op_or(ThreadContext context, IRubyObject mask) {
return context.nil;
public IRubyObject op_or(ThreadContext context, IRubyObject _mask) {
ByteBuffer buffer = getBufferForReading(context);

int mask = _mask.convertToInteger().getIntValue();

RubyIOBuffer outputBuffer = newBuffer(context.runtime, size, flags);
ByteBuffer output = outputBuffer.base;

for (int i = 0; i < buffer.capacity(); i++) {
output.put(i, (byte) (buffer.get(i) | mask));
}

return outputBuffer;
}

@JRubyMethod(name = "^")
public IRubyObject op_xor(ThreadContext context, IRubyObject mask) {
return context.nil;
public IRubyObject op_xor(ThreadContext context, IRubyObject _mask) {
ByteBuffer buffer = getBufferForReading(context);

int mask = _mask.convertToInteger().getIntValue();

RubyIOBuffer outputBuffer = newBuffer(context.runtime, size, flags);
ByteBuffer output = outputBuffer.base;

for (int i = 0; i < buffer.capacity(); i++) {
output.put(i, (byte) (buffer.get(i) ^ mask));
}

return outputBuffer;
}

@JRubyMethod(name = "~")
public IRubyObject op_not(ThreadContext context) {
return context.nil;
ByteBuffer buffer = getBufferForReading(context);

RubyIOBuffer outputBuffer = newBuffer(context.runtime, size, flags);
ByteBuffer output = outputBuffer.base;

for (int i = 0; i < buffer.capacity(); i++) {
output.put(i, (byte) ~buffer.get(i));
}

return outputBuffer;
}

@JRubyMethod(name = "read")
Expand Down

0 comments on commit dd70981

Please sign in to comment.