Skip to content

Instantly share code, notes, and snippets.

@risico
Created September 5, 2012 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save risico/3635159 to your computer and use it in GitHub Desktop.
Save risico/3635159 to your computer and use it in GitHub Desktop.
U0 ArcExpandBuf(ArcCs *c)
//Use ExpandBuf() unless you know what
//you're doing.
{
U8 *dst_ptr,*dst_limit;
U64 basecode,lastcode,code;
ArcTableEntry *temp,*temp1;
dst_ptr=c->dst_buf+c->dst_pos;
dst_limit=c->dst_buf+c->dst_size;
while (dst_ptr<dst_limit &&
c->stk_ptr!=c->stk_base)
*dst_ptr++ = * -- c->stk_ptr;
if (c->stk_ptr==c->stk_base && dst_ptr<dst_limit) {
if (c->saved_basecode==MAX_U32) {
lastcode=BFieldExtU32(c->src_buf,c->src_pos,
c->next_bits_in_use);
c->src_pos+=c->next_bits_in_use;
*dst_ptr++=lastcode;
ArcGetTableEntry(c);
c->last_ch=lastcode;
} else
lastcode=c->saved_basecode;
while (dst_ptr<dst_limit &&
c->src_pos+c->next_bits_in_use<=c->src_size) {
basecode=BFieldExtU32(c->src_buf,c->src_pos,
c->next_bits_in_use);
c->src_pos+=c->next_bits_in_use;
if (c->cur_entry==&c->compress[basecode]) {
*c->stk_ptr++=c->last_ch;
code=lastcode;
} else
code=basecode;
while (code>=c->min_table_entry) {
*c->stk_ptr++=c->compress[code].ch;
code=c->compress[code].basecode;
}
*c->stk_ptr++=code;
c->last_ch=code;
c->entry_used=TRUE;
temp=c->cur_entry;
temp->basecode=lastcode;
temp->ch=c->last_ch;
temp1=&c->hash[lastcode];
temp->next=temp1->next;
temp1->next=temp;
ArcGetTableEntry(c);
while (dst_ptr<dst_limit && c->stk_ptr!=c->stk_base)
*dst_ptr++ = * -- c->stk_ptr;
lastcode=basecode;
}
c->saved_basecode=lastcode;
}
c->dst_pos=dst_ptr-c->dst_buf;
}
ArcCs *ArcCsNew(BoolI8 expand,BoolI8 text_only)
{
ArcCs *c;
c=CAlloc(sizeof(ArcCs));
if (expand) {
c->stk_base=MAlloc(ARC_MAX_TABLE_ENTRY+1);
c->stk_ptr=c->stk_base;
}
if (text_only)
c->min_bits=7;
else
c->min_bits=8;
c->min_table_entry=1<<c->min_bits;
c->free_index=c->min_table_entry;
c->next_bits_in_use=c->min_bits+1;
c->free_limit=1<<c->next_bits_in_use;
c->saved_basecode=MAX_U32;
c->entry_used=TRUE;
ArcGetTableEntry(c);
c->entry_used=TRUE;
return c;
}
U0 ArcCsDel(ArcCs *c)
{
Free(c->stk_base);
Free(c);
}
ArcCompressStruct *CompressBuf(U8 *src,U64 size,
U64 flags=0,TaskStruct *mem_task=NULL)
{
U64 size_out;
ArcCompressStruct *result;
BoolI8 text_only=ArcDetermineCompressionType(src,size)==CT_7_BIT;
ArcCs *c=ArcCsNew(FALSE,text_only);
c->src_size=size;
c->src_buf=src;
c->dst_size=(size+sizeof(ArcCompressStruct))<<3;
c->dst_buf=CAlloc(c->dst_size>>3);
c->dst_pos=sizeof(ArcCompressStruct)<<3;
ArcCompressBuf(c);
ArcFinishCompression(c);
if (c->src_pos==c->src_size) {
size_out=(c->dst_pos+7)>>3;
result=MAlloc(size_out,mem_task);
MemCpy(result,c->dst_buf,size_out);
result->compression_type=text_only ? CT_7_BIT:CT_8_BIT;
result->compressed_size=size_out;
} else {
result=MAlloc(size+sizeof(ArcCompressStruct),mem_task);
MemCpy(&result->body,src,size);
result->compression_type=CT_NONE;
result->compressed_size=size+sizeof(ArcCompressStruct);
}
result->expanded_size=size;
result->flags=flags;
Free(c->dst_buf);
ArcCsDel(c);
return result;
}
U8 *ExpandBuf(ArcCompressStruct *r,TaskStruct *mem_task=NULL)
{
ArcCs *c;
U8 *result;
BoolI8 text_only;
result=MAlloc(r->expanded_size+1,mem_task);
result[r->expanded_size]=0; //terminate
text_only= r->compression_type==CT_7_BIT;
if (r->compression_type==CT_NONE) {
MemCpy(result,&r->body,r->expanded_size);
goto expand_end;
}
c=ArcCsNew(TRUE,text_only);
c->src_size=r->compressed_size<<3;
c->src_pos=sizeof(ArcCompressStruct)<<3;
c->src_buf=r;
c->dst_size=r->expanded_size;
c->dst_buf=result;
c->dst_pos=0;
ArcExpandBuf(c);
ArcCsDel(c);
expand_end:
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment