package net.minecraft.util.parsing.packrat; import javax.annotation.Nullable; import net.minecraft.Util; public abstract class CachedParseState implements ParseState { private CachedParseState.PositionCache[] positionCache = new CachedParseState.PositionCache[256]; private final ErrorCollector errorCollector; private final Scope scope = new Scope(); private CachedParseState.SimpleControl[] controlCache = new CachedParseState.SimpleControl[16]; private int nextControlToReturn; private final CachedParseState.Silent silent = new CachedParseState.Silent(); protected CachedParseState(ErrorCollector p_395135_) { this.errorCollector = p_395135_; } @Override public Scope scope() { return this.scope; } @Override public ErrorCollector errorCollector() { return this.errorCollector; } @Nullable @Override public T parse(NamedRule p_392393_) { int i = this.mark(); CachedParseState.PositionCache cachedparsestate$positioncache = this.getCacheForPosition(i); int j = cachedparsestate$positioncache.findKeyIndex(p_392393_.name()); if (j != -1) { CachedParseState.CacheEntry cacheentry = cachedparsestate$positioncache.getValue(j); if (cacheentry != null) { if (cacheentry == CachedParseState.CacheEntry.NEGATIVE) { return null; } this.restore(cacheentry.markAfterParse); return cacheentry.value; } } else { j = cachedparsestate$positioncache.allocateNewEntry(p_392393_.name()); } T t = p_392393_.value().parse(this); CachedParseState.CacheEntry cacheentry1; if (t == null) { cacheentry1 = CachedParseState.CacheEntry.negativeEntry(); } else { int k = this.mark(); cacheentry1 = new CachedParseState.CacheEntry<>(t, k); } cachedparsestate$positioncache.setValue(j, cacheentry1); return t; } private CachedParseState.PositionCache getCacheForPosition(int p_392170_) { int i = this.positionCache.length; if (p_392170_ >= i) { int j = Util.growByHalf(i, p_392170_ + 1); CachedParseState.PositionCache[] acachedparsestate$positioncache = new CachedParseState.PositionCache[j]; System.arraycopy(this.positionCache, 0, acachedparsestate$positioncache, 0, i); this.positionCache = acachedparsestate$positioncache; } CachedParseState.PositionCache cachedparsestate$positioncache = this.positionCache[p_392170_]; if (cachedparsestate$positioncache == null) { cachedparsestate$positioncache = new CachedParseState.PositionCache(); this.positionCache[p_392170_] = cachedparsestate$positioncache; } return cachedparsestate$positioncache; } @Override public Control acquireControl() { int i = this.controlCache.length; if (this.nextControlToReturn >= i) { int j = Util.growByHalf(i, this.nextControlToReturn + 1); CachedParseState.SimpleControl[] acachedparsestate$simplecontrol = new CachedParseState.SimpleControl[j]; System.arraycopy(this.controlCache, 0, acachedparsestate$simplecontrol, 0, i); this.controlCache = acachedparsestate$simplecontrol; } int k = this.nextControlToReturn++; CachedParseState.SimpleControl cachedparsestate$simplecontrol = this.controlCache[k]; if (cachedparsestate$simplecontrol == null) { cachedparsestate$simplecontrol = new CachedParseState.SimpleControl(); this.controlCache[k] = cachedparsestate$simplecontrol; } else { cachedparsestate$simplecontrol.reset(); } return cachedparsestate$simplecontrol; } @Override public void releaseControl() { this.nextControlToReturn--; } @Override public ParseState silent() { return this.silent; } record CacheEntry(@Nullable T value, int markAfterParse) { public static final CachedParseState.CacheEntry NEGATIVE = new CachedParseState.CacheEntry(null, -1); public static CachedParseState.CacheEntry negativeEntry() { return (CachedParseState.CacheEntry)NEGATIVE; } } 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; public int findKeyIndex(Atom p_396726_) { for (int i = 0; i < this.nextKey; i += 2) { if (this.atomCache[i] == p_396726_) { return i; } } return -1; } public int allocateNewEntry(Atom p_393666_) { int i = this.nextKey; this.nextKey += 2; int j = i + 1; int k = this.atomCache.length; if (j >= k) { int l = Util.growByHalf(k, j + 1); Object[] aobject = new Object[l]; System.arraycopy(this.atomCache, 0, aobject, 0, k); this.atomCache = aobject; } this.atomCache[i] = p_393666_; return i; } @Nullable public CachedParseState.CacheEntry getValue(int p_392011_) { return (CachedParseState.CacheEntry)this.atomCache[p_392011_ + 1]; } public void setValue(int p_394123_, CachedParseState.CacheEntry p_393425_) { this.atomCache[p_394123_ + 1] = p_393425_; } } class Silent implements ParseState { private final ErrorCollector silentCollector = new ErrorCollector.Nop<>(); @Override public ErrorCollector errorCollector() { return this.silentCollector; } @Override public Scope scope() { return CachedParseState.this.scope(); } @Nullable @Override public T parse(NamedRule p_397853_) { return CachedParseState.this.parse(p_397853_); } @Override public S input() { return CachedParseState.this.input(); } @Override public int mark() { return CachedParseState.this.mark(); } @Override public void restore(int p_397781_) { CachedParseState.this.restore(p_397781_); } @Override public Control acquireControl() { return CachedParseState.this.acquireControl(); } @Override public void releaseControl() { CachedParseState.this.releaseControl(); } @Override public ParseState silent() { return this; } } static class SimpleControl implements Control { private boolean hasCut; @Override public void cut() { this.hasCut = true; } @Override public boolean hasCut() { return this.hasCut; } public void reset() { this.hasCut = false; } } }