minecraft-src/net/minecraft/client/gui/font/CodepointMap.java
2025-07-04 02:49:36 +03:00

116 lines
2.9 KiB
Java

package net.minecraft.client.gui.font;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.Arrays;
import java.util.function.IntFunction;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class CodepointMap<T> {
private static final int BLOCK_BITS = 8;
private static final int BLOCK_SIZE = 256;
private static final int IN_BLOCK_MASK = 255;
private static final int MAX_BLOCK = 4351;
private static final int BLOCK_COUNT = 4352;
private final T[] empty;
private final T[][] blockMap;
private final IntFunction<T[]> blockConstructor;
public CodepointMap(IntFunction<T[]> blockConstructor, IntFunction<T[][]> blockMapConstructor) {
this.empty = (T[])((Object[])blockConstructor.apply(256));
this.blockMap = (T[][])((Object[][])blockMapConstructor.apply(4352));
Arrays.fill(this.blockMap, this.empty);
this.blockConstructor = blockConstructor;
}
public void clear() {
Arrays.fill(this.blockMap, this.empty);
}
@Nullable
public T get(int index) {
int i = index >> 8;
int j = index & 0xFF;
return this.blockMap[i][j];
}
@Nullable
public T put(int index, T value) {
int i = index >> 8;
int j = index & 0xFF;
T[] objects = this.blockMap[i];
if (objects == this.empty) {
objects = (T[])((Object[])this.blockConstructor.apply(256));
this.blockMap[i] = objects;
objects[j] = value;
return null;
} else {
T object = objects[j];
objects[j] = value;
return object;
}
}
public T computeIfAbsent(int index, IntFunction<T> valueIfAbsentGetter) {
int i = index >> 8;
int j = index & 0xFF;
T[] objects = this.blockMap[i];
T object = objects[j];
if (object != null) {
return object;
} else {
if (objects == this.empty) {
objects = (T[])((Object[])this.blockConstructor.apply(256));
this.blockMap[i] = objects;
}
T object2 = (T)valueIfAbsentGetter.apply(index);
objects[j] = object2;
return object2;
}
}
@Nullable
public T remove(int index) {
int i = index >> 8;
int j = index & 0xFF;
T[] objects = this.blockMap[i];
if (objects == this.empty) {
return null;
} else {
T object = objects[j];
objects[j] = null;
return object;
}
}
public void forEach(CodepointMap.Output<T> output) {
for (int i = 0; i < this.blockMap.length; i++) {
T[] objects = this.blockMap[i];
if (objects != this.empty) {
for (int j = 0; j < objects.length; j++) {
T object = objects[j];
if (object != null) {
int k = i << 8 | j;
output.accept(k, object);
}
}
}
}
}
public IntSet keySet() {
IntOpenHashSet intOpenHashSet = new IntOpenHashSet();
this.forEach((i, object) -> intOpenHashSet.add(i));
return intOpenHashSet;
}
@FunctionalInterface
@Environment(EnvType.CLIENT)
public interface Output<T> {
void accept(int i, T object);
}
}