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: a3c648dca805
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: df7961fbd277
Choose a head ref
  • 4 commits
  • 4 files changed
  • 1 contributor

Commits on Dec 13, 2015

  1. Copy the full SHA
    1fba3b5 View commit details
  2. Copy the full SHA
    17005ed View commit details
  3. Copy the full SHA
    258021a View commit details
  4. unused imports in RubyHash

    kares committed Dec 13, 2015
    Copy the full SHA
    df7961f View commit details
Showing with 72 additions and 35 deletions.
  1. +0 −3 core/src/main/java/org/jruby/RubyHash.java
  2. +3 −0 core/src/main/java/org/jruby/RubyObject.java
  3. +62 −32 core/src/main/java/org/jruby/RubyStruct.java
  4. +7 −0 test/mri/ruby/test_struct.rb
3 changes: 0 additions & 3 deletions core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
@@ -38,15 +38,12 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import static org.jruby.RubyEnumerator.enumeratorize;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaUtil;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/RubyObject.java
Original file line number Diff line number Diff line change
@@ -546,6 +546,9 @@ static IRubyObject dig(ThreadContext context, IRubyObject obj, IRubyObject[] arg
if ( obj instanceof RubyHash ) {
return ((RubyHash) obj).dig(context, args, idx);
}
if ( obj instanceof RubyStruct ) {
return ((RubyStruct) obj).dig(context, args, idx);
}
if ( obj.respondsTo("dig") ) {
final int len = args.length - idx;
switch ( len ) {
94 changes: 62 additions & 32 deletions core/src/main/java/org/jruby/RubyStruct.java
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ public class RubyStruct extends RubyObject {
private RubyStruct(Ruby runtime, RubyClass rubyClass) {
super(runtime, rubyClass);

int size = RubyNumeric.fix2int(getInternalVariable((RubyClass)rubyClass, "__size__"));
int size = RubyNumeric.fix2int(getInternalVariable(rubyClass, "__size__"));

values = new IRubyObject[size];

@@ -131,25 +131,29 @@ public RubyFixnum hash(ThreadContext context) {
}

private IRubyObject setByName(String name, IRubyObject value) {
RubyArray member = __member__();
final RubyArray member = __member__();

modify();

for (int i = 0,k=member.getLength(); i < k; i++) {
if (member.eltInternal(i).asJavaString().equals(name)) return values[i] = value;
for ( int i = 0; i < member.getLength(); i++ ) {
if ( member.eltInternal(i).asJavaString().equals(name) ) {
return values[i] = value;
}
}

throw notStructMemberError(name);
return null;
}

private IRubyObject getByName(String name) {
RubyArray member = __member__();
final RubyArray member = __member__();

for (int i = 0,k=member.getLength(); i < k; i++) {
if (member.eltInternal(i).asJavaString().equals(name)) return values[i];
for ( int i = 0; i < member.getLength(); i++ ) {
if ( member.eltInternal(i).asJavaString().equals(name) ) {
return values[i];
}
}

throw notStructMemberError(name);
return null;
}

// Struct methods
@@ -397,7 +401,7 @@ public IRubyObject initializeInternal(ThreadContext context, int provided, IRuby
Helpers.fillNil(values, provided, values.length, context.runtime);
}

return getRuntime().getNil();
return context.nil;
}

// NOTE: no longer used ... should it get deleted?
@@ -488,7 +492,7 @@ private RaiseException notStructMemberError(String name) {
return getRuntime().newNameError("no member '" + name + "' in struct", name);
}

public IRubyObject get(int index) {
public final IRubyObject get(int index) {
return values[index];
}

@@ -666,17 +670,29 @@ public IRubyObject each_pair(final ThreadContext context, final Block block) {

@JRubyMethod(name = "[]", required = 1)
public IRubyObject aref(IRubyObject key) {
return arefImpl( key, false );
}

private IRubyObject arefImpl(IRubyObject key, final boolean nilOnNoMember) {
if (key instanceof RubyString || key instanceof RubySymbol) {
return getByName(key.asJavaString());
final String name = key.asJavaString();
final IRubyObject value = getByName(name);
if ( value == null ) {
if ( nilOnNoMember ) return getRuntime().getNil();
throw notStructMemberError(name);
}
return value;
}
return aref( RubyNumeric.fix2int(key) );
}

int idx = RubyNumeric.fix2int(key);

final IRubyObject aref(int idx) {
idx = idx < 0 ? values.length + idx : idx;

if (idx < 0) {
throw getRuntime().newIndexError("offset " + idx + " too small for struct(size:" + values.length + ")");
} else if (idx >= values.length) {
}
if (idx >= values.length) {
throw getRuntime().newIndexError("offset " + idx + " too large for struct(size:" + values.length + ")");
}

@@ -686,7 +702,10 @@ public IRubyObject aref(IRubyObject key) {
@JRubyMethod(name = "[]=", required = 2)
public IRubyObject aset(IRubyObject key, IRubyObject value) {
if (key instanceof RubyString || key instanceof RubySymbol) {
return setByName(key.asJavaString(), value);
final String name = key.asJavaString();
final IRubyObject val = setByName(name, value);
if ( val == null ) throw notStructMemberError(name);
return value;
}

return aset(RubyNumeric.fix2int(key), value);
@@ -706,38 +725,49 @@ private IRubyObject aset(int idx, IRubyObject value) {
}

// FIXME: This is copied code from RubyArray. Both RE, Struct, and Array should share one impl
// This is also hacky since I construct ruby objects to access ruby arrays through aref instead
// of something lower.
@JRubyMethod(rest = true)
public IRubyObject values_at(IRubyObject[] args) {
int olen = values.length;
RubyArray result = getRuntime().newArray(args.length);
final Ruby runtime = getRuntime();
final int olen = values.length;
RubyArray result = runtime.newArray(args.length);

for (int i = 0; i < args.length; i++) {
if (args[i] instanceof RubyFixnum) {
result.append(aref(args[i]));
final IRubyObject arg = args[i];
if ( arg instanceof RubyFixnum ) {
result.append( aref(arg) );
continue;
}

int beglen[];
if (!(args[i] instanceof RubyRange)) {
} else if ((beglen = ((RubyRange) args[i]).begLenInt(olen, 0)) == null) {
final int[] beglen;
if ( ! ( arg instanceof RubyRange ) ) {
}
else if ( ( beglen = ((RubyRange) args[i]).begLenInt(olen, 0) ) == null ) {
continue;
} else {
int beg = beglen[0];
int len = beglen[1];
int end = len;
for (int j = 0; j < end; j++) {
result.append(aref(getRuntime().newFixnum(j + beg)));
}
else {
final int beg = beglen[0];
final int len = beglen[1];
for (int j = 0; j < len; j++) {
result.append( aref(j + beg) );
}
continue;
}
result.append(aref(getRuntime().newFixnum(RubyNumeric.num2long(args[i]))));
result.append( aref(RubyNumeric.num2int(arg)) );
}

return result;
}

@JRubyMethod(name = "dig", required = 1, rest = true)
public IRubyObject dig(ThreadContext context, IRubyObject[] args) {
return dig(context, args, 0);
}

final IRubyObject dig(ThreadContext context, IRubyObject[] args, int idx) {
final IRubyObject val = arefImpl( args[idx++], true );
return idx == args.length ? val : RubyObject.dig(context, val, args, idx);
}

public static void marshalTo(RubyStruct struct, MarshalStream output) throws java.io.IOException {
output.registerLinkTarget(struct);
output.dumpDefaultObjectHeader('S', struct.getMetaClass());
7 changes: 7 additions & 0 deletions test/mri/ruby/test_struct.rb
Original file line number Diff line number Diff line change
@@ -312,6 +312,13 @@ def test_setter_method_returns_value
assert_equal "[Bug #9353]", x.send(:a=, "[Bug #9353]")
end

def test_dig
klass = @Struct.new(:a)
o = klass.new(klass.new({b: [1, 2, 3]}))
assert_equal(1, o.dig(:a, :a, :b, 0))
assert_nil(o.dig(:b, 0))
end

class TopStruct < Test::Unit::TestCase
include TestStruct