using System.Collections.Generic; namespace PKHeX.Core { /// /// block accessor, where blocks are ordered by ascending . /// public abstract class SCBlockAccessor : ISaveBlockAccessor { public abstract IReadOnlyList BlockInfo { get; } public object GetBlockValue(uint key) => GetBlock(key).GetValue(); public void SetBlockValue(uint key, object value) => GetBlock(key).SetValue(value); // Rather than storing a dictionary of keys, we can abuse the fact that the SCBlock[] is stored in order of ascending block key. // Binary Search doesn't require extra memory like a Dictionary would; also, we only need to find a few blocks. public SCBlock GetBlock(uint key) => BinarySearch(BlockInfo, key); /// /// Tries to grab the actual block, and returns a new dummy if the block does not exist. /// /// Block Key /// Block if exists, dummy if not. Dummy key will not match requested key. public SCBlock GetBlockSafe(uint key) { try { return GetBlock(key); } #pragma warning disable CA1031 // Do not catch general exception types catch (KeyNotFoundException) { return new SCBlock(0, SCTypeCode.None); } #pragma warning restore CA1031 // Do not catch general exception types } private static SCBlock BinarySearch(IReadOnlyList arr, uint key) { int min = 0; int max = arr.Count - 1; do { int mid = (min + max) / 2; var entry = arr[mid]; var ek = entry.Key; if (key == ek) return entry; if (key < ek) max = mid - 1; else min = mid + 1; } while (min <= max); throw new KeyNotFoundException(nameof(key)); } } }