private static Stream GetStream(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } var position = stream.Position; var parse = RNCHeader.TryParse(stream, out var header); stream.Position = position; // restore position in case of not-RNC if (!parse) { return(stream); } var input = new byte[stream.Length]; var output = new byte[header.UncompressedSize]; var read = stream.Read(input, 0, input.Length); if (read != input.Length) { throw new EndOfStreamException("Couldn't read entire stream."); } var p1 = Marshal.AllocHGlobal(input.Length); var p2 = Marshal.AllocHGlobal(output.Length); Marshal.Copy(input, 0, p1, input.Length); Marshal.Copy(output, 0, p2, output.Length); var status = Unpack(p1, p2); if (status == RNCStatus.Ok) { Marshal.Copy(p2, output, 0, output.Length); } Marshal.FreeHGlobal(p1); Marshal.FreeHGlobal(p2); if (status != RNCStatus.Ok) { throw new InvalidOperationException($"Error while unpacking: '{status}'."); } return(new MemoryStream(output)); }
/// <summary> /// Tries to parse an instance from a stream. /// </summary> /// <param name="stream"></param> /// <param name="result"></param> /// <returns> /// <c>true</c> if a header was found and compression scheme is supported. /// </returns> public static bool TryParse(Stream stream, out RNCHeader result) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } result = default(RNCHeader); var reader = new BinaryReader(stream); var signature = Encoding.ASCII.GetString(reader.ReadBytes(3)); if (signature != "RNC") { return(false); } var compression = (RNCCompression)reader.ReadByte(); if (compression != RNCCompression.Method1) { return(false); } var uncompressedSize = ReadUInt32BE(reader); var compressedSize = ReadUInt32BE(reader); var uncompressedSum = ReadUInt16BE(reader); var compressedSum = ReadUInt16BE(reader); var leeway = reader.ReadByte(); var packChunks = reader.ReadByte(); result = new RNCHeader( signature, compression, uncompressedSize, compressedSize, uncompressedSum, compressedSum, leeway, packChunks ); return(true); }