vector-default/depack.h
/*
* aPLib compression library - the smaller the better :)
*
* C depacker, header file
*
* Copyright (c) 1998-2009 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
*/
#ifndef DEPACK_H_INCLUDED
#define DEPACK_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#ifndef APLIB_ERROR
# define APLIB_ERROR (-1)
#endif
/* internal data structure */
typedef struct {
const unsigned char *source;
unsigned char *destination;
unsigned int tag;
unsigned int bitcount;
} APDEPACKDATA;
/*
; header format:
;
; offs size data
; --------------------------------------
; 0 dword tag ('AP32')
; 4 dword header_size (24 bytes)
; 8 dword packed_size
; 12 dword packed_crc
; 16 dword orig_size
; 20 dword orig_crc
*/
typedef struct {
DWORD tag;
DWORD header_size;
DWORD packed_size;
DWORD packed_crc;
DWORD orig_size;
DWORD orig_crc;
} APLIBHEADER, *PALIBHEADER;
__forceinline static int aP_getbit(APDEPACKDATA *ud)
{
unsigned int bit;
/* check if tag is empty */
if (!ud->bitcount--)
{
/* load next tag */
ud->tag = *ud->source++;
ud->bitcount = 7;
}
/* shift bit out of tag */
bit = (ud->tag >> 7) & 0x01;
ud->tag <<= 1;
return bit;
}
__forceinline static unsigned int aP_getgamma(APDEPACKDATA *ud)
{
unsigned int result = 1;
/* input gamma2-encoded bits */
do {
result = (result << 1) + aP_getbit(ud);
} while (aP_getbit(ud));
return (result);
}
//__forceinline unsigned int aP_depack(const void *source, void *destination)
unsigned int aP_depack(const void *source, void *destination)
{
APDEPACKDATA ud;
unsigned int offs, len, R0, LWM;
int done;
int i;
ud.source = (const unsigned char *) source;
ud.destination = (unsigned char *) destination;
ud.bitcount = 0;
LWM = 0;
done = 0;
/* first byte verbatim */
*ud.destination++ = *ud.source++;
/* main decompression loop */
while (!done)
{
if (aP_getbit(&ud))
{
if (aP_getbit(&ud))
{
if (aP_getbit(&ud))
{
offs = 0;
for (i = 4; i; i--) offs = (offs << 1) + aP_getbit(&ud);
if (offs)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
} else {
*ud.destination++ = 0x00;
}
LWM = 0;
} else {
offs = *ud.source++;
len = 2 + (offs & 0x0001);
offs >>= 1;
if (offs)
{
for (; len; len--)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
}
} else done = 1;
R0 = offs;
LWM = 1;
}
} else {
offs = aP_getgamma(&ud);
if ((LWM == 0) && (offs == 2))
{
offs = R0;
len = aP_getgamma(&ud);
for (; len; len--)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
}
} else {
if (LWM == 0) offs -= 3; else offs -= 2;
offs <<= 8;
offs += *ud.source++;
len = aP_getgamma(&ud);
if (offs >= 32000) len++;
if (offs >= 1280) len++;
if (offs < 128) len += 2;
for (; len; len--)
{
*ud.destination = *(ud.destination - offs);
ud.destination++;
}
R0 = offs;
}
LWM = 1;
}
} else {
*ud.destination++ = *ud.source++;
LWM = 0;
}
}
return ud.destination - (unsigned char *) destination;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* DEPACK_H_INCLUDED */