C#: Fixed the writing of the header of the RLE compressed files; it should state the decompressed size, and not the compressed size. Also added an exception that indicates there is still some input data to read after the compressed stream.

The current RLE implementation passed the first test: compression->decompression resulted in the same file for a manually created test file. (and the compressed file also has the expected format)
This commit is contained in:
barubary 2011-04-05 16:44:41 +00:00
parent 2c6ef5570a
commit 3a6221a0c6
4 changed files with 62 additions and 6 deletions

View File

@ -45,6 +45,7 @@
<ItemGroup>
<Compile Include="Exceptions\InputTooLargeException.cs" />
<Compile Include="Exceptions\StreamTooShortException.cs" />
<Compile Include="Exceptions\TooMuchInputException.cs" />
<Compile Include="Formats\CompressionFormat.cs" />
<Compile Include="Formats\Nitro\Huffman.cs" />
<Compile Include="Formats\Nitro\LZ10.cs" />
@ -52,6 +53,7 @@
<Compile Include="Formats\Nitro\NitroCFormat.cs" />
<Compile Include="Exceptions\NotEnoughDataException.cs" />
<Compile Include="Formats\Nitro\RLE.cs" />
<Compile Include="NewProgram.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace DSDecmp
{
public class TooMuchInputException : Exception
{
/// <summary>
/// Gets the number of bytes read by the decompressed to decompress the stream.
/// </summary>
public long ReadBytes { get; private set; }
/// <summary>
/// Creates a new exception indicating that the input has more data than necessary for
/// decompressing th stream. It may indicate that other data is present after the compressed
/// stream.
/// </summary>
/// <param name="readBytes">The number of bytes read by the decompressor.</param>
/// <param name="totLength">The indicated length of the input stream.</param>
public TooMuchInputException(long readBytes, long totLength)
: base("The input contains more data than necessary. Only used 0x"
+ readBytes.ToString("X") + " of 0x" + totLength.ToString("X") + " bytes")
{
this.ReadBytes = readBytes;
}
}
}

View File

@ -117,10 +117,17 @@ namespace DSDecmp.Formats.Nitro
#endregion
}
}
if (readBytes < inLength)
throw new TooMuchInputException(readBytes, inLength);
}
public override int Compress(Stream instream, long inLength, Stream outstream)
{
if (inLength > 0xFFFFFF)
throw new InputTooLargeException();
List<byte> compressedData = new List<byte>();
// at most 0x7F+3=130 bytes are compressed into a single block.
@ -227,15 +234,12 @@ namespace DSDecmp.Formats.Nitro
currentBlockLength = 0;
}
if (compressedData.Count > 0xFFFFFF)
throw new InputTooLargeException();
// write the RLE marker and the decompressed size
outstream.WriteByte(0x30);
int compLen = compressedData.Count;
outstream.WriteByte((byte)(compLen & 0xFF));
outstream.WriteByte((byte)((compLen >> 8) & 0xFF));
outstream.WriteByte((byte)((compLen >> 16) & 0xFF));
outstream.WriteByte((byte)(inLength & 0xFF));
outstream.WriteByte((byte)((inLength >> 8) & 0xFF));
outstream.WriteByte((byte)((inLength >> 16) & 0xFF));
// write the compressed data
outstream.Write(compressedData.ToArray(), 0, compLen);

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using DSDecmp.Formats.Nitro;
using System.IO;
namespace DSDecmp
{
class TestProgram
{
public static void Main2(string[] args)
{
new RLE().Compress("tests/rle/testdata.dat", "tests/rle/cmp/testdata.rle.dat");
new RLE().Decompress("tests/rle/cmp/testdata.rle.dat", "tests/rle/dec/testdata.elr.dat");
Console.WriteLine("Success?");
Console.ReadLine();
}
}
}