mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
158 lines
3.1 KiB
C++
158 lines
3.1 KiB
C++
#include "LayDes.h"
|
|
|
|
static inline int sMatchLen(const char *a, const char *al, const char *b, const char *bl)
|
|
{
|
|
const char *q = a;
|
|
if(al - a < bl - b)
|
|
while(a < al && *a == *b) {
|
|
a++;
|
|
b++;
|
|
}
|
|
else
|
|
while(b < bl && *a == *b) {
|
|
a++;
|
|
b++;
|
|
}
|
|
return int(a - q);
|
|
}
|
|
|
|
unsigned HashPos(byte *s)
|
|
{
|
|
return s[0] + (s[1] << 8) + (s[2] << 16) + (s[3] << 24);
|
|
}
|
|
|
|
void DiffPacker::SetMaster(const String& m)
|
|
{
|
|
master = m;
|
|
mapn = master.GetLength() | 5;
|
|
prev.Alloc(master.GetLength(), -1);
|
|
map.Alloc(mapn, -1);
|
|
for(int i = master.GetLength() - 4; i >= 0; --i) {
|
|
int hp = HashPos((byte *)~master + i) % mapn;
|
|
prev[i] = map[hp];
|
|
map[hp] = i;
|
|
}
|
|
}
|
|
|
|
String DiffPacker::Pack(const String& data)
|
|
{
|
|
String result;
|
|
const char *masterend = master.End();
|
|
const char *dataend = data.End();
|
|
const char *s = data;
|
|
while(s < dataend) {
|
|
int pos = 0;
|
|
int ml = 0;
|
|
int p = map[HashPos((byte *)s) % mapn];
|
|
int ni = INT_MAX;
|
|
while(p >= 0 && ml < ni) {
|
|
int l = sMatchLen(s, dataend, ~master + p, masterend);
|
|
if(l > ml) {
|
|
pos = p;
|
|
ml = l;
|
|
}
|
|
p = prev[p];
|
|
ni >>= 1;
|
|
}
|
|
if(ml > 65535)
|
|
ml = 65535;
|
|
if(pos <= 255 && ml <= 255 && ml > 3) {
|
|
result.Cat(0xfb);
|
|
result.Cat(pos);
|
|
result.Cat(ml);
|
|
s += ml;
|
|
}
|
|
else
|
|
if(pos <= 65535 && ml <= 255 && ml > 4) {
|
|
result.Cat(0xfc);
|
|
result.Cat(LOBYTE(pos));
|
|
result.Cat(HIBYTE(pos));
|
|
result.Cat(ml);
|
|
s += ml;
|
|
}
|
|
else
|
|
if(pos <= 65535 && ml > 5) {
|
|
result.Cat(0xfd);
|
|
result.Cat(LOBYTE(pos));
|
|
result.Cat(HIBYTE(pos));
|
|
result.Cat(LOBYTE(ml));
|
|
result.Cat(HIBYTE(ml));
|
|
s += ml;
|
|
}
|
|
else
|
|
if(ml > 7) {
|
|
result.Cat(0xfe);
|
|
result.Cat(LOBYTE(LOWORD(pos)));
|
|
result.Cat(HIBYTE(LOWORD(pos)));
|
|
result.Cat(LOBYTE(HIWORD(pos)));
|
|
result.Cat(HIBYTE(HIWORD(pos)));
|
|
result.Cat(LOBYTE(ml));
|
|
result.Cat(HIBYTE(ml));
|
|
s += ml;
|
|
}
|
|
else {
|
|
if((byte)*s >= 0xfb)
|
|
result.Cat(0xff);
|
|
result.Cat(*s++);
|
|
}
|
|
}
|
|
result.Shrink();
|
|
return result;
|
|
}
|
|
|
|
String DiffPack(const String& master, const String& data)
|
|
{
|
|
DiffPacker p;
|
|
p.SetMaster(master);
|
|
return p.Pack(data);
|
|
}
|
|
|
|
String DiffUnpack(const String& master, const String& pack)
|
|
{
|
|
String result;
|
|
const char *s = pack;
|
|
while(s < pack.End()) {
|
|
int c = (byte)*s++;
|
|
if(c == 0xfb) {
|
|
ASSERT(s <= pack.End() - 2);
|
|
byte p = (byte)*s++;
|
|
byte l = (byte)*s++;
|
|
result.Cat(~master + p, l);
|
|
}
|
|
else
|
|
if(c == 0xfc) {
|
|
ASSERT(s <= pack.End() - 3);
|
|
byte pl = (byte)*s++;
|
|
byte ph = (byte)*s++;
|
|
byte ln = (byte)*s++;
|
|
result.Cat(~master + MAKEWORD(pl, ph), ln);
|
|
}
|
|
else
|
|
if(c == 0xfd) {
|
|
ASSERT(s <= pack.End() - 4);
|
|
byte pl = (byte)*s++;
|
|
byte ph = (byte)*s++;
|
|
byte ll = (byte)*s++;
|
|
byte lh = (byte)*s++;
|
|
result.Cat(~master + MAKEWORD(pl, ph), MAKEWORD(ll, lh));
|
|
}
|
|
else
|
|
if(c == 0xfe) {
|
|
ASSERT(s <= pack.End() - 5);
|
|
byte pll = (byte)*s++;
|
|
byte plh = (byte)*s++;
|
|
byte phl = (byte)*s++;
|
|
byte phh = (byte)*s++;
|
|
byte ll = (byte)*s++;
|
|
byte lh = (byte)*s++;
|
|
result.Cat(~master + MAKELONG(MAKEWORD(pll, plh), MAKEWORD(phl, phh)),
|
|
MAKEWORD(ll, lh));
|
|
}
|
|
else
|
|
if(c == 0xff)
|
|
result.Cat(*s++);
|
|
else
|
|
result.Cat(c);
|
|
}
|
|
return result;
|
|
}
|