Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- '3.1'
- '3.2'
- debug
- jruby-head
- jruby-9.4.1.0
- truffleruby
- truffleruby-head
include:
Expand Down
139 changes: 56 additions & 83 deletions ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import org.jruby.ast.util.ArgsUtil;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
Expand All @@ -62,7 +61,9 @@
import static org.jruby.runtime.Visibility.PRIVATE;

/**
* @author kscott
* JRuby implementation of the strscan library from Ruby.
*
* Original implementation by Kelly Nawrocke. Currently a loose port of the C implementation from CRuby.
*/
@JRubyClass(name = "StringScanner")
public class RubyStringScanner extends RubyObject {
Expand All @@ -73,7 +74,7 @@ public class RubyStringScanner extends RubyObject {

private Region regs;
private Regex pattern;
private int scannerFlags;
private boolean matched;
private boolean fixedAnchor;

private static final int MATCHED_STR_SCN_F = 1 << 11;
Expand Down Expand Up @@ -195,15 +196,15 @@ public int getNumRegs(Region region) {
}

private void clearMatched() {
scannerFlags &= ~MATCHED_STR_SCN_F;
matched = false;
}

private void setMatched() {
scannerFlags |= MATCHED_STR_SCN_F;
matched = true;
}

private boolean isMatched() {
return (scannerFlags & MATCHED_STR_SCN_F) != 0;
return matched;
}

private void check(ThreadContext context) {
Expand Down Expand Up @@ -244,7 +245,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject other) {
str = otherScanner.str;
curr = otherScanner.curr;
prev = otherScanner.prev;
scannerFlags = otherScanner.scannerFlags;
matched = otherScanner.matched;

regs = otherScanner.regs.clone();
pattern = otherScanner.pattern;
Expand Down Expand Up @@ -350,20 +351,6 @@ private IRubyObject extractBegLen(Ruby runtime, int beg, int len) {
return str.makeSharedString(runtime, beg, len);
}

final ThreadLocal<Matcher> currentMatcher = new ThreadLocal<>();
final RubyThread.Task<RubyStringScanner, Integer> task = new RubyThread.Task<RubyStringScanner, Integer>() {
@Override
public Integer run(ThreadContext context, RubyStringScanner rubyStringScanner) throws InterruptedException {
ByteList value = str.getByteList();
return currentMatcher.get().matchInterruptible(value.begin() + curr, value.begin() + value.realSize(), Option.NONE);
}

@Override
public void wakeup(RubyThread thread, RubyStringScanner rubyStringScanner) {
thread.getNativeThread().interrupt();
}
};

// MRI: strscan_do_scan
private IRubyObject scan(ThreadContext context, IRubyObject regex, boolean succptr, boolean getstr, boolean headonly) {
final Ruby runtime = context.runtime;
Expand Down Expand Up @@ -625,8 +612,9 @@ public IRubyObject peek(ThreadContext context, IRubyObject length) {
}

ByteList value = str.getByteList();
if (curr >= value.getRealSize()) return RubyString.newEmptyString(context.runtime);
if (curr + len > value.getRealSize()) len = value.getRealSize() - curr;
int realSize = value.getRealSize();
if (curr >= realSize) return RubyString.newEmptyString(context.runtime);
if (curr + len > realSize) len = realSize - curr;

return extractBegLen(context.runtime, curr, len);
}
Expand All @@ -647,7 +635,7 @@ public IRubyObject unscan(ThreadContext context) {
if (!isMatched()) {
Ruby runtime = context.runtime;

RubyClass errorClass = runtime.getClass("StringScanner").getClass("Error");
RubyClass errorClass = (RubyClass) runtime.getClassFromPath("StringScanner::Error");
throw RaiseException.from(runtime, errorClass, "unscan failed: previous match had failed");
}

Expand Down Expand Up @@ -716,7 +704,7 @@ public IRubyObject matchedsize(ThreadContext context) {
if (runtime.isVerbose()) {
runtime.getWarnings().warning(ID.DEPRECATED_METHOD, "StringScanner#matchedsize is obsolete; use #matched_size instead");
}
return matched_size();
return matched_size(context);
}

@JRubyMethod(name = "[]")
Expand Down Expand Up @@ -779,12 +767,13 @@ public IRubyObject rest(ThreadContext context) {
Ruby runtime = context.runtime;

ByteList value = str.getByteList();
int realSize = value.getRealSize();

if (curr >= value.getRealSize()) {
if (curr >= realSize) {
return RubyString.newEmptyString(runtime);
}

return extractRange(runtime, curr, value.getRealSize());
return extractRange(runtime, curr, realSize);
}

@JRubyMethod(name = "rest_size")
Expand All @@ -793,10 +782,11 @@ public RubyFixnum rest_size(ThreadContext context) {
Ruby runtime = context.runtime;

ByteList value = str.getByteList();
int realSize = value.getRealSize();

if (curr >= value.getRealSize()) return RubyFixnum.zero(runtime);
if (curr >= realSize) return RubyFixnum.zero(runtime);

return RubyFixnum.newFixnum(runtime, value.getRealSize() - curr);
return RubyFixnum.newFixnum(runtime, realSize - curr);
}

@JRubyMethod(name = "restsize")
Expand All @@ -812,9 +802,15 @@ public RubyFixnum restsize(ThreadContext context) {
@Override
public IRubyObject inspect() {
if (str == null) return inspect("(uninitialized)");
if (curr >= str.getByteList().getRealSize()) return inspect("fin");
if (curr == 0) return inspect(curr + "/" + str.getByteList().getRealSize() + " @ " + inspect2());
return inspect(curr + "/" + str.getByteList().getRealSize() + " " + inspect1() + " @ " + inspect2());

ByteList byteList = str.getByteList();
int realSize = byteList.getRealSize();

if (curr >= realSize) return inspect("fin");

if (curr == 0) return inspect(curr + "/" + realSize + " @ " + inspect2());

return inspect(curr + "/" + realSize + " " + inspect1() + " @ " + inspect2());
}

@JRubyMethod(name = "fixed_anchor?")
Expand Down Expand Up @@ -859,20 +855,30 @@ private IRubyObject inspect(String msg) {

private IRubyObject inspect1() {
final Ruby runtime = getRuntime();

if (curr == 0) return RubyString.newEmptyString(runtime);

if (curr > INSPECT_LENGTH) {
return RubyString.newStringNoCopy(runtime, DOT_BYTES).append(str.substr(runtime, curr - INSPECT_LENGTH, INSPECT_LENGTH)).inspect();
}

return str.substr(runtime, 0, curr).inspect();
}

private IRubyObject inspect2() {
final Ruby runtime = getRuntime();
if (curr >= str.getByteList().getRealSize()) return RubyString.newEmptyString(runtime);
int len = str.getByteList().getRealSize() - curr;

ByteList byteList = str.getByteList();
int realSize = byteList.getRealSize();

if (curr >= realSize) return RubyString.newEmptyString(runtime);

int len = realSize - curr;

if (len > INSPECT_LENGTH) {
return ((RubyString) str.substr(runtime, curr, INSPECT_LENGTH)).cat(DOT_BYTES).inspect();
}

return str.substr(runtime, curr, len).inspect();
}

Expand Down Expand Up @@ -921,65 +927,32 @@ public IRubyObject values_at(ThreadContext context, IRubyObject[] args) {
return newAry;
}

@Deprecated
public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) {
str = args[0].convertToString();
return this;
}

@Deprecated
public IRubyObject initialize_copy(IRubyObject other) {
return initialize_copy(getRuntime().getCurrentContext(), other);
}

@Deprecated
public IRubyObject concat(IRubyObject obj) {
return concat(getRuntime().getCurrentContext(), obj);
}

@Deprecated
public RubyFixnum pos() {
return pos(getRuntime().getCurrentContext());
}

@Deprecated
public IRubyObject set_pos(IRubyObject pos) {
return set_pos(getRuntime().getCurrentContext(), pos);
}
@JRubyMethod(name = "values_at")
public IRubyObject values_at(ThreadContext context) {
if (!isMatched()) return context.nil;

@Deprecated
public IRubyObject getch19(ThreadContext context) {
return getch(context);
return RubyArray.newEmptyArray(context.runtime);
}

@Deprecated
public IRubyObject reset() {
return reset(getRuntime().getCurrentContext());
}
@JRubyMethod(name = "values_at")
public IRubyObject values_at(ThreadContext context, IRubyObject index) {
if (!isMatched()) return context.nil;

@Deprecated
public IRubyObject unscan() {
return unscan(getRuntime().getCurrentContext());
return RubyArray.newArray(context.runtime, op_aref(context, index));
}

@Deprecated
public IRubyObject matched_size() {
return matched_size(getRuntime().getCurrentContext());
}
@JRubyMethod(name = "values_at")
public IRubyObject values_at(ThreadContext context, IRubyObject index1, IRubyObject index2) {
if (!isMatched()) return context.nil;

@Deprecated
public IRubyObject bol_p() {
return bol_p(getRuntime().getCurrentContext());
return RubyArray.newArray(context.runtime, op_aref(context, index1), op_aref(context, index2));
}

@Deprecated
public RubyFixnum rest_size() {
return rest_size(getRuntime().getCurrentContext());
}
@JRubyMethod(name = "values_at")
public IRubyObject values_at(ThreadContext context, IRubyObject index1, IRubyObject index2, IRubyObject index3) {
if (!isMatched()) return context.nil;

@Deprecated
public IRubyObject getchCommon(ThreadContext context, boolean is1_9) {
return getchCommon(context);
return RubyArray.newArray(context.runtime, op_aref(context, index1), op_aref(context, index2), op_aref(context, index3));
}

/**
Expand Down