From eb9ae1804cc6905dc41ce984b941bef90f104102 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 7 Feb 2023 23:38:55 +0100 Subject: [PATCH] Introduce an adapter from joni 2.1 to 2.2 (#55) 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. --- .../jruby/ext/strscan/RubyStringScanner.java | 134 +++++++++++++++--- 1 file changed, 111 insertions(+), 23 deletions(-) diff --git a/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java b/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java index 9720c6bd09..bf3d08ca0e 100644 --- a/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java +++ b/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java @@ -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; @@ -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; } @@ -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; } @@ -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; } @@ -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); } } @@ -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); } } @@ -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); } } @@ -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") @@ -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") @@ -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") @@ -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") @@ -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") @@ -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") @@ -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") @@ -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); }