namespace XFESystem.Desktop; /// UI-owned diagnostic state. Unchanged readbacks allocate nothing; /// the cache never retains a window or its complete large source. public sealed class EditorReadbackTracker { public const int MaximumPrefixCharacters = 8192; private bool hasState; private int windowId, sourceLength; private string path = "", prefix = ""; public bool TryUpdate(int id, string location, string content, out string sourcePrefix) { ArgumentNullException.ThrowIfNull(location); ArgumentNullException.ThrowIfNull(content); int prefixLength = Math.Min(content.Length, MaximumPrefixCharacters); if (hasState && id == windowId && location == path && content.Length == sourceLength && content.AsSpan(0, prefixLength).SequenceEqual(prefix.AsSpan())) { sourcePrefix = prefix; return false; } // Copy only after the comparison, independently of the original string. // Even a closed large editor therefore leaves at most this bounded prefix. prefix = content.AsSpan(0, prefixLength).ToString(); path = location; windowId = id; sourceLength = content.Length; hasState = true; sourcePrefix = prefix; return true; } public void Reset() { hasState = false; windowId = sourceLength = 0; path = prefix = ""; } }