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
15 changes: 11 additions & 4 deletions src/main/java/org/perlonjava/runtime/regex/JoniRegexPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,11 @@ private static InputEncoding buildByteInputEncoding(String input) {

private static InputEncoding buildInputEncoding(String input) {
byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
if (bytes.length == input.length()) {
int[] identity = new int[input.length() + 1];
for (int i = 0; i <= input.length(); i++) identity[i] = i;
return new InputEncoding(bytes, identity, identity);
}
int[] charToByte = JoniRegexMatcher.buildCharToByte(input);
int[] byteToChar = JoniRegexMatcher.buildByteToChar(input, bytes.length, charToByte);
return new InputEncoding(bytes, charToByte, byteToChar);
Expand Down Expand Up @@ -891,6 +896,7 @@ private static final class JoniRegexMatcher implements RegexMatcher {
private final int[] byteToChar;
private Matcher matcher;
private Region captures;
private final int captureCount;
private int regionStart;
private int regionEnd;
private int nextStart;
Expand Down Expand Up @@ -929,6 +935,8 @@ private static final class JoniRegexMatcher implements RegexMatcher {
this.deferredPropertyResolver = deferredPropertyResolver;
this.nonUnicodePropertyWarning = nonUnicodePropertyWarning;
this.alarmInterruptMode = alarmInterruptMode;
this.captureCount = regex.numberOfCaptures();
this.captures = Region.newRegion(captureCount + 1);
InputEncoding encoding = inputEncoding(input, subject, byteMode);
this.bytes = encoding.bytes();
this.charToByte = encoding.charToByte();
Expand All @@ -952,7 +960,7 @@ private boolean find(int option, boolean anchored) {
committedLastClosedCapture = -1;
return false;
}
matcher = regex.matcher(bytes);
matcher = captureCount > 0 ? regex.matcher(bytes) : regex.matcherNoRegion(bytes);
matcher.setAlarmInterruptMode(alarmInterruptMode);
boolean localeMatcher = flags.isLocale()
|| regex.getParsedProgramMetadata().has(
Expand All @@ -979,7 +987,7 @@ private boolean find(int option, boolean anchored) {
result = search(charToByte[globalPosition], charToByte[nextStart],
charToByte[regionEnd], option);
if (result < 0 && searchBeforeGlobalPosition && nextStart > 0) {
matcher = regex.matcher(bytes);
matcher = captureCount > 0 ? regex.matcher(bytes) : regex.matcherNoRegion(bytes);
matcher.setAlarmInterruptMode(alarmInterruptMode);
if (localeMatcher) {
matcher.setLocaleResolver(localeResolver(
Expand Down Expand Up @@ -1031,8 +1039,7 @@ private boolean find(int option, boolean anchored) {
return false;
}
consumedStart = directMatch ? nextStart : toCharOffset(result);
captures = Region.newRegion(regex.numberOfCaptures() + 1);
for (int group = 0; group <= regex.numberOfCaptures(); group++) {
for (int group = 0; group <= captureCount; group++) {
captures.setBeg(group, matcher.captureBegin(group));
captures.setEnd(group, matcher.captureEnd(group));
}
Expand Down
29 changes: 16 additions & 13 deletions src/main/java/org/perlonjava/runtime/regex/RegexQuoteMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import org.perlonjava.runtime.runtimetypes.WarningFlags;

public class RegexQuoteMeta {
private static final ThreadLocal<Integer> CALL_SITE_WARNING_STATE = new ThreadLocal<>();
private static final ThreadLocal<String> CALL_SITE_WARNING_BITS = new ThreadLocal<>();
private static final int CALL_SITE_WARNING_UNSET = Integer.MIN_VALUE;
private static final ThreadLocal<int[]> CALL_SITE_WARNING_STATE = ThreadLocal.withInitial(() -> new int[]{CALL_SITE_WARNING_UNSET});
private static final ThreadLocal<String[]> CALL_SITE_WARNING_BITS = ThreadLocal.withInitial(() -> new String[]{null});
private static final ThreadLocal<String> PARSER_WARNING_BITS = new ThreadLocal<>();
private static final ThreadLocal<String> MATCH_TARGET_NAME = new ThreadLocal<>();

Expand All @@ -16,20 +17,22 @@ public record ConstructionWarningDisposition(boolean enabled, boolean fatal) {
}

public static void setCallSiteWarningState(int state) {
CALL_SITE_WARNING_STATE.set(state);
int[] holder = CALL_SITE_WARNING_STATE.get();
if (holder[0] != state) holder[0] = state;
}

public static void setCallSiteWarningBits(String bits) {
CALL_SITE_WARNING_BITS.set(bits);
String[] holder = CALL_SITE_WARNING_BITS.get();
if (holder[0] != bits) holder[0] = bits;
}

public static String getCallSiteWarningBits() {
return CALL_SITE_WARNING_BITS.get();
return CALL_SITE_WARNING_BITS.get()[0];
}

public static boolean isCallSiteWarningExplicitlyDisabled() {
Integer state = CALL_SITE_WARNING_STATE.get();
return state != null && state < 0;
int state = CALL_SITE_WARNING_STATE.get()[0];
return state != CALL_SITE_WARNING_UNSET && state < 0;
}

public static void setParserWarningBits(String bits) {
Expand Down Expand Up @@ -58,10 +61,10 @@ static void warnAtConstruction(String message, boolean strictDefault) {
// This warning belongs to construction of the interpolated pattern.
// Retaining it on the cached RuntimeRegex re-emits it for every match
// and can leak a warning-enabled compilation into a no-warnings use.
Integer state = CALL_SITE_WARNING_STATE.get();
int state = CALL_SITE_WARNING_STATE.get()[0];
RuntimeScalar warning = new RuntimeScalar(message);
RuntimeScalar where = new RuntimeScalar("");
String warningBits = CALL_SITE_WARNING_BITS.get();
String warningBits = CALL_SITE_WARNING_BITS.get()[0];
if (warningBits == null) {
// Synthetic/interpolated regex wrappers do not always have a
// dedicated quote opcode. Use the active statement mask rather
Expand All @@ -75,7 +78,7 @@ static void warnAtConstruction(String message, boolean strictDefault) {
}
if (disposition.fatal()) {
WarnDie.die(warning, new RuntimeScalar(WarnDie.getPerlLocationFromStack()));
} else if (warningBits != null || state != null) {
} else if (warningBits != null || (state != CALL_SITE_WARNING_UNSET && state != 0)) {
WarnDie.warn(warning, where);
} else {
WarnDie.warnWithCategory(warning, where, warningCategory(message));
Expand All @@ -90,7 +93,7 @@ static void warnAtConstruction(String message, boolean strictDefault) {
public static ConstructionWarningDisposition constructionWarningDisposition(
String message, boolean strictDefault) {
String category = warningCategory(message);
String warningBits = CALL_SITE_WARNING_BITS.get();
String warningBits = CALL_SITE_WARNING_BITS.get()[0];
if (warningBits == null) {
warningBits = WarningBitsRegistry.getRuntimeWarningBits();
}
Expand All @@ -105,8 +108,8 @@ public static ConstructionWarningDisposition constructionWarningDisposition(
enabled && WarningFlags.isFatalInBits(warningBits, category));
}

Integer state = CALL_SITE_WARNING_STATE.get();
if (state != null) {
int state = CALL_SITE_WARNING_STATE.get()[0];
if (state != CALL_SITE_WARNING_UNSET) {
return new ConstructionWarningDisposition(state > 0, state == 2);
}
if (WarningFlags.isWarningSuppressedAtRuntime(category)) {
Expand Down
Loading
Loading