depacks.c
来自「一些初级的网络编程」· C语言 代码 · 共 228 行
C
228 行
/*
* aPLib compression library - the smaller the better :)
*
* C safe depacker
*
* Copyright (c) 1998-2004 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*/
#include "depacks.h"
/* internal data structure */
typedef struct {
const unsigned char *source;
unsigned int srclen;
unsigned char *destination;
unsigned int dstlen;
unsigned int tag;
unsigned int bitcount;
} APDEPACKSAFEDATA;
static int aP_getbit_safe(APDEPACKSAFEDATA *ud, unsigned int *result)
{
unsigned int bit;
/* check if tag is empty */
if (!ud->bitcount--)
{
if (!ud->srclen--) return 0;
/* load next tag */
ud->tag = *ud->source++;
ud->bitcount = 7;
}
/* shift bit out of tag */
bit = (ud->tag >> 7) & 0x01;
ud->tag <<= 1;
*result = bit;
return 1;
}
static int aP_getgamma_safe(APDEPACKSAFEDATA *ud, unsigned int *result)
{
unsigned int bit;
unsigned int v = 1;
/* input gamma2-encoded bits */
do {
if (!aP_getbit_safe(ud, &bit)) return 0;
v = (v << 1) + bit;
if (!aP_getbit_safe(ud, &bit)) return 0;
} while (bit);
*result = v;
return 1;
}
unsigned int aP_depack_safe(const void *source,
unsigned int srclen,
void *destination,
unsigned int dstlen)
{
APDEPACKSAFEDATA ud;
unsigned int offs, len, R0, LWM, bit;
int done;
int i;
if (!source || !destination) return APLIB_ERROR;
ud.source = (const unsigned char *) source;
ud.srclen = srclen;
ud.destination = (unsigned char *) destination;
ud.dstlen = dstlen;
ud.bitcount = 0;
LWM = 0;
done = 0;
/* first byte verbatim */
if (!ud.srclen-- || !ud.dstlen--) return APLIB_ERROR;
*ud.destination++ = *ud.source++;
/* main decompression loop */
while (!done)
{
if (!aP_getbit_safe(&ud, &bit)) return APLIB_ERROR;
if (bit)
{
if (!aP_getbit_safe(&ud, &bit)) return APLIB_ERROR;
if (bit)
{
if (!aP_getbit_safe(&ud, &bit)) return APLIB_ERROR;
if (bit)
{
offs = 0;
for (i = 4; i; i--)
{
if (!aP_getbit_safe(&ud, &bit)) return APLIB_ERROR;
offs = (offs << 1) + bit;
}
if (offs)
{
if (offs > (dstlen - ud.dstlen)) return APLIB_ERROR;
if (!ud.dstlen--) return APLIB_ERROR;
*ud.destination = *(ud.destination - offs);
ud.destination++;
} else {
if (!ud.dstlen--) return APLIB_ERROR;
*ud.destination++ = 0x00;
}
LWM = 0;
} else {
if (!ud.srclen--) return APLIB_ERROR;
offs = *ud.source++;
len = 2 + (offs & 0x0001);
offs >>= 1;
if (offs)
{
if (offs > (dstlen - ud.dstlen)) return APLIB_ERROR;
if (len > ud.dstlen) return APLIB_ERROR;
ud.dstlen -= len;
for (; len; len--)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
}
} else done = 1;
R0 = offs;
LWM = 1;
}
} else {
if (!aP_getgamma_safe(&ud, &offs)) return APLIB_ERROR;
if ((LWM == 0) && (offs == 2))
{
offs = R0;
if (!aP_getgamma_safe(&ud, &len)) return APLIB_ERROR;
if (offs > (dstlen - ud.dstlen)) return APLIB_ERROR;
if (len > ud.dstlen) return APLIB_ERROR;
ud.dstlen -= len;
for (; len; len--)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
}
} else {
if (LWM == 0) offs -= 3; else offs -= 2;
if (!ud.srclen--) return APLIB_ERROR;
offs <<= 8;
offs += *ud.source++;
if (!aP_getgamma_safe(&ud, &len)) return APLIB_ERROR;
if (offs >= 32000) len++;
if (offs >= 1280) len++;
if (offs < 128) len += 2;
if (offs > (dstlen - ud.dstlen)) return APLIB_ERROR;
if (len > ud.dstlen) return APLIB_ERROR;
ud.dstlen -= len;
for (; len; len--)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
}
R0 = offs;
}
LWM = 1;
}
} else {
if (!ud.srclen-- || !ud.dstlen--) return APLIB_ERROR;
*ud.destination++ = *ud.source++;
LWM = 0;
}
}
return ud.destination - (unsigned char *) destination;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?