#include "vdelhdr.h"
typedef struct _table_s
{ uchar* delta;
uchar* tar;
int n_tar;
K_UDECL(quick,recent,rhere);
} Table_t;
#if __STD_C
static int vdunfold(reg Table_t* tab)
#else
static int vdunfold(tab)
reg Table_t* tab;
#endif
{
reg int size, copy;
reg int inst, k_type, n;
reg uchar *tar, *to, *fr;
reg int t, c_addr, n_tar;
n_tar = tab->n_tar;
tar = tab->tar;
for(t = 0, c_addr = 0; t < n_tar; )
{ inst = STRGETC(tab);
k_type = K_GET(inst);
if(!VD_ISCOPY(k_type))
{ if(K_ISMERGE(k_type))
size = A_TGET(inst);
else if(A_ISHERE(inst))
size = A_LGET(inst);
else
{ STRGETU(tab,size);
size = A_GET(size);
}
if((t+size) > n_tar)
return -1;
c_addr += size;
STRREAD(tab,tar+t,size);
t += size;
if(K_ISMERGE(k_type))
{ size = C_TGET(inst);
k_type -= K_MERGE;
goto do_copy;
}
}
else
{ if(C_ISHERE(inst))
size = C_LGET(inst);
else
{ STRGETU(tab,size);
size = C_GET(size);
}
do_copy:
if((t+size) > n_tar)
return -1;
if(k_type >= K_QUICK && k_type < (K_QUICK+K_QTYPE) )
{ copy = STRGETC(tab);
copy = tab->quick[copy + ((k_type-K_QUICK)<<VD_BITS)];
}
else
{ STRGETU(tab,copy);
if(k_type >= K_RECENT && k_type < (K_RECENT+K_RTYPE) )
copy += tab->recent[k_type - K_RECENT];
else if(k_type == K_HERE)
copy = c_addr - copy;
}
K_UPDATE(tab->quick,tab->recent,tab->rhere,copy);
c_addr += size;
if(copy >= t || (copy+size) > n_tar)
return -1;
for(;;)
{ if((n = t-copy) > size)
n = size;
to = tar+t; fr = tar+copy;
MEMCPY(to,fr,n);
t += n;
if((size -= n) == 0)
break;
}
}
}
return 0;
}
#if __STD_C
int vdexpand(Void_t* target, int size, Void_t* delta)
#else
int vdexpand(target, size, delta)
Void_t* target;
int size;
Void_t* delta;
#endif
{
reg int t;
Table_t tab;
tab.tar = (uchar*)target;
tab.delta = (uchar*)delta;
STRGETU(&tab,t);
if(t > size)
return -1;
tab.n_tar = t;
K_INIT(tab.quick,tab.recent,tab.rhere);
if(vdunfold(&tab) < 0)
return -1;
return t;
}