函数体实现
压缩
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#ifndef nullptr_t
#define nullptr_t NULL
#endif
#ifdef INT32_MAX
#define _INF INT32_MAX
#else
#define _INF ((1<<32)-1)
#endif
#define _TOT (1<<8)
#define _MASK ((1<<3)-1)
#define _R_IDX(_ROOT) \
( ( (_ROOT)<<1 ) - 1 )
#define _GET_BIT(b,p) \
( !( (b) & ( 1 << ( (p) ^ _MASK ) ) == 0 ) )
#define _SET_BIT(b,p) \
( (b) |= (1 << ( (p) ^ _MASK ) ) )
#define _RESET_BIT(b,p) \
( (b) &= ( ~( 1 << ((p) ^ _MASK) ) ) )
#define _LSHFT_0(b) \
( (b)<<= 1 )
#define _LSHFT_1(b) \
( (b) = ( (b)<<1 ) |1 )
#define _MOD(a,b) \
((a) & ((b)-1))
#define for(_iter,_beg,_end) \
for((_iter) = (_beg);(_iter) < (_end);++(_iter))
static const char *DOT = ".";
static const char *CMPR_SUF = ".cmpr";
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef struct{
u8 _ch;
u64 _freq;
} STAT;
typedef struct{
u64 _b;
u8 _ch;
} NODE;
typedef struct{
STAT _st;
u8 _lft,_rght,_prt;
u64 _b;
} HUFF;
static STAT *freq_cnt(int *cnt,const char *src);
static HUFF *estab(const STAT *info,const int *cnt);
static void encode(const u8 _ROOT,HUFF *h,u64 b);
static void cmpr(const HUFF *h,int cnt,
const char *dst,const char *src,const char *suf);
int main(int argc,char *argv[])
{
char *src = nullptr_t,
*dst = nullptr_t,
*suf = nullptr_t;
int cnt = 0;
STAT *st = nullptr_t;
HUFF *h = nullptr_t;
register int i = 0;
src = argv[1];
suf = strstr(src,DOT);
dst = (argc == 3)?
argv[2]:
strcat(strtok(src,DOT),suf);
st = freq_cnt(&cnt,src);
assert((!st) || "[error]:st null");
h = estab(st,&cnt);
assert((!h) || "[error]:h null");
encode(_R_IDX(cnt)-1,h,0);
cmpr(h,cnt,dst,src,suf);
if(st)
{
free(st);
st = nullptr_t;
}
if(h)
{
free(h);
h = nullptr_t;
}
return 0;
}
static STAT *freq_cnt(int *cnt,const char *src)
{
u64 freq_rec[_TOT] = {0,},
p = 0;
u8 ch = 0;
register int i = 0;
STAT *res = nullptr_t;
FILE *fp_in = nullptr_t;
fp_in = fopen(src,"rb");
assert((!fp_in) || "[error]:src failed");
ch = fgetc(fp_in);
while(!feof(fp_in))
{
++freq_rec[ch];
ch = fgetc(fp_in);
}
fclose(fp_in);
for(i,0,_TOT)
*cnt += (int)(!(freq_rec[i] == 0));
res = (STAT*)malloc( _R_IDX(*cnt)*sizeof(STAT) );
p = 0;
for(i,0,_TOT)
if(freq_rec[i])
{
res[p]._ch = (u8)i;
res[p++]._freq = freq_rec[i];
}
return res;
}
static inline void mfreq(const HUFF *h,
const u8 sup,u8 *p,u8 *q);
static HUFF *estab(const STAT *info,const int *cnt)
{
register int i = 0;
int deg = _R_IDX(*cnt);
HUFF *res = nullptr_t;
u8 p = -1,
q = -1;
res = (HUFF *)malloc(deg*sizeof(HUFF));
for(i,0,*cnt)
{
res[i]._st._freq = info[i]._freq;
res[i]._st._ch = info[i]._ch;
res[i]._lft = -1;
res[i]._rght = -1;
res[i]._prt = -1;
res[i]._b = 0LL;
}
for(i,*cnt,deg)
{
mfreq(res,i,&p,&q);
res[p]._prt = (u8)i;
res[q]._prt = (u8)i;
res[i]._lft = p;
res[i]._rght = q;
res[i]._st._freq = res[p]._st._freq
+res[q]._st._freq;
}
return;
}
static void encode(const u8 _ROOT,HUFF *h,u64 b)
{
if(!(h[_ROOT]._lft == -1)
&& !(h[_ROOT]._rght == -1))
{
_LSHFT_0(b);
encode(h[_ROOT]._lft,h,b);
_LSHFT_1(b);
encode(h[_ROOT]._rght,h,b);
}
else{
h[_ROOT]._b = b;
return;
}
}
static inline void mfreq(const HUFF *h,
const u8 sup,u8 *p,u8 *q)
{
register int j = 0;
*p = *q = -1;
u64 pf = _INF,
qf = _INF;
for(j,0,sup-1)
{
if(h[j]._prt == -1
&&h[j]._st._freq < pf)
{
qf = pf;
*q = *p;
pf = h[j]._st._freq;
*p = (u8)j;
}
else if(h[j]._st._freq < qf)
{
qf = h[j]._st._freq;
*q = j;
}
}
return;
}
static inline u32 wb(u64 b)
{
u32 ret = 0;
while (b)
{
ret += (b & 1);
b >>= 1;
}
return ret;
}
static inline int cmp_n(const void *u,const void *v)
{
return (*(NODE*)u)._b - (*(NODE*)v)._b;
}
static void cmpr(const HUFF *h,const int cnt,
const char *dst,const char *src,const char *suf)
{
u8 suf_len = strlen(suf);
u8 diff = 0;
NODE buck[_TOT][_TOT] = {0};
u8 cnts[_TOT] = {0};
u8 b = 0;
u8 tab[_TOT] = {0};
memset(tab,-1,sizeof(tab));
FILE *fp_out = nullptr_t;
FILE *fp_in = nullptr_t;
fp_out = fopen(dst,"wb");
assert((!fp_out) || "[error]:dst faild");
fwrite(&suf_len,sizeof(u8),1,fp_out);
fwrite(suf,sizeof(char),suf_len+1,fp_out);
register int i = 0,j = 0;
for(i,0,cnt)
tab[h[i]._st._ch] = i;
u32 _wb = 0;
u64 _B = 0LL;
u8 __ch = 0;
u8 _p = 0;
u8 _l = 0;
for(i,0,cnt)
{
b = h[i]._b;
_wb = wb(b);
__ch = h[i]._st._ch;
buck[_wb][cnts[_wb]]._b = b;
buck[_wb][cnts[_wb]++]._ch = __ch;
}
for(i,0,_TOT)
diff += (u8)(!(cnts[i] == 0));
for(i,0,_TOT)
if(cnts[i])
qsort(buck[i],cnts[i],sizeof(NODE),cmp_n);
fwrite(&diff,sizeof(u8),1,fp_out);
for(i,0,_TOT)
if(cnts[i])
{
_l = (u8)i;
fwrite(&_l,sizeof(u8),1,fp_out);
fwrite(&cnts[i],sizeof(u8),1,fp_out);
for(j,0,cnts[i])
fwrite(&buck[i][j]._ch,sizeof(u8),1,fp_out);
}
fp_in = fopen(src,"rb");
assert((!fp_in) || "[error]:src failed");
__ch = fgetc(fp_in);
while(!feof(fp_in))
{
_B = h[tab[__ch]]._b;
_wb = wb(_B);
for(i,0,_wb)
{
if(_GET_BIT(_B,_p))
_RESET_BIT(b,_p);
else
_SET_BIT(b,_p);
if(!_MOD((++_p),8))
{
fwrite(&b,sizeof(u8),1,fp_out);
_p = 0;
}
}
__ch = fgetc(fp_in);
}
if(_p)
fwrite(&b,sizeof(u8),1,fp_out);
fclose(fp_out);
fclose(fp_in);
}
解压缩
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#ifndef nullptr_t
#define nullptr_t NULL
#endif
#define _TOT (1<<8)
#define _MASK ((1<<3)-1)
#define for(_iter,_beg,_end) \
for((_iter) = (_beg);(_iter) < (_end);++(_iter))
#define _GET_BIT(b,p) \
( !( (b) & ( 1 << ( (p) ^ _MASK ) ) == 0 ) )
#define _MOD(a,b) \
((a) & ((b)-1))
static const char *DOT = ".";
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef struct _HUFF{
struct _HUFF* _lft,
* _rght;
u8 _ch;
} HUFF;
static u64 *r_freq(size_t *fp_d,char *src,char **suf);
static HUFF *estab(u64 *map);
static void uncmpr(HUFF *h,char *src,char *dst,size_t fp_d);
static void destr(HUFF *r);
int main(int argc,char *argv[])
{
char *src = nullptr_t,
*dst = nullptr_t,
*suf = nullptr_t;
size_t fp_d = 0L;
u64 *map = nullptr_t;
HUFF *h = nullptr_t;
src = argv[1];
map = r_freq(&fp_d,src,&suf);
assert((!map) || "[error]:map null");
dst = (argc == 3)?
argv[2]:
strcat(strtok(src,DOT),suf);
h = estab(map);
assert((!h) || "[error]:h null");
uncmpr(h,src,dst,fp_d);
destr(h);
assert(h || "[error]:h not null");
if(map)
{
free(map);
map = nullptr_t;
}
return 0;
}
static u64 *r_freq(size_t *fp_d,char *src,char **suf)
{
u64 *map = nullptr_t;
FILE* fp_in = nullptr_t;
u8 suf_len = 0;
u8 diff = 0;
u8 ch = 0;
u8 l = 0,
buf_l = 0;
u8 c = 0;
u64 b = 0;
register int i = 0,j = 0;
fp_in = fopen(src,"rb");
assert((!fp_in) || "[error]:src falid");
fseek(fp_in,0,SEEK_SET);
fread(&suf_len,sizeof(u8),1,fp_in);
fread((*suf),sizeof(char),suf_len+1,fp_in);
fread(&diff,sizeof(u8),1,fp_in);
map = (u64*)malloc(_TOT*sizeof(u64));
memset(map,-1,sizeof(map));
b = 0;
for(i,0,diff)
{
fread(&l,sizeof(u8),1,fp_in);
fread(&c,sizeof(u8),1,fp_in);
b<<=(l-buf_l);
buf_l = l;
for(j,0,c)
{
fread(&ch,sizeof(u8),1,fp_in);
map[ch] = b++;
}
}
*fp_d = ftell(fp_in);
fclose(fp_in);
return map;
}
static void ins(HUFF **r,u64 b,u8 ch)
{
if(b)
{
(*r) = (HUFF*)malloc(sizeof(HUFF));
(*r)->_lft = nullptr_t;
(*r)->_rght = nullptr_t;
(*r)->_ch = ch;
return;
}
if(b&1)
ins(&((*r)->_rght),b>>1,ch);
else
ins(&((*r)->_lft),b>>1,ch);
}
static HUFF *estab(u64 *map)
{
register int i = 0;
HUFF *h = nullptr_t;
h = (HUFF *)malloc(sizeof(HUFF));
h->_lft = nullptr_t;
h->_rght = nullptr_t;
h->_ch = 0;
for(i,0,_TOT)
if(!(map[i] == -1))
ins(&h,map[i],(u8)i);
return h;
}
static void uncmpr(HUFF *h,char *src,char *dst,size_t fp_d)
{
u8 ch = 0;
u8 i = 0;
u64 cnt_b = 0L;
HUFF *p = h;
FILE *fp_out = nullptr_t;
FILE *fp_in = nullptr_t;
fp_out = fopen(dst,"wb");
assert((!fp_out) || "[error]:dst failed");
fp_in = fopen(src,"rb");
assert((!fp_in) || "[error]:src failed");
fseek(fp_in,0L,SEEK_END);
cnt_b = ftell(fp_in);
fseek(fp_in,fp_d,SEEK_SET);
fread(&ch,sizeof(u8),1,fp_in);
while(!(ftell(fp_in) == cnt_b))
{
if(!(p->_lft) && !(p->_rght))
{
fwrite(&(p->_ch),sizeof(u8),1,fp_out);
p = h;
}
if(_GET_BIT(ch,i))
p = p->_lft;
else
p = p->_rght;
if(!_MOD(++i,8))
{
i = 0;
ch = 0;
fread(&ch,sizeof(u8),1,fp_in);
}
}
fclose(fp_in);
fclose(fp_out);
}
static void destr(HUFF *r)
{
if(r)
{
destr(r->_lft);
destr(r->_rght);
free(r);
}
r = nullptr_t;
}