Skip to content

Commit

Permalink
Introduce an adapter from joni 2.1 to 2.2 (#55)
Browse files Browse the repository at this point in the history
JOni 2.2 will hide these public fields and the direct constructors for
Region, so these adapters will bridge the gap until the new API is
widely available. The adapter and calls to it can be removed once JRuby
has shipped a few releases of 9.4 (and possibly 9.3) with the updated
JOni.
  • Loading branch information
headius committed Feb 7, 2023
1 parent 0856e23 commit eb9ae18
Showing 1 changed file with 111 additions and 23 deletions.
134 changes: 111 additions & 23 deletions ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

package org.jruby.ext.strscan;

import jnr.a64asm.REG;
import org.jcodings.Encoding;
import org.joni.Matcher;
import org.joni.NameEntry;
Expand Down Expand Up @@ -102,6 +103,93 @@ public static RubyClass createScannerClass(final Ruby runtime) {
return scannerClass;
}

// Provided temporarily to bridge the gap between joni 2.1 and 2.2
private static final RegionAdapter REGION_ADAPTER;
static {
RegionAdapter adapter;
try {
Region.class.getMethod("newRegion", int.class, int.class);
// ok, proceed with factory-based adapter
adapter = new FactoryRegionAdapter();
} catch (NoSuchMethodException | SecurityException ex) {
adapter = new OldRegionAdapter();
}
REGION_ADAPTER = adapter;
}

private interface RegionAdapter {
Region newRegion(int beg, int end);
int getBeg(Region region, int index);
int getEnd(Region region, int index);
int setBeg(Region region, int index, int value);
int setEnd(Region region, int index, int value);
int getNumRegs(Region region);
}

private static class OldRegionAdapter implements RegionAdapter {
@Override
public Region newRegion(int beg, int end) {
return new Region(beg, end);
}

@Override
public int getBeg(Region region, int index) {
return region.beg[index];
}

@Override
public int getEnd(Region region, int index) {
return region.end[index];
}

@Override
public int setBeg(Region region, int index, int value) {
return region.beg[index] = value;
}

@Override
public int setEnd(Region region, int index, int value) {
return region.end[index] = value;
}

@Override
public int getNumRegs(Region region) {
return region.numRegs;
}
}

private static class FactoryRegionAdapter implements RegionAdapter {
@Override
public Region newRegion(int beg, int end) {
return Region.newRegion(beg, end);
}

@Override
public int getBeg(Region region, int index) {
return region.getBeg(index);
}

@Override
public int getEnd(Region region, int index) {
return region.getEnd(index);
}

@Override
public int setBeg(Region region, int index, int value) {
return region.setBeg(index, value);
}

@Override
public int setEnd(Region region, int index, int value) {
return region.setEnd(index, value);
}

@Override
public int getNumRegs(Region region) {
return region.getNumRegs();
}
}

private void clearMatched() {
scannerFlags &= ~MATCHED_STR_SCN_F;
}
Expand Down Expand Up @@ -131,7 +219,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject string) {
public IRubyObject initialize(ThreadContext context, IRubyObject string, IRubyObject dupOrOpts) {
this.str = string.convertToString();
this.fixedAnchor = ArgsUtil.extractKeywordArg(context, "fixed_anchor", dupOrOpts).isTrue();
this.regs = new Region(0, 0);
this.regs = REGION_ADAPTER.newRegion(0, 0);

return this;
}
Expand Down Expand Up @@ -313,7 +401,7 @@ private IRubyObject scan(ThreadContext context, IRubyObject regex, boolean succp

Region matchRegion = matcher.getRegion();
if (matchRegion == null) {
regs = new Region(matcher.getBegin(), matcher.getEnd());
regs = REGION_ADAPTER.newRegion(matcher.getBegin(), matcher.getEnd());
} else {
regs = matchRegion;
}
Expand Down Expand Up @@ -359,17 +447,17 @@ private IRubyObject scan(ThreadContext context, IRubyObject regex, boolean succp

private int lastMatchLength() {
if (fixedAnchor) {
return regs.end[0] - prev;
return REGION_ADAPTER.getEnd(regs, 0) - prev;
} else {
return regs.end[0];
return REGION_ADAPTER.getEnd(regs, 0);
}
}

private void succ() {
if (fixedAnchor) {
this.curr = this.regs.end[0];
this.curr = REGION_ADAPTER.getEnd(regs, 0);
} else {
this.curr += this.regs.end[0];
this.curr += REGION_ADAPTER.getEnd(regs, 0);
}
}

Expand All @@ -392,9 +480,9 @@ private int restLen() {
// MRI: set_registers
private void setRegisters(int length) {
if (fixedAnchor) {
regs = new Region(curr, curr + length);
regs = REGION_ADAPTER.newRegion(curr, curr + length);
} else {
regs = new Region(0, length);
regs = REGION_ADAPTER.newRegion(0, length);
}
}

Expand Down Expand Up @@ -451,9 +539,9 @@ public IRubyObject search_full(ThreadContext context, IRubyObject regex, IRubyOb
// MRI: adjust_register_to_matched
private void adjustRegisters() {
if (fixedAnchor) {
regs = new Region(prev, curr);
regs = REGION_ADAPTER.newRegion(prev, curr);
} else {
regs = new Region(0, curr - prev);
regs = REGION_ADAPTER.newRegion(0, curr - prev);
}
}

Expand Down Expand Up @@ -485,8 +573,8 @@ public IRubyObject getchCommon(ThreadContext context) {
adjustRegisters();

return extractRange(runtime,
prev + regs.beg[0],
prev + regs.end[0]);
prev + REGION_ADAPTER.getBeg(regs, 0),
prev + REGION_ADAPTER.getEnd(regs, 0));
}

@JRubyMethod(name = "get_byte")
Expand All @@ -501,7 +589,7 @@ public IRubyObject get_byte(ThreadContext context) {
setMatched();
adjustRegisters();

return extractRange(context.runtime, prev + regs.beg[0], prev + regs.end[0]);
return extractRange(context.runtime, prev + REGION_ADAPTER.getBeg(regs, 0), prev + REGION_ADAPTER.getEnd(regs, 0));
}

@JRubyMethod(name = "getbyte")
Expand Down Expand Up @@ -596,14 +684,14 @@ public RubyBoolean matched_p(ThreadContext context) {
public IRubyObject matched(ThreadContext context) {
check(context);
if (!isMatched()) return context.nil;
return extractRange(context.runtime, prev + regs.beg[0], prev + regs.end[0]);
return extractRange(context.runtime, prev + REGION_ADAPTER.getBeg(regs, 0), prev + REGION_ADAPTER.getEnd(regs, 0));
}

@JRubyMethod(name = "matched_size")
public IRubyObject matched_size(ThreadContext context) {
check(context);
if (!isMatched()) return context.nil;
return RubyFixnum.newFixnum(context.runtime, regs.end[0] - regs.beg[0]);
return RubyFixnum.newFixnum(context.runtime, REGION_ADAPTER.getEnd(regs, 0) - REGION_ADAPTER.getBeg(regs, 0));
}

@JRubyMethod(name = "matchedsize")
Expand Down Expand Up @@ -635,14 +723,14 @@ public IRubyObject op_aref(ThreadContext context, IRubyObject idx) {
}

private IRubyObject extractRegion(ThreadContext context, int i) {
int numRegs = regs.numRegs;
int numRegs = REGION_ADAPTER.getNumRegs(regs);

if (i < 0) i += numRegs;
if (i < 0 || i >= numRegs || regs.beg[i] == -1) {
if (i < 0 || i >= numRegs || REGION_ADAPTER.getBeg(regs, i) == -1) {
return context.nil;
}

return extractRange(context.runtime, prev + regs.beg[i], prev + regs.end[i]);
return extractRange(context.runtime, prev + REGION_ADAPTER.getBeg(regs, i), prev + REGION_ADAPTER.getEnd(regs, i));
}

@JRubyMethod(name = "pre_match")
Expand All @@ -651,7 +739,7 @@ public IRubyObject pre_match(ThreadContext context) {
if (!isMatched()) {
return context.nil;
}
return extractRange(context.runtime, 0, prev + regs.beg[0]);
return extractRange(context.runtime, 0, prev + REGION_ADAPTER.getBeg(regs, 0));
}

@JRubyMethod(name = "post_match")
Expand All @@ -662,7 +750,7 @@ public IRubyObject post_match(ThreadContext context) {
return context.nil;
}

return extractRange(context.runtime, prev + regs.end[0], str.getByteList().getRealSize());
return extractRange(context.runtime, prev + REGION_ADAPTER.getEnd(regs, 0), str.getByteList().getRealSize());
}

@JRubyMethod(name = "rest")
Expand Down Expand Up @@ -769,7 +857,7 @@ private IRubyObject inspect2() {
@JRubyMethod(name = "size")
public IRubyObject size(ThreadContext context) {
if (!isMatched()) return context.nil;
return context.runtime.newFixnum(regs.numRegs);
return context.runtime.newFixnum(REGION_ADAPTER.getNumRegs(regs));
}

@JRubyMethod(name = "captures")
Expand All @@ -781,11 +869,11 @@ public IRubyObject captures(ThreadContext context) {

Ruby runtime = context.runtime;

numRegs = regs.numRegs;
numRegs = REGION_ADAPTER.getNumRegs(regs);
newAry = RubyArray.newArray(runtime, numRegs);

for (i = 1; i < numRegs; i++) {
IRubyObject str = extractRange(runtime, prev + regs.beg[i], prev + regs.end[i]);
IRubyObject str = extractRange(runtime, prev + REGION_ADAPTER.getBeg(regs, i), prev + REGION_ADAPTER.getEnd(regs, i));
newAry.push(str);
}

Expand Down

0 comments on commit eb9ae18

Please sign in to comment.