/*
RDLE
this include file has
2 functions :
rdle() : compresses a
memory area
unrdle() : uncompresses
a memory area
rdautel@geocities.com
*/
#include
#include
#include
#define ITS_OK
0 /* no error */
#define BAD_DATA
1 /* unexpected end of data */
#define NO_MEM
2 /* memory allocation failure */
/*
rdle()
this function compresses
an existing memory area
and copies it into a
compressed memory area
which is allocated into
the function, do not forget the free()
lgi : size of the existing
memory area in input
dti : pointer to the
existing memory area
lgo : contains the size
of the compressed memory size in output
dto : contains the pointer
to the compressed memory area in output, do
not forget the free()
returns the error code
*/
int rdle(int lgi,char
*dti,int *lgo,char **dto)
{
unsigned
char n=0,m=0;
int sblk=2+lgi/2;
*lgo=0;
if(!lgi)
return ITS_OK;
if(lgi==1)
{
*lgo=2;
*dto=(char *)malloc(2);
**dto=0;
*(*dto+1)=*dti;
return ITS_OK;
}
if(!(*dto=(char
*)malloc(sblk)))
return NO_MEM;
for(--lgi;--lgi;++dti)
{
if(*lgo>=sblk)
{
if(!(*dto=(char
*)realloc(*dto,sblk<<=1)))
return NO_MEM;
}
if(*dti!=*(dti+1)||*(dti+1)!=*(dti+2))
{
if(n)
{
*(*dto+(*lgo)++)=n|128;
*(*dto+(*lgo)++)=*dti;
n=0;
}
else
{
*(*dto+(++*lgo))=*dti;
if(++m==128)
{
*(*dto+((*lgo)++-128))=127;
m=0;
}
}
}
else
{
if(m)
{
*(*dto+((*lgo)++-m))=m-1;
m=0;
n=1;
}
else
{
if(++n==128)
{
*(*dto+(*lgo)++)=255;
*(*dto+(*lgo)++)=*dti;
n=0;
}
}
}
}
if(m)
*(*dto+((*lgo)++-m))=m-1;
*(*dto+(*lgo)++)=n|128;
*(*dto+(*lgo)++)=*dti;
*(*dto+(*lgo)++)=0;
*(*dto+(*lgo)++)=*(dti+1);
*dto=(char
*)realloc(*dto,*lgo);
return
ITS_OK;
}
/*
unrdle()
this function uncompresses
a compressed memory area
and copies it into an
uncompressed memory area
which is allocated into
the function, do not forget the free()
lgi : size of the compressed
memory area in input
dti : pointer to the
compressed memory area
lgo : contains the size
of the uncompressed memory size in output
dto : contains the pointer
to the uncompressed memory area in output, do
not forget the free()
returns the error code
*/
int unrdle(int lgi,char
*dti,int *lgo,char **dto)
{
unsigned
char n;
int sblk=lgi*2;
if(!(*dto=(char
*)malloc(128+sblk)))
return NO_MEM;
for(*lgo=0;lgi;(*lgo)+=n)
{
if(*lgo>=sblk)
{
if(!(*dto=(char
*)realloc(*dto,128+(sblk<<=1))))
return NO_MEM;
}
if((n=*dti)&128)
{
n^=128;
memset((*dto)+*lgo,*++dti,++n);
lgi-=2;
++dti;
}
else
{
memcpy((*dto)+*lgo,++dti,++n);
lgi-=n+1;
dti+=n;
}
if(lgi<0)
return BAD_DATA;
}
*dto=(char
*)realloc(*dto,*lgo);
return
ITS_OK;
}
/*
the main() function
is just here to perform tests
*/
int main(int argc,char
**argv)
{
FILE *fd1,*fd2;
int code;
int lg1,lg2;
char *ch1,*ch2;
if(argc==4)
{
if(!(fd1=fopen(argv[2],"rb")))
{
puts("error input
file");
return 7;
}
if(!(fd2=fopen(argv[3],"wb")))
{
puts("error output
file");
fclose(fd1);
return 8;
}
switch(*argv[1])
{
case 'a' :
case 'A' :
fseek(fd1,0,SEEK_END);
lg1=ftell(fd1);
rewind(fd1);
ch1=(char *)malloc(lg1);
if(!ch1)
exit(23);
lg1=fread(ch1,1,lg1,fd1);
code=rdle(lg1,ch1,&lg2,&ch2);
if(!code)
{
fwrite(ch2,1,lg2,fd2);
free(ch1);
if(lg2)
free(ch2);
}
break;
case 'x' :
case 'X' :
fseek(fd1,0,SEEK_END);
lg1=ftell(fd1);
rewind(fd1);
ch1=(char *)malloc(lg1);
if(!ch1)
exit(23);
lg1=fread(ch1,1,lg1,fd1);
code=unrdle(lg1,ch1,&lg2,&ch2);
if(!code)
{
fwrite(ch2,1,lg2,fd2);
free(ch1);
if(lg2)
free(ch2);
}
break;
default :
code=9;
}
fclose(fd1);
fclose(fd2);
if(code!=9)
{
if(code)
printf("error %d\n",code);
return code;
}
}
puts("rdle
a file rlefile");
puts("rdle
x rlefile file");
return
9;
}
|