Skip to content

Commit

Permalink
the SyllablesMatcher now also ignores hex color-sequences in its targets
Browse files Browse the repository at this point in the history
  • Loading branch information
BlvckBytes committed Nov 9, 2024
1 parent 220bcb8 commit 5ef6e7f
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ private boolean matchQueryAgainstTargets(int querySyllable, Syllables target, lo
}

private void addTargetRemainder(int start, int end) {
assert target != null;

// Mini-Message's *ingenious* parser colors whitespace on - for example - rainbows, thus we
// need to check for whether the syllable is just made up of a color-sequence, as to not
// have matches fail because of dangling colors.
if (isColorSequence(target.container, start, end) == (end - start + 1))
return;

targetRemainders.add(start, end, false);

int newRequiredLongs = requiredLongs(targetRemainders.capacity());
Expand All @@ -230,6 +238,62 @@ private void addTargetRemainder(int start, int end) {
}
}

/**
* @return Length of color-sequence at that position, zero if there is none
*/
private int isColorSequence(String input, int position, int lastPosition) {
if (input.charAt(position) != '§')
return 0;

var remainingCharacters = lastPosition - position + 1;

// Need to have at least two characters to be a color-sequence
if (remainingCharacters == 1)
return 0;

var nextContainerChar = input.charAt(position + 1);

// Standard color-sequences
if (
(nextContainerChar >= '0' && nextContainerChar <= '9') ||
(nextContainerChar >= 'a' && nextContainerChar <= 'f') ||
(nextContainerChar >= 'k' && nextContainerChar <= 'o') ||
nextContainerChar == 'r'
) {
return 2;
}

// Hex color-sequences of format §x§<R>§<R>§<G>§<G>§<B>§<B>
if (nextContainerChar == 'x' && remainingCharacters >= 2 + 6 * 2) {
var matchesSequence = true;

for (var i = 1; i <= 6 * 2; i += 2) {
var paragraphChar = input.charAt(position + 1 + i);
var hexColorChar = input.charAt(position + 1 + (i + 1));

if (
paragraphChar == '§' &&
(
Character.isDigit(hexColorChar) ||
(hexColorChar >= 'a' && hexColorChar <= 'f') ||
(hexColorChar >= 'A' && hexColorChar <= 'F')
)
) {
continue;
}

matchesSequence = false;
break;
}

if (matchesSequence)
return 2 + 6 * 2;
}

// Not a color-sequence of any known scheme
return 0;
}

/**
* @return <32b begin_in_target><32b number_of_target_chars>;
* if begin_in_target == Integer.MAX_VALUE then it's not contained;
Expand All @@ -247,6 +311,7 @@ private long relativeIndexOf(int querySyllable, int targetSyllable) {

var querySyllableStart = Syllables.getStartIndex(querySyllable);
var targetSyllableStart = Syllables.getStartIndex(targetSyllable);
var targetSyllableEnd = Syllables.getEndIndex(targetSyllable);

/*
0: A B C
Expand All @@ -268,26 +333,15 @@ private long relativeIndexOf(int querySyllable, int targetSyllable) {
for (int queryOffset = 0; queryOffset < querySyllableLength; ++queryOffset) {
var targetIndex = targetSyllableStart + queryOffset + targetOffset;
var queryIndex = querySyllableStart + queryOffset;
var targetChar = target.container.charAt(targetIndex);

while (targetChar == '§' && targetOffset < highestOffset) {
var nextContainerChar = target.container.charAt(targetIndex + 1);

if (
(nextContainerChar >= '0' && nextContainerChar <= '9')
|| (nextContainerChar >= 'a' && nextContainerChar <= 'f')
|| (nextContainerChar >= 'k' && nextContainerChar <= 'o')
|| nextContainerChar == 'r'
) {
targetOffset += 2;
targetIndex = targetSyllableStart + queryOffset + targetOffset;
targetChar = target.container.charAt(targetIndex);
}

else
break;
int colorSequenceLength;

while ((colorSequenceLength = isColorSequence(target.container, targetIndex, targetSyllableEnd)) != 0) {
targetOffset += colorSequenceLength;
targetIndex += colorSequenceLength;
}

var targetChar = target.container.charAt(targetIndex);
var containedChar = query.container.charAt(queryIndex);

if (charToLower(targetChar) != charToLower(containedChar)) {
Expand All @@ -296,8 +350,10 @@ private long relativeIndexOf(int querySyllable, int targetSyllable) {
}
}

if (didMatch)
return ((long) initialTargetOffset) << 16 | (targetOffset - initialTargetOffset + querySyllableLength);
if (didMatch) {
var numberOfTargetChars = targetOffset - initialTargetOffset + querySyllableLength;
return ((long) initialTargetOffset) << 16 | numberOfTargetChars;
}
}

return ((long) Integer.MAX_VALUE) << 16;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,39 @@ public void shouldIgnoreStandardColorSequences() {
);
}

@Test
public void shouldIgnoreHexColorSequences() {
var coloredString = "§x§F§F§0§0§0§0h§x§F§F§5§F§0§0e§x§F§F§B§F§0§0l§x§D§F§F§F§0§0l§x§7§F§F§F§0§0o§x§1§F§F§F§0§0,§x§0§0§F§F§3§F-§x§0§0§F§F§9§Fw§x§0§0§F§F§F§Fo§x§0§0§9§F§F§Fr§x§0§0§3§F§F§Fl§x§1§F§0§0§F§Fd§x§7§F§0§0§F§F!§x§D§F§0§0§F§F-§x§F§F§0§0§B§F:§x§F§F§0§0§5§F)";

makeUnmatchedCase(
coloredString, "hello,-world!-:)", false,
EMPTY_SYLLABLES,
EMPTY_SYLLABLES
);
}

@Test
public void shouldIgnoreConsecutiveStandardColorSequences() {
var coloredString = "§c§l§kHello-world";

makeUnmatchedCase(
coloredString, "hello-world", false,
EMPTY_SYLLABLES,
EMPTY_SYLLABLES
);
}

@Test
public void shouldIgnoreConsecutiveHexColorSequences() {
var coloredString = "§x§F§F§0§0§0§0§x§0§0§F§F§0§0§x§0§0§0§0§F§FHello-world";

makeUnmatchedCase(
coloredString, "hello-world", false,
EMPTY_SYLLABLES,
EMPTY_SYLLABLES
);
}

@Test
public void shouldResetMatches() {
var remainingTargetSyllables = new Syllables(null)
Expand Down

0 comments on commit 5ef6e7f

Please sign in to comment.