0 Star 1 Fork 3

Cheney/McuCodeCompress

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
MiniLZO.cs 24.08 KB
一键复制 编辑 原始数据 按行查看 历史
Cheney 提交于 2017-07-12 08:47 . First version.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
/**
* ManagedLZO.MiniLZO
*
* Minimalistic reimplementation of minilzo in C#
*
* @author Shane Eric Bryldt, Copyright (C) 2006, All Rights Reserved
* @note Uses unsafe/fixed pointer contexts internally
* @liscence Bound by same liscence as minilzo as below, see file COPYING
*/
/* Based on minilzo.c -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2, as published by the Free Software Foundation.
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
/*
* NOTE:
* the full LZO package can be found at
* http://www.oberhumer.com/opensource/lzo/
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace ManagedLZO
{
public static class MiniLZO
{
private const uint M2_MAX_LEN = 8;
private const uint M3_MAX_LEN = 33;
private const uint M4_MAX_LEN = 9;
private const byte M3_MARKER = 32;
private const byte M4_MARKER = 16;
private const uint M1_MAX_OFFSET = 0x0400;
private const uint M2_MAX_OFFSET = 0x0800;
private const uint M3_MAX_OFFSET = 0x4000;
private const uint M4_MAX_OFFSET = 0xbfff;
private const byte BITS = 14;
private const uint D_MASK = (1 << BITS) - 1;
private const uint DICT_SIZE = 65536 + 3;
public unsafe static void Compress(byte[] src, out byte[] dst)
{
uint tmp;
uint dstlen = (uint)(src.Length + (src.Length / 16) + 64 + 3);
dst = new byte[dstlen];
if (src.Length <= M2_MAX_LEN + 5)
{
tmp = (uint)src.Length;
dstlen = 0;
}
else
{
byte[] workmem = new byte[DICT_SIZE];
fixed (byte* work = workmem, input = src, output = dst)
{
byte** dict = (byte**)work;
byte* in_end = input + src.Length;
byte* ip_end = input + src.Length - M2_MAX_LEN - 5;
byte* ii = input;
byte* ip = input + 4;
byte* op = output;
bool literal = false;
bool match = false;
uint offset;
uint length;
uint index;
byte* pos;
for (; ; )
{
offset = 0;
index = D_INDEX1(ip);
pos = ip - (ip - dict[index]);
if (pos < input || (offset = (uint)(ip - pos)) <= 0 || offset > M4_MAX_OFFSET)
literal = true;
else if (offset <= M2_MAX_OFFSET || pos[3] == ip[3])
{
}
else
{
index = D_INDEX2(index);
pos = ip - (ip - dict[index]);
if (pos < input || (offset = (uint)(ip - pos)) <= 0 || offset > M4_MAX_OFFSET)
literal = true;
else if (offset <= M2_MAX_OFFSET || pos[3] == ip[3])
{
}
else
literal = true;
}
if (!literal)
{
if (*((ushort*)pos) == *((ushort*)ip) && pos[2] == ip[2])
match = true;
}
literal = false;
if (!match)
{
dict[index] = ip;
++ip;
if (ip >= ip_end)
break;
continue;
}
match = false;
dict[index] = ip;
if (ip - ii > 0)
{
uint t = (uint)(ip - ii);
if (t <= 3)
{
Debug.Assert(op - 2 > output);
op[-2] |= (byte)(t);
}
else if (t <= 18)
*op++ = (byte)(t - 3);
else
{
uint tt = t - 18;
*op++ = 0;
while (tt > 255)
{
tt -= 255;
*op++ = 0;
}
Debug.Assert(tt > 0);
*op++ = (byte)(tt);
}
do
{
*op++ = *ii++;
} while (--t > 0);
}
Debug.Assert(ii == ip);
ip += 3;
if (pos[3] != *ip++ || pos[4] != *ip++ || pos[5] != *ip++
|| pos[6] != *ip++ || pos[7] != *ip++ || pos[8] != *ip++)
{
--ip;
length = (uint)(ip - ii);
Debug.Assert(length >= 3);
Debug.Assert(length <= M2_MAX_LEN);
if (offset <= M2_MAX_OFFSET)
{
--offset;
*op++ = (byte)(((length - 1) << 5) | ((offset & 7) << 2));
*op++ = (byte)(offset >> 3);
}
else if (offset <= M3_MAX_OFFSET)
{
--offset;
*op++ = (byte)(M3_MARKER | (length - 2));
*op++ = (byte)((offset & 63) << 2);
*op++ = (byte)(offset >> 6);
}
else
{
offset -= 0x4000;
Debug.Assert(offset > 0);
Debug.Assert(offset <= 0x7FFF);
*op++ = (byte)(M4_MARKER | ((offset & 0x4000) >> 11) | (length - 2));
*op++ = (byte)((offset & 63) << 2);
*op++ = (byte)(offset >> 6);
}
}
else
{
byte* m = pos + M2_MAX_LEN + 1;
while (ip < in_end && *m == *ip)
{
++m;
++ip;
}
length = (uint)(ip - ii);
Debug.Assert(length > M2_MAX_LEN);
if (offset <= M3_MAX_OFFSET)
{
--offset;
if (length <= 33)
*op++ = (byte)(M3_MARKER | (length - 2));
else
{
length -= 33;
*op++ = M3_MARKER | 0;
while (length > 255)
{
length -= 255;
*op++ = 0;
}
Debug.Assert(length > 0);
*op++ = (byte)(length);
}
}
else
{
offset -= 0x4000;
Debug.Assert(offset > 0);
Debug.Assert(offset <= 0x7FFF);
if (length <= M4_MAX_LEN)
*op++ = (byte)(M4_MARKER | ((offset & 0x4000) >> 11) | (length - 2));
else
{
length -= M4_MAX_LEN;
*op++ = (byte)(M4_MARKER | ((offset & 0x4000) >> 11));
while (length > 255)
{
length -= 255;
*op++ = 0;
}
Debug.Assert(length > 0);
*op++ = (byte)(length);
}
}
*op++ = (byte)((offset & 63) << 2);
*op++ = (byte)(offset >> 6);
}
ii = ip;
if (ip >= ip_end)
break;
}
dstlen = (uint)(op - output);
tmp = (uint)(in_end - ii);
}
}
if (tmp > 0)
{
uint ii = (uint)src.Length - tmp;
if (dstlen == 0 && tmp <= 238)
{
dst[dstlen++] = (byte)(17 + tmp);
}
else if (tmp <= 3)
{
dst[dstlen - 2] |= (byte)(tmp);
}
else if (tmp <= 18)
{
dst[dstlen++] = (byte)(tmp - 3);
}
else
{
uint tt = tmp - 18;
dst[dstlen++] = 0;
while (tt > 255)
{
tt -= 255;
dst[dstlen++] = 0;
}
Debug.Assert(tt > 0);
dst[dstlen++] = (byte)(tt);
}
do
{
dst[dstlen++] = src[ii++];
} while (--tmp > 0);
}
dst[dstlen++] = M4_MARKER | 1;
dst[dstlen++] = 0;
dst[dstlen++] = 0;
if (dst.Length != dstlen)
{
byte[] final = new byte[dstlen];
Buffer.BlockCopy(dst, 0, final, 0, (int)dstlen);
dst = final;
}
}
public unsafe static void Decompress(byte[] src, byte[] dst)
{
uint t = 0;
fixed (byte* input = src, output = dst)
{
byte* pos = null;
byte* ip_end = input + src.Length;
byte* op_end = output + dst.Length;
byte* ip = input;
byte* op = output;
bool match = false;
bool match_next = false;
bool match_done = false;
bool copy_match = false;
bool first_literal_run = false;
bool eof_found = false;
if (*ip > 17)
{
t = (uint)(*ip++ - 17);
if (t < 4)
match_next = true;
else
{
Debug.Assert(t > 0);
if ((op_end - op) < t)
throw new OverflowException("Output Overrun");
if ((ip_end - ip) < t + 1)
throw new OverflowException("Input Overrun");
do
{
*op++ = *ip++;
} while (--t > 0);
first_literal_run = true;
}
}
while (!eof_found && ip < ip_end)
{
if (!match_next && !first_literal_run)
{
t = *ip++;
if (t >= 16)
match = true;
else
{
if (t == 0)
{
if ((ip_end - ip) < 1)
throw new OverflowException("Input Overrun");
while (*ip == 0)
{
t += 255;
++ip;
if ((ip_end - ip) < 1)
throw new OverflowException("Input Overrun");
}
t += (uint)(15 + *ip++);
}
Debug.Assert(t > 0);
if ((op_end - op) < t + 3)
throw new OverflowException("Output Overrun");
if ((ip_end - ip) < t + 4)
throw new OverflowException("Input Overrun");
for (int x = 0; x < 4; ++x, ++op, ++ip)
*op = *ip;
if (--t > 0)
{
if (t >= 4)
{
do
{
for (int x = 0; x < 4; ++x, ++op, ++ip)
*op = *ip;
t -= 4;
} while (t >= 4);
if (t > 0)
{
do
{
*op++ = *ip++;
} while (--t > 0);
}
}
else
{
do
{
*op++ = *ip++;
} while (--t > 0);
}
}
}
}
if (!match && !match_next)
{
first_literal_run = false;
t = *ip++;
if (t >= 16)
match = true;
else
{
pos = op - (1 + M2_MAX_OFFSET);
pos -= t >> 2;
pos -= *ip++ << 2;
if (pos < output || pos >= op)
throw new OverflowException("Lookbehind Overrun");
if ((op_end - op) < 3)
throw new OverflowException("Output Overrun");
*op++ = *pos++;
*op++ = *pos++;
*op++ = *pos++;
match_done = true;
}
}
match = false;
do
{
if (t >= 64)
{
pos = op - 1;
pos -= (t >> 2) & 7;
pos -= *ip++ << 3;
t = (t >> 5) - 1;
if (pos < output || pos >= op)
throw new OverflowException("Lookbehind Overrun");
if ((op_end - op) < t + 2)
throw new OverflowException("Output Overrun");
copy_match = true;
}
else if (t >= 32)
{
t &= 31;
if (t == 0)
{
if ((ip_end - ip) < 1)
throw new OverflowException("Input Overrun");
while (*ip == 0)
{
t += 255;
++ip;
if ((ip_end - ip) < 1)
throw new OverflowException("Input Overrun");
}
t += (uint)(31 + *ip++);
}
pos = op - 1;
pos -= (*(ushort*)ip) >> 2;
ip += 2;
}
else if (t >= 16)
{
pos = op;
pos -= (t & 8) << 11;
t &= 7;
if (t == 0)
{
if ((ip_end - ip) < 1)
throw new OverflowException("Input Overrun");
while (*ip == 0)
{
t += 255;
++ip;
if ((ip_end - ip) < 1)
throw new OverflowException("Input Overrun");
}
t += (uint)(7 + *ip++);
}
pos -= (*(ushort*)ip) >> 2;
ip += 2;
if (pos == op)
eof_found = true;
else
pos -= 0x4000;
}
else
{
pos = op - 1;
pos -= t >> 2;
pos -= *ip++ << 2;
if (pos < output || pos >= op)
throw new OverflowException("Lookbehind Overrun");
if ((op_end - op) < 2)
throw new OverflowException("Output Overrun");
*op++ = *pos++;
*op++ = *pos++;
match_done = true;
}
if (!eof_found && !match_done && !copy_match)
{
if (pos < output || pos >= op)
throw new OverflowException("Lookbehind Overrun");
Debug.Assert(t > 0);
if ((op_end - op) < t + 2)
throw new OverflowException("Output Overrun");
}
if (!eof_found && t >= 2 * 4 - 2 && (op - pos) >= 4 && !match_done && !copy_match)
{
for (int x = 0; x < 4; ++x, ++op, ++pos)
*op = *pos;
t -= 2;
do
{
for (int x = 0; x < 4; ++x, ++op, ++pos)
*op = *pos;
t -= 4;
} while (t >= 4);
if (t > 0)
{
do
{
*op++ = *pos++;
} while (--t > 0);
}
}
else if(!eof_found && !match_done)
{
copy_match = false;
*op++ = *pos++;
*op++ = *pos++;
do
{
*op++ = *pos++;
} while (--t > 0);
}
if (!eof_found && !match_next)
{
match_done = false;
t = (uint)(ip[-2] & 3);
if (t == 0)
break;
}
if (!eof_found)
{
match_next = false;
Debug.Assert(t > 0);
Debug.Assert(t < 4);
if ((op_end - op) < t)
throw new OverflowException("Output Overrun");
if ((ip_end - ip) < t + 1)
throw new OverflowException("Input Overrun");
*op++ = *ip++;
if (t > 1)
{
*op++ = *ip++;
if (t > 2)
*op++ = *ip++;
}
t = *ip++;
}
} while (!eof_found && ip < ip_end);
}
if (!eof_found)
throw new OverflowException("EOF Marker Not Found");
else
{
Debug.Assert(t == 1);
if (ip > ip_end)
throw new OverflowException("Input Overrun");
else if (ip < ip_end)
throw new OverflowException("Input Not Consumed");
}
}
}
private unsafe static uint D_INDEX1(byte * input)
{
return D_MS(D_MUL(0x21, D_X3(input, 5, 5, 6)) >> 5, 0);
}
private static uint D_INDEX2(uint idx)
{
return (idx & (D_MASK & 0x7FF)) ^ (((D_MASK >> 1) + 1) | 0x1F);
}
private static uint D_MS(uint v, byte s)
{
return (v & (D_MASK >> s)) << s;
}
private static uint D_MUL(uint a, uint b)
{
return a * b;
}
private unsafe static uint D_X2(byte* input, byte s1, byte s2)
{
return (uint)((((input[2] << s2) ^ input[1]) << s1) ^ input[0]);
}
private unsafe static uint D_X3(byte* input, byte s1, byte s2, byte s3)
{
return (D_X2(input + 1, s2, s3) << s1) ^ input[0];
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/orange2348/mcu_compress.git
git@gitee.com:orange2348/mcu_compress.git
orange2348
mcu_compress
McuCodeCompress
master

搜索帮助