Comb UTF-8 literal processing

PiperOrigin-RevId: 770672448
This commit is contained in:
Evgenii Kliuchnikov
2025-06-12 08:47:30 -07:00
committed by Copybara-Service
parent 405b434d85
commit 3efb30f96b
7 changed files with 66 additions and 21 deletions

View File

@@ -39,6 +39,7 @@ final class DictionaryData {
String skipFlip, int[] sizeBits, String sizeBitsData) {
// Initialize lower 7 bits of every byte in the dictionary.
final byte[] dict = Utils.toUsAsciiBytes(data0 + data1);
final int[] skipFlipRunes = Utils.toUtf8Runes(skipFlip);
if (DICTIONARY_DATA_DEBUG != 0) {
if (dict.length != dictionary.capacity()) {
throw new RuntimeException("Corrupted brotli dictionary");
@@ -47,10 +48,10 @@ final class DictionaryData {
// Toggle high bit using run-length delta encoded "skipFlip".
int offset = 0;
final int n = skipFlip.length() >> 1;
final int n = skipFlipRunes.length >> 1;
for (int i = 0; i < n; ++i) {
final int skip = (int) skipFlip.charAt(2 * i) - 36;
final int flip = (int) skipFlip.charAt(2 * i + 1) - 36;
final int skip = skipFlipRunes[2 * i] - 36;
final int flip = skipFlipRunes[2 * i + 1] - 36;
for (int j = 0; j < skip; ++j) {
dict[offset] = (byte) ((int) dict[offset] ^ 3);
offset++;

View File

@@ -76,11 +76,12 @@ final class Transform {
private static void unpackTransforms(byte[] prefixSuffix,
int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc) {
final int n = prefixSuffixSrc.length();
final int[] prefixSuffixBytes = Utils.toUtf8Runes(prefixSuffixSrc);
final int n = prefixSuffixBytes.length;
int index = 1;
int j = 0;
for (int i = 0; i < n; ++i) {
final int c = (int) prefixSuffixSrc.charAt(i);
final int c = prefixSuffixBytes[i];
if (c == 35) { // == #
prefixSuffixHeads[index++] = j;
} else {

View File

@@ -99,6 +99,14 @@ final class Utils {
}
}
static int[] toUtf8Runes(String src) {
int[] result = new int[src.length()];
for (int i = 0; i < src.length(); i++) {
result[i] = (int) src.charAt(i);
}
return result;
}
static ByteBuffer asReadOnlyBuffer(ByteBuffer src) {
return src.asReadOnlyBuffer();
}

View File

@@ -1312,11 +1312,12 @@ internal class Transforms {
}
private fun unpackTransforms(prefixSuffix: ByteArray, prefixSuffixHeads: IntArray, transforms: IntArray, prefixSuffixSrc: String, transformsSrc: String): Unit {
val n: Int = prefixSuffixSrc.length;
val prefixSuffixBytes: IntArray = toUtf8Runes(prefixSuffixSrc);
val n: Int = prefixSuffixBytes.size;
var index: Int = 1;
var j: Int = 0;
for (i: Int in 0 until n) {
val c: Int = prefixSuffixSrc[i].code.toInt();
val c: Int = prefixSuffixBytes[i];
if (c == 35) {
prefixSuffixHeads[index++] = j;
} else {
@@ -1945,11 +1946,12 @@ fun setData(newData: ByteBuffer, newSizeBits: IntArray): Unit {
private fun unpackDictionaryData(dictionary: ByteBuffer, data0: String, data1: String, skipFlip: String, sizeBits: IntArray, sizeBitsData: String): Unit {
val dict: ByteArray = toUsAsciiBytes(data0 + data1);
val skipFlipRunes: IntArray = toUtf8Runes(skipFlip);
var offset: Int = 0;
val n: Int = skipFlip.length shr 1;
val n: Int = skipFlipRunes.size shr 1;
for (i: Int in 0 until n) {
val skip: Int = skipFlip[2 * i].code.toInt() - 36;
val flip: Int = skipFlip[2 * i + 1].code.toInt() - 36;
val skip: Int = skipFlipRunes[2 * i] - 36;
val flip: Int = skipFlipRunes[2 * i + 1] - 36;
for (j: Int in 0 until skip) {
dict[offset] = (dict[offset].toInt() xor 3).toByte();
offset++;
@@ -2015,6 +2017,15 @@ internal fun toUsAsciiBytes(src: String): ByteArray {
return src.toByteArray(Charsets.US_ASCII);
}
internal fun toUtf8Runes(src: String): IntArray {
var len: Int = src.length;
var result: IntArray = IntArray(size = len);
for (i: Int in 0 until len) {
result[i] = src[i].code.toInt();
}
return result;
}
internal fun flipBuffer(buffer: Buffer): Unit {
buffer.flip();
}