/// <inheritdoc/> public byte[] Decompress(byte[] data, long start = 0, long count = -1, object decompressorSettings = null) { if (count == 0) { return(Array.Empty <byte>()); } #region Проверка аргументов #if CHECK_ARGS if (data is null) { throw new ArgumentNullException(nameof(data)); } if ((start < 0) || (start >= data.LongLength)) { throw new ArgumentOutOfRangeException(nameof(start)); } if ((start + count) > data.LongLength) { throw new ArgumentOutOfRangeException(nameof(count)); } #endif #endregion Проверка аргументов #region Инициализация var last = (count < 0) ? (data.LongLength) : (start + count); var pos = start; var settings = new SavegameCompressonSettings(data[start], data[start + 1]); int size = data.LoadUInt16(start + 2, isLittleEndian: true); var res = new MemoryStream(); #endregion Инициализация #region аспаковка for (var i = start; i < last; i++) { if (data[i] == settings.ControlCode) { if ((i + 2) >= last) { throw new IncompleteDataException(); } var cnt = data[++i]; var val = data[++i]; for (var j = 0; j < cnt; j++) { res.WriteByte(val); } } else { res.WriteByte(data[i]); } } #endregion аспаковка return(res.ToArray()); }
/// <summary> /// <para>Записать упаковочную последовательность байт в поток</para> /// </summary> /// <param name="outStream">Целевой поток</param> /// <param name="val">Значение</param> /// <param name="count">Количество повторов</param> /// <param name="settings">Параметры упаковки</param> private static void WriteRLE(Stream outStream, byte val, int count, SavegameCompressonSettings settings) { if (count > 0) { if (val == settings.ControlCode) { WritePackedSequence(outStream, val, count, settings); } else if (count <= settings.MaxUnRLEValueCount) { for (var i = 0; i < count; i++) { outStream.WriteByte(val); } } else { WritePackedSequence(outStream, val, count, settings); } } }
/// <summary> /// <para>Записать кодовую последовательность в поток</para> /// </summary> /// <param name="outStream">Целевой поток</param> /// <param name="val">Значение</param> /// <param name="count">Количество повторов</param> /// <param name="settings">Параметры упаковки</param> private static void WritePackedSequence(Stream outStream, byte val, int count, SavegameCompressonSettings settings) { if (count > 0) { while (count > byte.MaxValue) { outStream.WriteByte(settings.ControlCode); outStream.WriteByte(byte.MaxValue); outStream.WriteByte(val); count -= byte.MaxValue; } outStream.WriteByte(settings.ControlCode); outStream.WriteByte((byte)count); outStream.WriteByte(val); } }