com.oracle.truffle.api.ArrayUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of truffle-api Show documentation
Show all versions of truffle-api Show documentation
Truffle is a multi-language framework for executing dynamic languages
that achieves high performance when combined with Graal.
/*
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.truffle.api;
import java.lang.reflect.Field;
import java.nio.ByteOrder;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import sun.misc.Unsafe;
/**
* This class provides additional operations for {@link String} as well as character and byte
* arrays, which may be intrinsified by a compiler.
*
* @since 19.0
*/
public final class ArrayUtils {
private ArrayUtils() {
}
@SuppressWarnings("deprecation"/* JDK-8277863 */)
static long getObjectFieldOffset(Field field) {
return UNSAFE.objectFieldOffset(field);
}
private static final sun.misc.Unsafe UNSAFE = getUnsafe();
private static final long javaStringValueFieldOffset;
private static final long javaStringCoderFieldOffset;
static {
Field valueField = getStringDeclaredField("value");
javaStringValueFieldOffset = getObjectFieldOffset(valueField);
Field coderField = getStringDeclaredField("coder");
javaStringCoderFieldOffset = getObjectFieldOffset(coderField);
}
private static Field getStringDeclaredField(String name) {
try {
return String.class.getDeclaredField(name);
} catch (NoSuchFieldException e) {
throw new RuntimeException("failed to get " + name + " field offset", e);
}
}
private static Unsafe getUnsafe() {
try {
return Unsafe.getUnsafe();
} catch (SecurityException e1) {
try {
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
} catch (Exception e2) {
throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e2);
}
}
}
private static byte[] getJavaStringArray(String str) {
Object value = UNSAFE.getObject(str, javaStringValueFieldOffset);
assert value instanceof byte[];
return (byte[]) value;
}
private static boolean isCompactString(String s) {
return UNSAFE.getByte(s, javaStringCoderFieldOffset) == 0;
}
/**
* Returns the index of the first occurrence of any character contained in {@code values} in
* {@code string}, bounded by {@code fromIndex} (inclusive) and {@code maxIndex} (exclusive).
*
* @return the index of the first occurrence of any character contained in {@code values} in
* {@code string} that is greater than or equal to {@code fromIndex} and less than
* {@code maxIndex}, or {@code -1} if none of the characters occur.
* @since 19.0
*/
public static int indexOf(String string, int fromIndex, int maxIndex, char... values) {
checkArgs(string.length(), fromIndex, maxIndex, values.length);
if (fromIndex >= string.length()) {
return -1;
}
if (values.length <= 4) {
if (isCompactString(string)) {
int valuesInt = 0;
int nValues = 0;
for (int i = 0; i < values.length; i++) {
if (values[i] <= 0xff) {
valuesInt = (valuesInt << 8) | values[i];
nValues++;
}
}
return nValues == 0 ? -1 : indexOfBS1(getJavaStringArray(string), fromIndex, maxIndex, valuesInt, nValues);
} else {
return indexOfBS2(getJavaStringArray(string), fromIndex, maxIndex, values, values.length);
}
}
return runIndexOfS2(string, fromIndex, maxIndex, values);
}
/**
* Returns the index of the first occurrence of any character contained in {@code values} in
* {@code array}, bounded by {@code fromIndex} (inclusive) and {@code maxIndex} (exclusive).
*
* @return the index of the first occurrence of any character contained in {@code values} in
* {@code array} that is greater than or equal to {@code fromIndex} and less than
* {@code maxIndex}, or {@code -1} if none of the characters occur.
* @since 19.0
*/
public static int indexOf(char[] array, int fromIndex, int maxIndex, char... values) {
checkArgs(array.length, fromIndex, maxIndex, values.length);
if (fromIndex >= array.length) {
return -1;
}
if (values.length <= 4) {
return indexOfCS2(array, fromIndex, maxIndex, values, values.length);
}
return runIndexOfS2(array, fromIndex, maxIndex, values);
}
/**
* Returns the index of the first occurrence of any byte contained in {@code values} in
* {@code array}, bounded by {@code fromIndex} (inclusive) and {@code maxIndex} (exclusive).
*
* @return the index of the first occurrence of any byte contained in {@code values} in
* {@code array} that is greater than or equal to {@code fromIndex} and less than
* {@code maxIndex}, or {@code -1} if none of the values occur.
* @since 19.0
*/
public static int indexOf(byte[] array, int fromIndex, int maxIndex, byte... values) {
checkArgs(array.length, fromIndex, maxIndex, values.length);
if (fromIndex >= array.length) {
return -1;
}
if (values.length <= 4) {
return indexOfBS1(array, fromIndex, maxIndex, values, values.length);
}
return runIndexOfS1(array, fromIndex, maxIndex, values);
}
/**
* Returns the index of the first region of {@code haystack} that equals {@code needle} after
* being OR'ed with {@code mask}, bounded by {@code fromIndex} (inclusive) and {@code length}.
* Performs best if {@code needle} and {@code mask} are {@link CompilationFinal} with
* {@code dimensions = 1}.
*
* @return the index of the first region of {@code haystack} where for all indices {@code i} of
* {@code needle} {@code (haystack[index + i] | mask[i]) == needle[i]} holds, and
* {@code fromIndex <= index && index + needle.length <= fromIndex + length} holds, or
* {@code -1} if no such region is found.
* @since 19.3
*/
public static int indexOfWithOrMask(byte[] haystack, int fromIndex, int length, byte[] needle, byte[] mask) {
checkArgsIndexOf(haystack.length, fromIndex, length);
if (mask != null) {
checkMaskLengthIndexOf(needle.length, mask.length);
}
if (needle.length == 0) {
return fromIndex;
}
if (length - needle.length < 0) {
return -1;
} else if (needle.length == 1) {
if (mask == null) {
return stubIndexOfB1S1(haystack, fromIndex, fromIndex + length, Byte.toUnsignedInt(needle[0]));
}
return stubIndexOfWithOrMaskS1(haystack, fromIndex, fromIndex + length, Byte.toUnsignedInt(needle[0]), Byte.toUnsignedInt(mask[0]));
} else {
int max = fromIndex + length - (needle.length - 2);
int index = fromIndex;
if (mask == null) {
while (index < max - 1) {
index = stubIndexOf2ConsecutiveS1(haystack, index, max, Byte.toUnsignedInt(needle[0]), Byte.toUnsignedInt(needle[1]));
if (index < 0) {
return -1;
}
if (needle.length == 2 || stubRegionEqualsS1(haystack, index, needle, 0, needle.length)) {
return index;
}
index++;
}
} else {
while (index < max - 1) {
index = stubIndexOf2ConsecutiveWithOrMaskS1(haystack, index, max, Byte.toUnsignedInt(needle[0]), Byte.toUnsignedInt(needle[1]), Byte.toUnsignedInt(mask[0]),
Byte.toUnsignedInt(mask[1]));
if (index < 0) {
return -1;
}
if (needle.length == 2 || stubRegionEqualsWithOrMaskS1(haystack, index, needle, 0, mask, mask.length)) {
return index;
}
index++;
}
}
return -1;
}
}
/**
* Returns the index of the first region of {@code haystack} that equals {@code needle} after
* being OR'ed with {@code mask}, bounded by {@code fromIndex} (inclusive) and {@code length}.
* Performs best if {@code needle} and {@code mask} are {@link CompilationFinal} with
* {@code dimensions = 1}.
*
* @return the index of the first region of {@code haystack} where for all indices {@code i} of
* {@code needle} {@code (haystack[index + i] | mask[i]) == needle[i]} holds, and
* {@code fromIndex <= index && index + needle.length <= fromIndex + length} holds, or
* {@code -1} if no such region is found.
* @since 19.3
*/
public static int indexOfWithOrMask(char[] haystack, int fromIndex, int length, char[] needle, char[] mask) {
checkArgsIndexOf(haystack.length, fromIndex, length);
if (mask != null) {
checkMaskLengthIndexOf(needle.length, mask.length);
}
if (needle.length == 0) {
return fromIndex;
}
if (length - needle.length < 0) {
return -1;
} else if (needle.length == 1) {
if (mask == null) {
return stubIndexOfC1S2(haystack, fromIndex, fromIndex + length, needle[0]);
}
return stubIndexOfWithOrMaskS2(haystack, fromIndex, fromIndex + length, needle[0], mask[0]);
} else {
int max = fromIndex + length - (needle.length - 2);
int index = fromIndex;
if (mask == null) {
while (index < max - 1) {
index = stubIndexOf2ConsecutiveS2(haystack, index, max, needle[0], needle[1]);
if (index < 0) {
return -1;
}
if (needle.length == 2 || stubRegionEqualsS2(haystack, index, needle, 0, needle.length)) {
return index;
}
index++;
}
} else {
while (index < max - 1) {
index = stubIndexOf2ConsecutiveWithOrMaskS2(haystack, index, max, needle[0], needle[1], mask[0], mask[1]);
if (index < 0) {
return -1;
}
if (needle.length == 2 || stubRegionEqualsWithOrMaskS2(haystack, index, needle, 0, mask, mask.length)) {
return index;
}
index++;
}
}
return -1;
}
}
/**
* Returns the index of the first region of {@code haystack} that equals {@code needle} after
* being OR'ed with {@code mask}, bounded by {@code fromIndex} (inclusive) and {@code length}.
* Performs best if {@code needle} and {@code mask} are {@link CompilationFinal}.
*
* @return the index of the first region of {@code haystack} where for all indices {@code i} of
* {@code needle}
* {@code (haystack.charAt(index + i) | mask.charAt(i)) == needle.charAt(i)} holds, and
* {@code fromIndex <= index && index + needle.length() <= fromIndex + length} holds, or
* {@code -1} if no such region is found.
* @since 19.3
*/
public static int indexOfWithOrMask(String haystack, int fromIndex, int length, String needle, String mask) {
checkArgsIndexOf(haystack.length(), fromIndex, length);
if (mask != null) {
checkMaskLengthIndexOf(needle.length(), mask.length());
}
if (needle.isEmpty()) {
return fromIndex;
}
if (length - needle.length() < 0) {
return -1;
} else if (needle.length() == 1) {
return indexOfWithOrMaskJLString(haystack, fromIndex, length, needle, mask);
} else {
int max = fromIndex + length - (needle.length() - 2);
int index = fromIndex;
while (index < max - 1) {
index = indexOf2ConsecutiveWithOrMaskJLString(haystack, index, needle, mask, max);
if (index < 0) {
return -1;
}
if (needle.length() == 2 || regionEqualsWithOrMask(haystack, index, needle, 0, needle.length(), mask)) {
return index;
}
index++;
}
return -1;
}
}
private static int indexOfWithOrMaskJLString(String haystack, int fromIndex, int length, String needle, String mask) {
int maxIndex = fromIndex + length;
int v0 = needle.charAt(0);
byte[] array = getJavaStringArray(haystack);
if (mask == null) {
if (isCompactString(haystack)) {
return v0 <= 0xff ? stubIndexOfB1S1(array, fromIndex, maxIndex, v0) : -1;
} else {
return stubIndexOfB1S2(array, fromIndex, maxIndex, v0);
}
} else {
int mask0 = mask.charAt(0);
if (isCompactString(haystack)) {
return (v0 ^ mask0) <= 0xff ? stubIndexOfWithOrMaskS1(array, fromIndex, maxIndex, v0, mask0) : -1;
} else {
return stubIndexOfWithOrMaskS2(array, fromIndex, maxIndex, v0, mask0);
}
}
}
private static int indexOf2ConsecutiveWithOrMaskJLString(String haystack, int fromIndex, String needle, String mask, int max) {
char v0 = needle.charAt(0);
char v1 = needle.charAt(1);
byte[] array = getJavaStringArray(haystack);
if (mask == null) {
if (isCompactString(haystack)) {
return v0 <= 0xff && v1 <= 0xff ? stubIndexOf2ConsecutiveS1(array, fromIndex, max, v0, v1) : -1;
} else {
return stubIndexOf2ConsecutiveS2(array, fromIndex, max, v0, v1);
}
} else {
char mask0 = mask.charAt(0);
char mask1 = mask.charAt(1);
if (isCompactString(haystack)) {
return (v0 ^ mask0) <= 0xff && (v1 ^ mask1) <= 0xff ? stubIndexOf2ConsecutiveWithOrMaskS1(array, fromIndex, max, v0, v1, mask0, mask1) : -1;
} else {
return stubIndexOf2ConsecutiveWithOrMaskS2(array, fromIndex, max, v0, v1, mask0, mask1);
}
}
}
/**
* Returns {@code true} iff for all indices {@code i} from {@code 0} (inclusive) to
* {@code length} (exclusive), {@code (a[offsetA + i] | mask[i]) == b[offsetB + i]} holds.
* Performs best if {@code length} and {@code mask} are {@link CompilationFinal} with
* {@code dimensions = 1}. If {@code mask} is {@code null}, it is treated as if it was filled
* with zeroes.
*
* @since 19.3
*/
public static boolean regionEqualsWithOrMask(byte[] a, int offsetA, byte[] b, int offsetB, int length, byte[] mask) {
requireNonNull(a);
requireNonNull(b);
checkArgsRegionEquals(offsetA, offsetB, length);
if (regionEqualsOutOfBounds(a.length, offsetA, b.length, offsetB, length)) {
return false;
}
if (mask == null) {
return stubRegionEqualsS1(a, offsetA, b, offsetB, length);
}
checkMaskLengthRegionEquals(length, mask.length);
return stubRegionEqualsWithOrMaskS1(a, offsetA, b, offsetB, mask, mask.length);
}
/**
* Returns {@code true} iff for all indices {@code i} from {@code 0} (inclusive) to
* {@code length} (exclusive), {@code (a[offsetA + i] | mask[i]) == b[offsetB + i]} holds.
* Performs best if {@code length} and {@code mask} are {@link CompilationFinal} with
* {@code dimensions = 1}. If {@code mask} is {@code null}, it is treated as if it was filled
* with zeroes.
*
* @since 19.3
*/
public static boolean regionEqualsWithOrMask(char[] a, int offsetA, char[] b, int offsetB, int length, char[] mask) {
requireNonNull(a);
requireNonNull(b);
checkArgsRegionEquals(offsetA, offsetB, length);
if (regionEqualsOutOfBounds(a.length, offsetA, b.length, offsetB, length)) {
return false;
}
if (mask == null) {
return stubRegionEqualsS2(a, offsetA, b, offsetB, length);
}
checkMaskLengthRegionEquals(length, mask.length);
return stubRegionEqualsWithOrMaskS2(a, offsetA, b, offsetB, mask, mask.length);
}
/**
* Returns {@code true} iff for all indices {@code i} from {@code 0} (inclusive) to
* {@code length} (exclusive),
* {@code (a.charAt(offsetA + i) | mask.charAt(i)) == b.charAt(offsetB + i)} holds. Performs
* best if {@code length} and {@code mask} are {@link CompilationFinal} with
* {@code dimensions = 1}. If {@code mask} is {@code null}, it is treated as if it was filled
* with zeroes.
*
* @since 19.3
*/
public static boolean regionEqualsWithOrMask(String a, int offsetA, String b, int offsetB, int length, String mask) {
requireNonNull(a);
requireNonNull(b);
checkArgsRegionEquals(offsetA, offsetB, length);
if (regionEqualsOutOfBounds(a.length(), offsetA, b.length(), offsetB, length)) {
return false;
}
if (mask == null) {
byte[] arrayA = getJavaStringArray(a);
byte[] arrayB = getJavaStringArray(b);
boolean compactA = isCompactString(a);
if (compactA != isCompactString(b)) {
return stubRegionEqualsS2S1(
compactA ? arrayB : arrayA, compactA ? offsetB : offsetA,
compactA ? arrayA : arrayB, compactA ? offsetA : offsetB, length);
} else {
final int byteOffsetA;
final int byteOffsetB;
final int byteLength;
if (compactA) {
byteOffsetA = offsetA;
byteOffsetB = offsetB;
byteLength = length;
} else {
byteOffsetA = offsetA << 1;
byteOffsetB = offsetB << 1;
byteLength = length << 1;
}
return stubRegionEqualsS1(arrayA, byteOffsetA, arrayB, byteOffsetB, byteLength);
}
} else {
checkMaskLengthRegionEquals(length, mask.length());
byte[] arrayA = getJavaStringArray(a);
byte[] arrayB = getJavaStringArray(b);
byte[] arrayM = getJavaStringArray(mask);
boolean compact1 = isCompactString(a);
boolean compact2 = isCompactString(b);
boolean compactMask = isCompactString(mask);
if (compact2) {
if (compactMask) {
if (compact1) {
return stubRegionEqualsWithOrMaskCompactStrings(arrayA, offsetA, arrayB, offsetB, arrayM, mask.length(), true, true, true);
} else {
return stubRegionEqualsWithOrMaskCompactStrings(arrayA, offsetA, arrayB, offsetB, arrayM, mask.length(), false, true, true);
}
} else {
return false;
}
} else {
if (compactMask) {
if (compact1) {
return stubRegionEqualsWithOrMaskCompactStrings(arrayA, offsetA, arrayB, offsetB, arrayM, mask.length(), true, false, true);
} else {
return stubRegionEqualsWithOrMaskCompactStrings(arrayA, offsetA, arrayB, offsetB, arrayM, mask.length(), false, false, true);
}
} else {
if (compact1) {
return stubRegionEqualsWithOrMaskCompactStrings(arrayA, offsetA, arrayB, offsetB, arrayM, mask.length(), true, false, false);
} else {
return stubRegionEqualsWithOrMaskCompactStrings(arrayA, offsetA, arrayB, offsetB, arrayM, mask.length(), false, false, false);
}
}
}
}
}
private static boolean regionEqualsOutOfBounds(int lengthA, int offsetA, int lengthB, int offsetB, int length) {
return lengthA - offsetA < length || lengthB - offsetB < length;
}
private static void checkArgsRegionEquals(int offsetA, int offsetB, int length) {
if (offsetA < 0 || offsetB < 0 || length < 0) {
illegalArgumentException("length, offsetA and offsetB must be positive");
}
}
private static void checkMaskLengthRegionEquals(int length, int maskLength) {
if (length > maskLength) {
illegalArgumentException("mask length must be greater or equal to length");
}
}
private static void checkArgs(int length, int fromIndex, int maxIndex, int nValues) {
if (fromIndex < 0) {
illegalArgumentException("fromIndex must be positive");
}
if (maxIndex > length || maxIndex < fromIndex) {
illegalArgumentException("maxIndex out of range");
}
if (nValues == 0) {
illegalArgumentException("no search values provided");
}
}
private static void checkArgsIndexOf(int hayStackLength, int fromIndex, int length) {
if (fromIndex < 0 || length < 0) {
illegalArgumentException("fromIndex and length must be positive");
}
if (Integer.toUnsignedLong(fromIndex) + Integer.toUnsignedLong(length) > hayStackLength) {
illegalArgumentException("length out of range");
}
}
private static void checkMaskLengthIndexOf(int lengthB, int maskLength) {
if (lengthB != maskLength) {
illegalArgumentException("mask and needle length must be equal");
}
}
private static void requireNonNull(Object obj) {
if (obj == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new NullPointerException();
}
}
private static void illegalArgumentException(String msg) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new IllegalArgumentException(msg);
}
private static int indexOfBS1(byte[] array, int fromIndex, int maxIndex, int values, int nValues) {
if (nValues == 1) {
return stubIndexOfB1S1(array, fromIndex, maxIndex, values & 0xff);
} else if (nValues == 2) {
return stubIndexOfB2S1(array, fromIndex, maxIndex, values & 0xff, (values >>> 8) & 0xff);
} else if (nValues == 3) {
return stubIndexOfB3S1(array, fromIndex, maxIndex, values & 0xff, (values >>> 8) & 0xff, (values >>> 16) & 0xff);
} else {
return stubIndexOfB4S1(array, fromIndex, maxIndex, values & 0xff, (values >>> 8) & 0xff, (values >>> 16) & 0xff, (values >>> 24) & 0xff);
}
}
private static int indexOfBS1(byte[] array, int fromIndex, int maxIndex, byte[] bytes, int nValues) {
if (nValues == 1) {
return stubIndexOfB1S1(array, fromIndex, maxIndex, Byte.toUnsignedInt(bytes[0]));
} else if (nValues == 2) {
return stubIndexOfB2S1(array, fromIndex, maxIndex, Byte.toUnsignedInt(bytes[0]), Byte.toUnsignedInt(bytes[1]));
} else if (nValues == 3) {
return stubIndexOfB3S1(array, fromIndex, maxIndex, Byte.toUnsignedInt(bytes[0]), Byte.toUnsignedInt(bytes[1]), Byte.toUnsignedInt(bytes[2]));
} else {
return stubIndexOfB4S1(array, fromIndex, maxIndex, Byte.toUnsignedInt(bytes[0]), Byte.toUnsignedInt(bytes[1]), Byte.toUnsignedInt(bytes[2]), Byte.toUnsignedInt(bytes[3]));
}
}
private static int indexOfBS2(byte[] array, int fromIndex, int maxIndex, char[] chars, int nValues) {
if (nValues == 1) {
return stubIndexOfB1S2(array, fromIndex, maxIndex, chars[0]);
} else if (nValues == 2) {
return stubIndexOfB2S2(array, fromIndex, maxIndex, chars[0], chars[1]);
} else if (nValues == 3) {
return stubIndexOfB3S2(array, fromIndex, maxIndex, chars[0], chars[1], chars[2]);
} else {
return stubIndexOfB4S2(array, fromIndex, maxIndex, chars[0], chars[1], chars[2], chars[3]);
}
}
private static int indexOfCS2(char[] array, int fromIndex, int maxIndex, char[] chars, int nValues) {
if (nValues == 1) {
return stubIndexOfC1S2(array, fromIndex, maxIndex, chars[0]);
} else if (nValues == 2) {
return stubIndexOfC2S2(array, fromIndex, maxIndex, chars[0], chars[1]);
} else if (nValues == 3) {
return stubIndexOfC3S2(array, fromIndex, maxIndex, chars[0], chars[1], chars[2]);
} else {
return stubIndexOfC4S2(array, fromIndex, maxIndex, chars[0], chars[1], chars[2], chars[3]);
}
}
private static int stubIndexOfB1S1(byte[] array, long fromIndex, int maxIndex, int v1) {
return runIndexOfS1(array, fromIndex, maxIndex, v1);
}
private static int stubIndexOfB2S1(byte[] array, long fromIndex, int maxIndex, int v1, int v2) {
return runIndexOfS1(array, fromIndex, maxIndex, v1, v2);
}
private static int stubIndexOfB3S1(byte[] array, long fromIndex, int maxIndex, int v1, int v2, int v3) {
return runIndexOfS1(array, fromIndex, maxIndex, v1, v2, v3);
}
private static int stubIndexOfB4S1(byte[] array, long fromIndex, int maxIndex, int v1, int v2, int v3, int v4) {
return runIndexOfS1(array, fromIndex, maxIndex, v1, v2, v3, v4);
}
private static int stubIndexOfB1S2(byte[] array, long fromIndex, int maxIndex, int v1) {
return runIndexOfS2(array, fromIndex, maxIndex, v1);
}
private static int stubIndexOfB2S2(byte[] array, long fromIndex, int maxIndex, int v1, int v2) {
return runIndexOfS2(array, fromIndex, maxIndex, v1, v2);
}
private static int stubIndexOfB3S2(byte[] array, long fromIndex, int maxIndex, int v1, int v2, int v3) {
return runIndexOfS2(array, fromIndex, maxIndex, v1, v2, v3);
}
private static int stubIndexOfB4S2(byte[] array, long fromIndex, int maxIndex, int v1, int v2, int v3, int v4) {
return runIndexOfS2(array, fromIndex, maxIndex, v1, v2, v3, v4);
}
private static int stubIndexOfC1S2(char[] array, long fromIndex, int maxIndex, int v1) {
return runIndexOfS2(array, fromIndex, maxIndex, v1);
}
private static int stubIndexOfC2S2(char[] array, long fromIndex, int maxIndex, int v1, int v2) {
return runIndexOfS2(array, fromIndex, maxIndex, v1, v2);
}
private static int stubIndexOfC3S2(char[] array, long fromIndex, int maxIndex, int v1, int v2, int v3) {
return runIndexOfS2(array, fromIndex, maxIndex, v1, v2, v3);
}
private static int stubIndexOfC4S2(char[] array, long fromIndex, int maxIndex, int v1, int v2, int v3, int v4) {
return runIndexOfS2(array, fromIndex, maxIndex, v1, v2, v3, v4);
}
private static int stubIndexOfWithOrMaskS1(byte[] haystack, long fromIndex, int maxIndex, int needle, int mask) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
if ((Byte.toUnsignedInt(haystack[i]) | mask) == needle) {
return i;
}
}
return -1;
}
private static int stubIndexOfWithOrMaskS2(byte[] haystack, long fromIndex, int maxIndex, int needle, int mask) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
if ((readChar(haystack, i) | mask) == needle) {
return i;
}
}
return -1;
}
private static int stubIndexOfWithOrMaskS2(char[] haystack, long fromIndex, int maxIndex, int needle, int mask) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
if ((haystack[i] | mask) == needle) {
return i;
}
}
return -1;
}
private static int stubIndexOf2ConsecutiveS1(byte[] haystack, long fromIndex, int maxIndex, int c1, int c2) {
for (int i = (int) (fromIndex + 1); i < maxIndex; i++) {
if (Byte.toUnsignedInt(haystack[i - 1]) == c1 && Byte.toUnsignedInt(haystack[i]) == c2) {
return i - 1;
}
}
return -1;
}
private static int stubIndexOf2ConsecutiveS2(byte[] haystack, long fromIndex, int maxIndex, int c1, int c2) {
for (int i = (int) (fromIndex + 1); i < maxIndex; i++) {
if (readChar(haystack, i - 1) == c1 && readChar(haystack, i) == c2) {
return i - 1;
}
}
return -1;
}
private static int stubIndexOf2ConsecutiveS2(char[] haystack, long fromIndex, int maxIndex, int c1, int c2) {
for (int i = (int) (fromIndex + 1); i < maxIndex; i++) {
if (haystack[i - 1] == c1 && haystack[i] == c2) {
return i - 1;
}
}
return -1;
}
private static int stubIndexOf2ConsecutiveWithOrMaskS1(byte[] haystack, long fromIndex, int maxIndex, int c1, int c2, int mask1, int mask2) {
for (int i = (int) (fromIndex + 1); i < maxIndex; i++) {
if ((Byte.toUnsignedInt(haystack[i - 1]) | mask1) == c1 && (Byte.toUnsignedInt(haystack[i]) | mask2) == c2) {
return i - 1;
}
}
return -1;
}
private static int stubIndexOf2ConsecutiveWithOrMaskS2(byte[] haystack, long fromIndex, int maxIndex, int c1, int c2, int mask1, int mask2) {
for (int i = (int) (fromIndex + 1); i < maxIndex; i++) {
if ((readChar(haystack, i - 1) | mask1) == c1 && (readChar(haystack, i) | mask2) == c2) {
return i - 1;
}
}
return -1;
}
private static int stubIndexOf2ConsecutiveWithOrMaskS2(char[] haystack, long fromIndex, int maxIndex, int c1, int c2, int mask1, int mask2) {
for (int i = (int) (fromIndex + 1); i < maxIndex; i++) {
if ((haystack[i - 1] | mask1) == c1 && (haystack[i] | mask2) == c2) {
return i - 1;
}
}
return -1;
}
private static boolean stubRegionEqualsS1(byte[] a, long offsetA, byte[] b, long offsetB, int length) {
for (int i = 0; i < length; i++) {
if (a[(int) offsetA + i] != b[(int) offsetB + i]) {
return false;
}
}
return true;
}
private static boolean stubRegionEqualsS2S1(byte[] a, long offsetA, byte[] b, long offsetB, int length) {
for (int i = 0; i < length; i++) {
if (readChar(a, (int) offsetA + i) != Byte.toUnsignedInt(b[(int) offsetB + i])) {
return false;
}
}
return true;
}
private static boolean stubRegionEqualsS2(char[] a, long offsetA, char[] b, long offsetB, int length) {
for (int i = 0; i < length; i++) {
if (a[(int) offsetA + i] != b[(int) offsetB + i]) {
return false;
}
}
return true;
}
private static boolean stubRegionEqualsWithOrMaskS1(byte[] a, long offsetA, byte[] b, long offsetB, byte[] mask, int length) {
for (int i = 0; i < length; i++) {
if ((a[(int) offsetA + i] | mask[i]) != b[(int) offsetB + i]) {
return false;
}
}
return true;
}
private static boolean stubRegionEqualsWithOrMaskS2(char[] a, long offsetA, char[] b, long offsetB, char[] mask, int length) {
for (int i = 0; i < length; i++) {
if ((a[(int) offsetA + i] | mask[i]) != b[(int) offsetB + i]) {
return false;
}
}
return true;
}
private static boolean stubRegionEqualsWithOrMaskCompactStrings(byte[] a, long offsetA, byte[] b, long offsetB, byte[] mask, int length, boolean compactA, boolean compactB, boolean compactM) {
for (int i = 0; i < length; i++) {
int vA = compactA ? Byte.toUnsignedInt(a[(int) offsetA + i]) : readChar(a, (int) offsetA + i);
int vB = compactB ? Byte.toUnsignedInt(b[(int) offsetB + i]) : readChar(b, (int) offsetB + i);
int vM = compactM ? Byte.toUnsignedInt(mask[i]) : readChar(mask, i);
if ((vA | vM) != vB) {
return false;
}
}
return true;
}
private static int readChar(byte[] array, int i) {
int byte0 = Byte.toUnsignedInt(array[i << 1]);
int byte1 = Byte.toUnsignedInt(array[(i << 1) + 1]);
return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? byte0 | (byte1 << 8) : (byte0 << 8) | byte1;
}
private static int runIndexOfS1(byte[] array, long fromIndex, int maxIndex, int... values) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
for (int v : values) {
if (Byte.toUnsignedInt(array[i]) == v) {
return i;
}
}
}
return -1;
}
private static int runIndexOfS1(byte[] array, long fromIndex, int maxIndex, byte... values) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
for (int v : values) {
if (array[i] == v) {
return i;
}
}
}
return -1;
}
private static int runIndexOfS2(byte[] array, long fromIndex, int maxIndex, int... values) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
int c = readChar(array, i);
for (int v : values) {
if (c == v) {
return i;
}
}
}
return -1;
}
private static int runIndexOfS2(char[] array, long fromIndex, int maxIndex, int... values) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
for (int v : values) {
if (array[i] == v) {
return i;
}
}
}
return -1;
}
private static int runIndexOfS2(char[] array, long fromIndex, int maxIndex, char... values) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
for (int v : values) {
if (array[i] == v) {
return i;
}
}
}
return -1;
}
private static int runIndexOfS2(String haystack, long fromIndex, int maxIndex, char[] needle) {
for (int i = (int) fromIndex; i < maxIndex; i++) {
for (char c : needle) {
if (haystack.charAt(i) == c) {
return i;
}
}
}
return -1;
}
}