Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- zlz4c - permissive LZ4c handler
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #ifdef STANDALONE
- #define zlz4c main
- void write32(void *p, const unsigned int n){
- unsigned char *x=(unsigned char*)p;
- x[0]=n&0xff,x[1]=(n>>8)&0xff,x[2]=(n>>16)&0xff,x[3]=(n>>24)&0xff;
- }
- unsigned int read32(const void *p){
- const unsigned char *x=(const unsigned char*)p;
- return x[0]|(x[1]<<8)|(x[2]<<16)|(x[3]<<24);
- }
- #else
- #include "../compat.h"
- #endif
- #include "../lib/lz4/lz4.h"
- #include "../lib/lz4/xxhash.h"
- #define lz4s_magic 0x184D2204
- #define lz4s_legacy_magic 0x184C2102
- #define lz4s_legacy_blocksize 8*1024*1024
- //bitfield is LSB, on gcc/clang.
- typedef struct{
- //byte 0
- unsigned int dictionary: 1;
- unsigned int reserved1: 1;
- unsigned int stream_checksum: 1;
- unsigned int stream_size: 1;
- unsigned int block_checksum: 1;
- unsigned int block_independence: 1;
- unsigned int version: 2;
- //byte 1
- unsigned int reserved3: 4;
- unsigned int blocksize_id: 3;
- unsigned int reserved2: 1;
- } lz4s_descriptor;
- #define lz4s_getblocksize_fromid(n) (1<<(8+(2*(n))))
- #define lz4s_skippable_block(n) (((n)&0xfffffff0)==0x184d2a50)
- static int encode_file(FILE *fin,FILE *fout){
- unsigned char buf[4];
- write32(buf,lz4s_magic);
- fwrite(buf,1,4,fout);
- lz4s_descriptor *desc=buf;
- desc->version=1;
- desc->dictionary=0;
- desc->reserved1=0;
- desc->reserved2=0;
- desc->reserved3=0;
- desc->stream_size=0;
- desc->block_checksum=1;
- desc->stream_checksum=1;
- desc->block_independence=1; //gee
- desc->blocksize_id=7; ///
- fwrite(buf,1,2,fout);
- void *ctx=XXH32_init(0);
- XXH32_update(ctx,buf,2);
- fputc((XXH32_digest(ctx)>>8)&0xff,fout);
- //parsed header. entering data block.
- void *ctx_stream=XXH32_init(0);
- unsigned int blocksize=lz4s_getblocksize_fromid(desc->blocksize_id);
- unsigned int size_max=blocksize+(blocksize>>1);
- unsigned char *pc=malloc(size_max);
- unsigned char *pd=malloc(blocksize/*+65536*/);
- int readlen;
- for(;readlen=fread(pd,1,blocksize,fin);){
- XXH32_update(ctx_stream,pd,readlen);
- int clen=LZ4_compress(pd,pc,readlen);
- void *ctx_block=XXH32_init(0);
- if(clen>=blocksize){
- unsigned int size=readlen;
- write32(buf,size|0x80000000);
- fwrite(buf,1,4,fout);
- fwrite(pd,1,readlen,fout);
- XXH32_update(ctx_block,pd,readlen);
- }else{
- write32(buf,clen);
- fwrite(buf,1,4,fout);
- fwrite(pc,1,clen,fout);
- XXH32_update(ctx_block,pc,clen);
- }
- write32(buf,XXH32_digest(ctx_block));
- fwrite(buf,1,4,fout);
- }
- write32(buf,0);
- fwrite(buf,1,4,fout);
- write32(buf,XXH32_digest(ctx_stream));
- fwrite(buf,1,4,fout);
- return 0;
- }
- static int decode_file(FILE *fin,FILE *fout){
- unsigned char buf[15],hash[4];
- unsigned int ihash;
- if(fread(buf,1,4,fin)<4)return 1;
- if(read32(buf)==lz4s_legacy_magic){
- unsigned char *pd=malloc(lz4s_legacy_blocksize);
- for(;fread(buf,1,4,fin)==4;){
- unsigned char *pc=malloc(read32(buf));
- if(fread(pc,1,read32(buf),fin)<read32(buf))return 1;
- int dlen=LZ4_decompress_safe(pc,pd,read32(buf),lz4s_legacy_blocksize);
- if(dlen<0)return 3;
- fwrite(pd,1,dlen,fout);
- free(pc);
- }
- free(pd);
- }else{
- do{
- if(lz4s_skippable_block(read32(buf))){
- if(fread(buf,1,4,fin)<4)return 1;
- int i=0;
- for(;i<read32(buf);i++)fgetc(fin);
- }else if(read32(buf)==lz4s_magic){
- if(fread(buf,1,2,fin)<2)return 1;
- int descriptor_size=2;
- lz4s_descriptor *desc=buf;
- if(
- desc->version!=1 ||
- desc->dictionary!=0 ||
- desc->reserved1!=0 ||
- desc->reserved2!=0 ||
- desc->reserved3!=0
- )return 4;
- if(desc->stream_size){
- if(fread(buf+descriptor_size,1,8,fin)<8)return 1;
- descriptor_size+=8;
- }
- if(desc->dictionary){
- if(fread(buf+descriptor_size,1,4,fin)<4)return 1;
- descriptor_size+=4;
- }
- if(fread(buf+descriptor_size,1,1,fin)<1)return 1;
- void *ctx=XXH32_init(0);
- XXH32_update(ctx,buf,descriptor_size);
- if(((XXH32_digest(ctx)>>8)&0xff)!=buf[descriptor_size])return 2;
- unsigned int blocksize=lz4s_getblocksize_fromid(desc->blocksize_id);
- int block_checksum=desc->block_checksum;
- int block_independence=desc->block_independence;
- int stream_checksum=desc->stream_checksum;
- typedef int (*T_decompressor)(const char*,char*,int,int);
- T_decompressor decompressor=block_independence?LZ4_decompress_safe:LZ4_decompress_safe_withPrefix64k;
- //parsed header. entering data block.
- void *ctx_stream=XXH32_init(0);
- unsigned int size_max=blocksize;
- unsigned char *pc=malloc(size_max);
- unsigned char *pd=malloc(blocksize+65536);
- int bufsiz=0;
- for(;;){
- if(fread(buf,1,4,fin)<4)return 1;
- unsigned int size=read32(buf);
- int flag=size>>31;
- size&=0x7fffffff;
- if(size==0)break;
- //read data.
- void *ctx_block=XXH32_init(0);
- if(size>size_max){
- size_max=size;
- free(pc);
- pc=malloc(size_max);
- }
- if(fread(pc,1,size,fin)<size)return 1;
- XXH32_update(ctx_block,pc,size);
- ihash=XXH32_digest(ctx_block);
- if(block_checksum){
- if(fread(hash,1,4,fin)<4)return 1;
- if(read32(hash)!=ihash)return 2;
- }
- int dlen;
- if(flag==1){
- dlen=size;
- memcpy(pd+bufsiz,pc,size);
- }else{
- dlen=decompressor(pc,pd+bufsiz,read32(buf),blocksize);
- if(dlen<0)return 3;
- }
- XXH32_update(ctx_stream,pd+bufsiz,dlen);
- bufsiz+=dlen;
- if(bufsiz>65536){
- fwrite(pd,1,bufsiz-65536,fout);
- memmove(pd,pd+bufsiz-65536,65536);
- bufsiz=65536;
- }
- }
- fwrite(pd,1,bufsiz,fout);
- free(pd);
- free(pc);
- //processed all data blocks.
- ihash=XXH32_digest(ctx_stream);
- if(stream_checksum){
- if(fread(hash,1,4,fin)<4)return 1;
- if(read32(hash)!=ihash)return 2;
- }
- }else return 2;
- }while(fread(buf,1,4,fin)==4);
- }
- return 0;
- }
- int zlz4c(const int argc, const char **argv){
- int i;
- if(isatty(fileno(stdin))&&isatty(fileno(stdout))){
- fprintf(stderr,"zlz4c 140629 - permissive LZ4c handler\n");
- fprintf(stderr,"zlz4c [d] < in > out\n");
- return -1;
- }
- if(argc>1){
- i=decode_file(stdin,stdout);
- switch(i){
- case 0: fprintf(stderr,"Everything is Ok\n");break;
- case 1: fprintf(stderr,"Unexpected EOF\n");break;
- case 2: fprintf(stderr,"File Corrupted\n");break;
- case 3: fprintf(stderr,"Decode Error\n");break;
- case 4: fprintf(stderr,"Format Unsupported\n");break;
- default: fprintf(stderr,"Unknown Error\n");
- }
- return i;
- }else{
- return encode_file(stdin,stdout);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment