Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5c40a996e8dd
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ac1628379550
Choose a head ref
  • 8 commits
  • 13 files changed
  • 1 contributor

Commits on Jan 1, 2016

  1. Copy the full SHA
    63df8c1 View commit details
  2. [Truffle] b in unpack.

    chrisseaton committed Jan 1, 2016
    Copy the full SHA
    85146e7 View commit details
  3. [Truffle] h in unpack.

    chrisseaton committed Jan 1, 2016
    Copy the full SHA
    ba9625f View commit details

Commits on Jan 2, 2016

  1. Copy the full SHA
    bbd42d0 View commit details
  2. Copy the full SHA
    01b74f6 View commit details
  3. [Truffle] @ in unpack.

    chrisseaton committed Jan 2, 2016
    Copy the full SHA
    11c0aa8 View commit details
  4. [Truffle] x in unpack.

    chrisseaton committed Jan 2, 2016
    Copy the full SHA
    931667b View commit details
  5. Copy the full SHA
    ac16283 View commit details
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/util/Pack.java
Original file line number Diff line number Diff line change
@@ -78,8 +78,8 @@ public class Pack {
private static final String sTooFew = "too few arguments";
private static final byte[] uu_table;
private static final byte[] b64_table;
private static final byte[] sHexDigits;
private static final int[] b64_xtable = new int[256];
public static final byte[] sHexDigits;
public static final int[] b64_xtable = new int[256];
private static final Converter[] converters = new Converter[256];

private static long num2quad(IRubyObject arg) {
@@ -1451,7 +1451,7 @@ private static int utf8Decode(ByteBuffer buffer) {
0x80000000, /* 7 */
};

private static int safeGet(ByteBuffer encode) {
public static int safeGet(ByteBuffer encode) {
while (encode.hasRemaining()) {
int got = encode.get() & 0xff;

2 changes: 2 additions & 0 deletions spec/truffle/tags/core/string/unpack/m_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
fails:String#unpack with format 'M' calls #to_str to coerce the directives string
fails:String#unpack with format 'm' calls #to_str to coerce the directives string
fails:String#unpack with format 'M' ignores the count or '*' modifier and decodes the entire string
fails:String#unpack with format 'm' ignores the count or '*' modifier and decodes the entire string
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
@@ -50,7 +50,7 @@ directive : 'c' count? # int8
| 'M' INT? # mimeString
| 'm' count? # base64String
| ('p' | 'P') # pointer
| '@' INT? # at
| '@' count? # at
| 'X' count? # back
| 'x' count? # nullByte
| subSequence # subSequenceAlternate
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.format.nodes.control;

import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.truffle.format.nodes.PackNode;
import org.jruby.truffle.format.runtime.exceptions.OutsideOfStringException;
import org.jruby.truffle.runtime.RubyContext;

public class AtUnpackNode extends PackNode {

private final int position;

public AtUnpackNode(RubyContext context, int position) {
super(context);
this.position = position;
}

@Override
public Object execute(VirtualFrame frame) {
if (position > getSourceLength(frame)) {
throw new OutsideOfStringException();
}

setSourcePosition(frame, position);

return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.format.nodes.control;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.truffle.format.nodes.PackNode;
import org.jruby.truffle.format.runtime.exceptions.OutsideOfStringException;
import org.jruby.truffle.runtime.RubyContext;

public class BackUnpackNode extends PackNode {

private boolean star;

public BackUnpackNode(RubyContext context, boolean star) {
super(context);
this.star = star;
}

@Override
public Object execute(VirtualFrame frame) {
final int position = getSourcePosition(frame);

if (star) {
final int remaining = getSourceLength(frame) - position;

final int target = position - remaining;

if (target < 0) {
CompilerDirectives.transferToInterpreter();
throw new OutsideOfStringException();
}

setSourcePosition(frame, target);
} else {
if (position == 0) {
CompilerDirectives.transferToInterpreter();
throw new OutsideOfStringException();
}

setSourcePosition(frame, position - 1);
}


return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.format.nodes.control;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.truffle.format.nodes.PackNode;
import org.jruby.truffle.format.runtime.exceptions.OutsideOfStringException;
import org.jruby.truffle.runtime.RubyContext;

public class ForwardUnpackNode extends PackNode {

private boolean toEnd;

public ForwardUnpackNode(RubyContext context, boolean toEnd) {
super(context);
this.toEnd = toEnd;
}

@Override
public Object execute(VirtualFrame frame) {
if (toEnd) {
setSourcePosition(frame, getSourceLength(frame));
} else {
final int position = getSourcePosition(frame);

if (position + 1 > getSourceLength(frame)) {
throw new OutsideOfStringException();
}

setSourcePosition(frame, getSourcePosition(frame) + 1);
}

return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.format.nodes.read;

import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jcodings.Encoding;
import org.jcodings.specific.ASCIIEncoding;
import org.jruby.RubyString;
import org.jruby.truffle.format.nodes.PackNode;
import org.jruby.truffle.format.nodes.SourceNode;
import org.jruby.truffle.format.runtime.exceptions.FormatException;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
import org.jruby.util.Pack;
import org.jruby.util.StringSupport;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

@NodeChildren({
@NodeChild(value = "value", type = SourceNode.class),
})
public abstract class ReadBase64StringNode extends PackNode {

private final int requestedLength;

public ReadBase64StringNode(RubyContext context, int requestedLength) {
super(context);
this.requestedLength = requestedLength;
}

@Specialization
public Object read(VirtualFrame frame, byte[] source) {
// Bit string logic copied from jruby.util.Pack - see copyright and authorship there

final ByteBuffer encode = ByteBuffer.wrap(source, getSourcePosition(frame), getSourceLength(frame) - getSourcePosition(frame));

int occurrences = requestedLength;

int length = encode.remaining()*3/4;
byte[] lElem = new byte[length];
int a = -1, b = -1, c = 0, d;
int index = 0;
int s = -1;

if (occurrences == 0){
if (encode.remaining()%4 != 0) {
throw new FormatException("invalid base64");
}
while (encode.hasRemaining() && s != '=') {
a = b = c = -1;
d = -2;

// obtain a
s = Pack.safeGet(encode);
a = Pack.b64_xtable[s];
if (a == -1) throw new FormatException("invalid base64");

// obtain b
s = Pack.safeGet(encode);
b = Pack.b64_xtable[s];
if (b == -1) throw new FormatException("invalid base64");

// obtain c
s = Pack.safeGet(encode);
c = Pack.b64_xtable[s];
if (s == '=') {
if (Pack.safeGet(encode) != '=') throw new FormatException("invalid base64");
break;
}
if (c == -1) throw new FormatException("invalid base64");

// obtain d
s = Pack.safeGet(encode);
d = Pack.b64_xtable[s];
if (s == '=') break;
if (d == -1) throw new FormatException("invalid base64");

// calculate based on a, b, c and d
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
lElem[index++] = (byte)((c << 6 | d) & 255);
}

if (encode.hasRemaining()) throw new FormatException("invalid base64");

if (a != -1 && b != -1) {
if (c == -1 && s == '=') {
if ((b & 15) > 0) throw new FormatException("invalid base64");
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
} else if(c != -1 && s == '=') {
if ((c & 3) > 0) throw new FormatException("invalid base64");
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
}
}
}
else {

while (encode.hasRemaining()) {
a = b = c = d = -1;

// obtain a
s = Pack.safeGet(encode);
while (((a = Pack.b64_xtable[s]) == -1) && encode.hasRemaining()) {
s = Pack.safeGet(encode);
}
if (a == -1) break;

// obtain b
s = Pack.safeGet(encode);
while (((b = Pack.b64_xtable[s]) == -1) && encode.hasRemaining()) {
s = Pack.safeGet(encode);
}
if (b == -1) break;

// obtain c
s = Pack.safeGet(encode);
while (((c = Pack.b64_xtable[s]) == -1) && encode.hasRemaining()) {
if (s == '=') break;
s = Pack.safeGet(encode);
}
if ((s == '=') || c == -1) {
if (s == '=') {
encode.position(encode.position() - 1);
}
break;
}

// obtain d
s = Pack.safeGet(encode);
while (((d = Pack.b64_xtable[s]) == -1) && encode.hasRemaining()) {
if (s == '=') break;
s = Pack.safeGet(encode);
}
if ((s == '=') || d == -1) {
if (s == '=') {
encode.position(encode.position() - 1);
}
break;
}

// calculate based on a, b, c and d
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
lElem[index++] = (byte)((c << 6 | d) & 255);
}

if (a != -1 && b != -1) {
if (c == -1 && s == '=') {
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
} else if(c != -1 && s == '=') {
lElem[index++] = (byte)((a << 2 | b >> 4) & 255);
lElem[index++] = (byte)((b << 4 | c >> 2) & 255);
}
}
}

final Encoding encoding = Encoding.load("ASCII");
final ByteList result = new ByteList(lElem, 0, index, encoding, false);
setSourcePosition(frame, encode.position());

return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), result, StringSupport.CR_UNKNOWN, null);
}

}
Loading