/* * Decompiled with CFR 0.152. * * Could not load the following classes: * org.jspecify.annotations.Nullable */ package net.minecraft.util.parsing.packrat; import net.minecraft.util.Util; import net.minecraft.util.parsing.packrat.Atom; import net.minecraft.util.parsing.packrat.Control; import net.minecraft.util.parsing.packrat.ErrorCollector; import net.minecraft.util.parsing.packrat.NamedRule; import net.minecraft.util.parsing.packrat.ParseState; import net.minecraft.util.parsing.packrat.Scope; import org.jspecify.annotations.Nullable; public abstract class CachedParseState implements ParseState { private @Nullable PositionCache[] positionCache = new PositionCache[256]; private final ErrorCollector errorCollector; private final Scope scope = new Scope(); private @Nullable SimpleControl[] controlCache = new SimpleControl[16]; private int nextControlToReturn; private final Silent silent = new Silent(); protected CachedParseState(ErrorCollector errorCollector) { this.errorCollector = errorCollector; } @Override public Scope scope() { return this.scope; } @Override public ErrorCollector errorCollector() { return this.errorCollector; } @Override public @Nullable T parse(NamedRule rule) { CacheEntry entry; T result; int markBeforeParse = this.mark(); PositionCache positionCache = this.getCacheForPosition(markBeforeParse); int entryIndex = positionCache.findKeyIndex(rule.name()); if (entryIndex != -1) { CacheEntry value = positionCache.getValue(entryIndex); if (value != null) { if (value == CacheEntry.NEGATIVE) { return null; } this.restore(value.markAfterParse); return value.value; } } else { entryIndex = positionCache.allocateNewEntry(rule.name()); } if ((result = rule.value().parse(this)) == null) { entry = CacheEntry.negativeEntry(); } else { int markAfterParse = this.mark(); entry = new CacheEntry(result, markAfterParse); } positionCache.setValue(entryIndex, entry); return result; } private PositionCache getCacheForPosition(int index) { PositionCache result; int currentSize = this.positionCache.length; if (index >= currentSize) { int newSize = Util.growByHalf(currentSize, index + 1); PositionCache[] newCache = new PositionCache[newSize]; System.arraycopy(this.positionCache, 0, newCache, 0, currentSize); this.positionCache = newCache; } if ((result = this.positionCache[index]) == null) { this.positionCache[index] = result = new PositionCache(); } return result; } @Override public Control acquireControl() { int controlIndex; SimpleControl entry; int currentSize = this.controlCache.length; if (this.nextControlToReturn >= currentSize) { int newSize = Util.growByHalf(currentSize, this.nextControlToReturn + 1); SimpleControl[] newControlCache = new SimpleControl[newSize]; System.arraycopy(this.controlCache, 0, newControlCache, 0, currentSize); this.controlCache = newControlCache; } if ((entry = this.controlCache[controlIndex = this.nextControlToReturn++]) == null) { this.controlCache[controlIndex] = entry = new SimpleControl(); } else { entry.reset(); } return entry; } @Override public void releaseControl() { --this.nextControlToReturn; } @Override public ParseState silent() { return this.silent; } private static class PositionCache { public static final int ENTRY_STRIDE = 2; private static final int NOT_FOUND = -1; private Object[] atomCache = new Object[16]; private int nextKey; private PositionCache() { } public int findKeyIndex(Atom key) { for (int i = 0; i < this.nextKey; i += 2) { if (this.atomCache[i] != key) continue; return i; } return -1; } public int allocateNewEntry(Atom key) { int newKeyIndex = this.nextKey; this.nextKey += 2; int newValueIndex = newKeyIndex + 1; int currentSize = this.atomCache.length; if (newValueIndex >= currentSize) { int newSize = Util.growByHalf(currentSize, newValueIndex + 1); Object[] newCache = new Object[newSize]; System.arraycopy(this.atomCache, 0, newCache, 0, currentSize); this.atomCache = newCache; } this.atomCache[newKeyIndex] = key; return newKeyIndex; } public @Nullable CacheEntry getValue(int keyIndex) { return (CacheEntry)this.atomCache[keyIndex + 1]; } public void setValue(int keyIndex, CacheEntry entry) { this.atomCache[keyIndex + 1] = entry; } } private static class SimpleControl implements Control { private boolean hasCut; private SimpleControl() { } @Override public void cut() { this.hasCut = true; } @Override public boolean hasCut() { return this.hasCut; } public void reset() { this.hasCut = false; } } private class Silent implements ParseState { private final ErrorCollector silentCollector = new ErrorCollector.Nop(); private Silent() { } @Override public ErrorCollector errorCollector() { return this.silentCollector; } @Override public Scope scope() { return CachedParseState.this.scope(); } @Override public @Nullable T parse(NamedRule rule) { return CachedParseState.this.parse(rule); } @Override public S input() { return CachedParseState.this.input(); } @Override public int mark() { return CachedParseState.this.mark(); } @Override public void restore(int mark) { CachedParseState.this.restore(mark); } @Override public Control acquireControl() { return CachedParseState.this.acquireControl(); } @Override public void releaseControl() { CachedParseState.this.releaseControl(); } @Override public ParseState silent() { return this; } } private record CacheEntry(@Nullable T value, int markAfterParse) { public static final CacheEntry NEGATIVE = new CacheEntry(null, -1); public static CacheEntry negativeEntry() { return NEGATIVE; } } }