Skip to content

Commit

Permalink
feat: added fastlz1_decompress
Browse files Browse the repository at this point in the history
  • Loading branch information
ikpil committed Oct 1, 2023
1 parent 1b8d42a commit 0056dc6
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 14 deletions.
114 changes: 101 additions & 13 deletions src/DotFastLZ.Compression/FastLZv2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress below.
*/
public static long fastlz_compress_level(int level, byte[] input, int length, byte[] output)
public static long fastlz_compress_level(int level, byte[] input, long length, byte[] output)
{
if (level == 1)
{
Expand Down Expand Up @@ -195,7 +195,10 @@ public static long fastlz2_compress(byte[] input, long length, byte[] output)
refIdx = ip_start + htab[hash];
htab[hash] = ip - ip_start;
distance = ip - refIdx;
cmp = distance < MAX_FARDISTANCE ? flz_readu32(input, refIdx) & 0xffffff : 0x1000000;
cmp = distance < MAX_FARDISTANCE
? flz_readu32(input, refIdx) & 0xffffff
: 0x1000000;

if (ip >= ip_limit)
{
break;
Expand Down Expand Up @@ -242,7 +245,7 @@ public static long fastlz2_compress(byte[] input, long length, byte[] output)
}

long copy = length - anchor;
op = flz_literals(copy, input, anchor, output,op);
op = flz_literals(copy, input, anchor, output, op);

/* marker for fastlz2 */
output[0] |= (1 << 5);
Expand All @@ -265,7 +268,7 @@ more than what is specified in maxout.
compression level specified in fastlz_compress_level above (when
producing the compressed block).
*/
public static int fastlz_decompress(byte[] input, int length, byte[] output, int maxout)
public static long fastlz_decompress(byte[] input, long length, byte[] output, long maxout)
{
/* magic identifier for compression level */
int level = (input[0] >> 5) + 1;
Expand All @@ -276,25 +279,92 @@ public static int fastlz_decompress(byte[] input, int length, byte[] output, int
return 0;
}

public static int fastlz1_decompress(byte[] input, int length, byte[] output, int maxout)
public static long fastlz1_decompress(byte[] input, long length, byte[] output, long maxout)
{
return 0;
long ip = 0;
long ip_limit = ip + length;
long ip_bound = ip_limit - 2;

long opOffset = 0;
long op = 0;
long op_limit = op + maxout;
long ctrl = input[ip++] & 31;

while (true)
{
if (ctrl >= 32)
{
long len = (ctrl >> 5) - 1;
long ofs = (ctrl & 31) << 8;
long refIdx = op - ofs - 1;
if (len == 7 - 1)
{
if (!(ip <= ip_bound))
{
return 0;
}

len += input[ip++];
}

refIdx -= input[ip++];
len += 3;
if (!(op + len <= op_limit))
{
return 0;
}

if (!(refIdx >= opOffset))
{
return 0;
}

fastlz_memmove(output, op, output, refIdx, len);
op += len;
}
else
{
ctrl++;
if (!(op + ctrl <= op_limit))
{
return 0;
}

if (!(ip + ctrl <= ip_limit))
{
return 0;
}

Array.Copy(input, ip, output, op, ctrl);
ip += ctrl;
op += ctrl;
}

if (ip > ip_bound)
{
break;
}

ctrl = input[ip++];
}

return op;
}

public static int fastlz2_decompress(byte[] input, int length, byte[] output, int maxout)
public static int fastlz2_decompress(byte[] input, long length, byte[] output, long maxout)
{
return 0;
}

private static uint flz_readu32(byte[] data, long offset)
public static uint flz_readu32(byte[] data, long offset)
{
return ((uint)data[offset + 3] & 0xff) << 24 |
((uint)data[offset + 2] & 0xff) << 16 |
((uint)data[offset + 1] & 0xff) << 8 |
((uint)data[offset + 0] & 0xff);
}

private static ushort flz_hash(long v)
public static ushort flz_hash(long v)
{
ulong h = ((ulong)v * 2654435769UL) >> (32 - HASH_LOG);
return (ushort)(h & HASH_MASK);
Expand All @@ -317,7 +387,7 @@ static void flz_maxcopy(byte[] dest, long destOffset, byte[] src, long secOffset
Array.Copy(src, secOffset, dest, destOffset, MAX_COPY);
}

private static long flz_literals(long runs, byte[] src, long srcOffset, byte[] dest, long destOffset)
public static long flz_literals(long runs, byte[] src, long srcOffset, byte[] dest, long destOffset)
{
while (runs >= MAX_COPY)
{
Expand All @@ -338,7 +408,7 @@ private static long flz_literals(long runs, byte[] src, long srcOffset, byte[] d
return destOffset;
}

private static long flz1_match(long len, long distance, byte[] output, long op)
public static long flz1_match(long len, long distance, byte[] output, long op)
{
--distance;
if (len > MAX_LEN - 2)
Expand Down Expand Up @@ -367,7 +437,7 @@ private static long flz1_match(long len, long distance, byte[] output, long op)
return op;
}

private static long flz2_match(long len, long distance, byte[] output, long op)
public static long flz2_match(long len, long distance, byte[] output, long op)
{
--distance;
if (distance < MAX_L2_DISTANCE)
Expand Down Expand Up @@ -419,7 +489,7 @@ private static long flz2_match(long len, long distance, byte[] output, long op)
return op;
}

private static long flz_cmp(byte[] p, long pOffset, byte[] q, long qOffset, long r)
public static long flz_cmp(byte[] p, long pOffset, byte[] q, long qOffset, long r)
{
long start = pOffset;

Expand All @@ -437,5 +507,23 @@ private static long flz_cmp(byte[] p, long pOffset, byte[] q, long qOffset, long

return pOffset - start;
}

public static void fastlz_memmove(byte[] dest, long destOffset, byte[] src, long srcOffset, long count)
{
if (dest.Length < destOffset + count)
{
throw new IndexOutOfRangeException($"{dest.Length} < {destOffset} + {count}");
}

if (src.Length < srcOffset + count)
{
throw new IndexOutOfRangeException($"{src.Length} < {srcOffset} + {count}");
}

for (long i = 0; i < count; ++i)
{
dest[destOffset + i] = src[srcOffset + i];
}
}
}
}
2 changes: 1 addition & 1 deletion test/DotFastLZ.Compression.Tests/Fixtures/TestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public static bool test_roundtrip_level1(string name, string file_name)

Array.Fill(uncompressed_buffer, (byte)'-');

FastLZ.Decompress(compressed_buffer, 0, compressed_buffer.Length, uncompressed_buffer, 0, uncompressed_buffer.Length);
FastLZv2.fastlz1_decompress(compressed_buffer, compressed_size, uncompressed_buffer, uncompressed_buffer.Length);

Console.WriteLine("Comparing. Please wait...");
long result = ResourceHelper.Compare(file_name, file_buffer, uncompressed_buffer, file_size);
Expand Down

0 comments on commit 0056dc6

Please sign in to comment.