116 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			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);
 | |
| 	}
 | |
| }
 |