3

I'm trying to implement a Java extension for JRuby to perform string xors. I'm just uncertain how to type cast a byte array into a RubyString:

public static RubyString xor(ThreadContext context,  IRubyObject self, RubyString x, RubyString y) {
    byte[] xBytes = x.getBytes();
    byte[] yBytes = y.getBytes();

    int length = yBytes.length < xBytes.length ? yBytes.length : xBytes.length;

    for(int i = 0; i < length; i++) {
        xBytes[i] = (byte) (xBytes[i] ^ yBytes[i]);
    }

    // How to return a RubyString with xBytes as its content?
}

Also, how would one perform the same operation in-place (i.e. xs value is updated)?

fny
  • 31,255
  • 16
  • 96
  • 127
  • There are constructors on RubyString that accept a `byte[]` here `org.jruby.RubyString.RubyString(Ruby runtime, RubyClass rubyClass, byte[] value)` not sure if that's applicable in this instance? – xkickflip Jul 13 '15 at 03:47
  • Looks promising. Any idea what the `rubyClass` argument is supposed to be? – fny Jul 13 '15 at 04:00
  • Not sure about that argument unfortunately. I've used Jruby for years, but haven't tried writing an extension before. Dropping by the #jruby channel on freenode irc may be the quickest way to get some more info – xkickflip Jul 13 '15 at 04:03

2 Answers2

1

return context.runtime.newString(new ByteList(xBytes, false));

fny
  • 31,255
  • 16
  • 96
  • 127
kares
  • 7,076
  • 1
  • 28
  • 38
  • 1
    What is this? Some explanation would be nice. If you don't want to do that, post a comment. – VP. Jul 14 '15 at 11:29
0

You'll first need to wrap the bytes in a ByteList: new ByteList(xBytes, false). The last parameter (Boolean copy) dictates whether to wrap a copy of the Byte array.

To update the string in place, use [RubyString#setValue()][2]:

x.setValue(new ByteList(xBytes, false);
return x;

To return a new RubyString, you can pass that list to the current runtime's #newString():

return context.runtime.newString(new ByteList(xBytes, false));
fny
  • 31,255
  • 16
  • 96
  • 127