Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************** bZip *****************************************************************/
- typedef struct bZipEntry{bString filename;uint64_t size,offset;}bZipEntry;
- void bZipEntryFree(bZipEntry *entry);
- int bZipEntryCollate(bZipEntry *l,bZipEntry *r);
- bDECLARE_INDEX(bIndexZipEntry,bZipEntry);
- typedef struct bZipFile{bFile f;bIndexZipEntry entries;int error;}bZipFile;
- #define bZIP_ERROR_FILEERROR 1
- #define bZIP_ERROR_A 2
- #define bZIP_ERROR_B 3
- #define bZIP_ERROR_C 4
- #define bZIP_ERROR_D 5
- void bZipFileFree(bZipFile *z);
- bZipFile bZipFileFrom(char *filename);
- int bZipExtract(bZipFile *zip,char *name,char *dest);
- int bZipAdd(bZipFile *zip,char *file,char *name);
- #if defined(ZIB_IMPLEMENTATION)||defined(__CLION_IDE__)
- #define bBUFSIZE 4194304
- void bZipEntryFree(bZipEntry *entry){bStringFree(&entry->filename);}
- int bZipEntryCollate(bZipEntry *l,bZipEntry *r){return bCollateStringFast(&l->filename,&r->filename);}
- bDEFINE_INDEX(bIndexZipEntry,bZipEntry,bZipEntryCollate,bZipEntryFree);
- void bZipRead64(bString extra,uint64_t *size,uint64_t *compressedsize,uint64_t *offset){
- for(unsigned i=0,j,id,datasize=0;extra.size>4&&i<extra.size-4;i+=bMax(datasize+4,4)){
- id=bStringReadUint16(extra,i),datasize=bStringReadUint16(extra,i+2);
- if(j=4,datasize!=0&&id==1){
- if(size&&*size==4294967295)*size=bStringReadUint64(extra,j),j+=8;
- if(compressedsize&&*compressedsize==4294967295)*compressedsize=bStringReadUint64(extra,j),j+=8;
- if(offset&&*offset==4294967295)*offset=bStringReadUint64(extra,j);
- return;
- }
- }
- }
- bString bZipMakeFilename(char *filename,unsigned len){
- bString fn=bStringFrom(filename,len);
- if(fn.data[1]==':')bStringErase(&fn,0,3);
- if(fn.data[0]=='/')bStringErase(&fn,0,1);
- for(unsigned i=0;i<fn.size;i++)if(fn.data[i]=='\\')fn.data[i]='/';
- memset(fn.data+(fn.size=bMin(65535,fn.size)),0,ARRAY_EXTRA);
- return fn;
- }
- void bZipReadExtraTime(bString extra,bDatetime *created,bDatetime *modified,bDatetime *accessed){
- for(unsigned i=0,j,id,datasize=0;extra.size>4&&i<extra.size-4;i+=bMax(datasize+4,4)){
- id=bStringReadUint16(extra,i),datasize=bStringReadUint16(extra,i+2);
- if(j=4,datasize!=0&&id==215891){
- *modified=bDatetimeFromUnix(bStringReadUint32(extra,i+j+1));
- }else if(datasize==32&&id==10){
- *modified=bDatetimeFromWinFiletime(bStringReadUint64(extra,i+j+8));
- *accessed=bDatetimeFromWinFiletime(bStringReadUint64(extra,i+j+16));
- *created=bDatetimeFromWinFiletime(bStringReadUint64(extra,i+j+24));
- }
- }
- }
- void bZipFindCD(bZipFile *z,uint64_t *cd,uint64_t *cdend,uint64_t *cd64end,uint64_t *cdend64loc){
- if(z->error)return;
- unsigned p,i=101010256;
- uint64_t filesize,offs=(filesize=bFileGetSize(&z->f))-111111;
- if(filesize==0)return;
- if(offs>filesize)offs=0;
- bFileSetCursor(&z->f,offs);
- bString *r=bFileRead(&z->f,111111);
- if(r->size<20){z->error=z->f.error?bZIP_ERROR_FILEERROR:bZIP_ERROR_A;return;}
- for(p=r->size-20;p<r->size;p--)if(bStringReadUint32(*r,p)==i&&bStringReadUint32(*r,p+4)==0)break;
- if(p>=r->size){z->error=bZIP_ERROR_A;return;}
- *cd=bStringReadUint32(*r,p+16),*cdend=offs+p;
- if(*cd==4294967295){
- while(p--<r->size)if(bStringReadUint32(*r,p)==117853008&&bStringReadUint32(*r,p+4)==0)break;
- *cdend64loc=p+offs,*cd64end=bStringReadUint64(*r,p+8),p=(*cd64end-offs),*cd=bStringReadUint64(*r,p+48);
- }
- }
- void bZipFileFree(bZipFile *z){
- bIndexZipEntryFree(&z->entries);
- bFileFree(&z->f);
- memset(z,0,sizeof(*z));
- }
- bZipFile bZipFileFrom(char *filename){
- bZipFile z={.f=bFileFrom(filename,bFILE_READ|bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS)};
- if(z.f.error)bFileFree(&z.f),z.f=bFileFrom(filename,bFILE_READ);
- if(z.f.error)return bFileFree(&z.f),z.error=bZIP_ERROR_FILEERROR,z;
- uint64_t cd=(unsigned)-1,cdend=(unsigned)-1,cd64end=(unsigned)-1,cd64endloc=(unsigned)-1;
- bZipFindCD(&z,&cd,&cdend,&cd64end,&cd64endloc);
- bFileSetCursor(&z.f,cd);
- for(;;){
- bString *r=bFileRead(&z.f,46);
- if(bStringReadUint32(*r,0)!=33639248)break;
- uint64_t sz=bStringReadUint32(*r,24),csz=bStringReadUint32(*r,20),off=bStringReadUint32(*r,42);
- unsigned fnlen=bStringReadUint16(*r,28),exln=bStringReadUint16(*r,30),commln=bStringReadUint16(*r,32);
- bString fn=bZipMakeFilename((char*)bFileRead(&z.f,fnlen)->data,fnlen),*extra=bFileRead(&z.f,exln);
- bZipRead64(*extra,&sz,&csz,&off);
- bFileRead(&z.f,commln);
- bIndexZipEntryAdd(&z.entries,(bZipEntry){.size=sz,.filename=fn,.offset=off});
- }
- return z;
- }
- int bZipExtract(bZipFile *zip,char *name,char *dest){
- int ret=0;
- bString fn=bStringFrom(name,0);
- unsigned idx=bIndexZipEntryFindIndex(zip->entries,(bZipEntry){.filename=fn},0);
- bStringFree(&fn);
- if(idx==(unsigned)-1)return ret;
- bZipEntry entry=zip->entries.data[idx];
- bFileSetCursor(&zip->f,entry.offset);
- bFileReadUint64(&zip->f);
- unsigned metod=bFileReadUint16(&zip->f),t=bFileReadUint16(&zip->f),d=bFileReadUint16(&zip->f),
- c=bFileReadUint32(&zip->f),c2=0;
- bDatetime created=bDatetimeNow(),modified=bDatetimeFromDOS(t,d),accessed=bDatetimeNow();
- uint64_t compressedsize=bFileReadUint32(&zip->f),uncompressedsize=bFileReadUint32(&zip->f);
- unsigned filenamelen=bFileReadUint16(&zip->f),extralen=bFileReadUint16(&zip->f);
- bFileRead(&zip->f,filenamelen);
- bString *extra=bFileRead(&zip->f,extralen);
- bZipRead64(*extra,&uncompressedsize,&compressedsize,NULL);
- bZipReadExtraTime(*extra,&created,&modified,&accessed);
- bString *in,outbuf=bStringFrom(0,bBUFSIZE);
- bFile out=bFileFrom(dest,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS|bFILE_OVERWRITE);
- switch(metod){
- case 0:{
- while(compressedsize!=0){
- in=bFileRead(&zip->f,(unsigned)(bMin(compressedsize,bBUFSIZE)));
- bFileWrite(&out,in->data,in->size);
- c2=bCrc32(c,in->data,in->size),compressedsize-=in->size;
- }
- break;
- }
- case 8:{
- z_stream stream={0};
- inflateInit2(&stream,-15);
- do{
- if(compressedsize==0)break;
- compressedsize-=(in=bFileRead(&zip->f,(unsigned)(bMin(bBUFSIZE,compressedsize))))->size;
- if((stream.avail_in=in->size)==0)break;
- stream.next_in=in->data;
- do{
- stream.avail_out=bBUFSIZE,stream.next_out=outbuf.data;
- if((ret=inflate(&stream,Z_NO_FLUSH))<0&&ret!=Z_BUF_ERROR)break(compressedsize=0);
- outbuf.size=bBUFSIZE-stream.avail_out;
- bFileWrite(&out,outbuf.data,outbuf.size);
- c2=bCrc32(c2,(char*)outbuf.data,outbuf.size);
- }while(stream.avail_out==0);
- }while(ret!=Z_STREAM_END);
- /*ret=*/inflateEnd(&stream);
- break;
- }
- #if defined bUSE_BZIP2
- case 12:{
- bz_stream strm={0};
- if(BZ2_bzDecompressInit(&strm,0,0)!=BZ_MEM_ERROR){
- for(int fin=0;!fin;){
- in=bFileRead(&zip->f,bBUFSIZE),strm.avail_in=in->size,strm.next_in=(char*)in->data;
- if(strm.avail_in==0)break;
- do{
- strm.avail_out=bBUFSIZE,strm.next_out=(char*)outbuf.data;
- if((ret=BZ2_bzDecompress(&strm))==BZ_STREAM_END)fin=1;
- else if(ret!=BZ_OK)break(fin=1);
- bFileWrite(&out,outbuf.data,bBUFSIZE-strm.avail_out);
- }while(strm.avail_in>0||strm.avail_out==0);
- }
- BZ2_bzDecompressEnd(&strm);
- }
- break;
- }
- #endif
- #if defined bUSE_LZMA
- case 14:{
- uint16_t ver=bFileReadUint16(&zip->f),propsize=bFileReadUint16(&zip->f);
- if(compressedsize<=(4+propsize))break;
- in=bFileRead(&zip->f,5),compressedsize-=(4+propsize);
- CLzmaDec state={0};
- LzmaDec_Construct(&state);
- if((ret=LzmaDec_Allocate(&state,in->data,propsize,&g_Alloc))!=SZ_OK)break;
- LzmaDec_Init(&state);
- ELzmaStatus status;
- while(compressedsize>0){
- SizeT inSize=(SizeT)bMin(bBUFSIZE,compressedsize),srcPos=0;
- in=bFileRead(&zip->f,(unsigned)inSize),compressedsize-=inSize;
- while(srcPos<in->size){
- SizeT srcLen=in->size-srcPos,destLen=outbuf.capacity;
- ret=LzmaDec_DecodeToBuf(&state,outbuf.data,&destLen,in->data+srcPos,&srcLen,
- (compressedsize==0&&srcPos+srcLen==in->size)?LZMA_FINISH_END:LZMA_FINISH_ANY,&status);
- if(ret!=SZ_OK&&ret!=SZ_ERROR_DATA)break;
- bFileWrite(&out,outbuf.data,destLen);
- c2=bCrc32(c2,outbuf.data,(unsigned)destLen),srcPos+=srcLen;
- if(srcLen==0&&destLen==0)break;
- }
- }
- LzmaDec_Free(&state,&g_Alloc);
- break;
- }
- #endif
- default:{
- ret=bZIP_ERROR_C;
- break;
- }
- }
- ret=c==c2?0:ret?ret:bZIP_ERROR_D;
- bStringFree(&outbuf);
- bFileFree(&out);
- return ret;//meaningless
- return bZIP_ERROR_B;
- }
- int bZipAdd(bZipFile *zip,char *file,char *name){
- bFile compressed=bFileTempFile();
- int ret=bZlibCompressFile(file,(char*)compressed.name.data,0,0,6);
- uint32_t crc=0;
- bString *r;
- bFile uncompressed=bFileFrom(file,bFILE_READ);
- while((r=bFileRead(&uncompressed,4194304))->size)crc=bCrc32(crc,r->data,r->size);
- bFileinfo fileinfo=bFileinfoStatic(file);
- uint64_t csize64=bFileGetSize(&compressed),usize64=fileinfo.size,cd=0,cdend=0,cd64end=0,cd64endloc=0;
- bZipFindCD(zip,&cd,&cdend,&cd64end,&cd64endloc);
- bDatetime mod=fileinfo.modified;
- uint32_t fmod=(mod.year-1980)<<25|mod.month<<21|mod.day<<16|mod.hour<<11|mod.min<<5|(mod.sec/2);
- bString loc=bStringFrom((char[30]){80,75,3,4,20,0,0,0,8},30),ex={0};loc.size=30;
- bString fn=bZipMakeFilename(name,bStrlen(name));
- uint32_t csize32=(unsigned)bMin(4294967295,csize64),usize32=(unsigned)bMin(4294967295,usize64);
- uint16_t fnlen=fn.size,entries32=zip->entries.items+1;
- int want64=csize64>4294967295||usize64>4294967295||bFileGetSize(&zip->f)>4294967295||cd64end!=0;
- if(want64&&(loc.data[4]=45,loc.data[28]=28,ex=bStringFrom((char[28]){1,0,24},28),1))
- ex.size=28,memcpy(ex.data+4,&usize64,8),memcpy(ex.data+12,&csize64,8);
- memcpy(loc.data+10,&fmod,4),memcpy(loc.data+14,&crc,4);
- memcpy(loc.data+18,&csize32,4),memcpy(loc.data+22,&usize32,4),memcpy(loc.data+26,&fnlen,2);
- bStringAdd(&loc,(char*)fn.data,fn.size);
- bString centralheader=bStringFrom(loc.data,loc.size);
- if(ex.size)bStringAdd(&loc,ex.data,ex.size);
- centralheader.data[2]=1,centralheader.data[3]=2;
- bStringInsert(¢ralheader,"\055",2,4),bStringInsert(¢ralheader,(char[14]){0},14,32);
- uint32_t offs32=cd>4294967295?(uint32_t)-1:cd;
- memcpy(centralheader.data+42,&offs32,4);
- if(ex.size&&(centralheader.data[30]=12,ex.data[2]=8,ex.size=12,memcpy(ex.data+4,&cd,8),1))
- bStringAdd(¢ralheader,(char*)ex.data,ex.size);
- bFileSetCursor(&zip->f,cd);
- r=bFileRead(&zip->f,(unsigned)((cd64end==0?cdend:cd64end)-cd));
- bString oldcentraldir=bStringFrom((char*)r->data,r->size),endofcd=bStringFrom((char[22]){80,75,5,6},22);
- bFileSetCursor(&zip->f,cd);
- bFileWrite(&zip->f,loc.data,loc.size);
- bFileSetCursor(&compressed,0);
- while((r=bFileRead(&compressed,4194304))->size)bFileWrite(&zip->f,r->data,r->size);
- uint64_t newcd=bFileGetCursor(&zip->f);
- bFileWrite(&zip->f,oldcentraldir.data,oldcentraldir.size);
- bFileWrite(&zip->f,centralheader.data,centralheader.size);
- if(want64){
- uint64_t newentries=zip->entries.items+1,newcdsize=oldcentraldir.size+centralheader.size;
- bString z64loc=bStringFrom((char[20]){80,75,6,7},20);z64loc.data[16]=1;
- bString z64=bStringFrom((char[56]){80,75,6,6,44,0,0,0,0,0,0,0,45,0,45},56);
- memcpy(z64.data+24,&newentries,8),memcpy(z64.data+32,&newentries,8);
- memcpy(z64.data+40,&newcdsize,8),memcpy(z64.data+48,&newcd,8);
- uint64_t z64l=bFileGetCursor(&zip->f);
- memcpy(z64loc.data+8,&z64l,8);
- bFileWrite(&zip->f,z64.data,z64.size),bFileWrite(&zip->f,z64loc.data,z64loc.size);
- bStringFree(&z64),bStringFree(&z64loc);
- }
- uint32_t newcdsize32=oldcentraldir.size+centralheader.size,newcd32=newcd>65535?(uint32_t)-1:newcd;
- memcpy(endofcd.data+8,&entries32,2),memcpy(endofcd.data+10,&entries32,2);
- memcpy(endofcd.data+12,&newcdsize32,4),memcpy(endofcd.data+16,&newcd32,4);
- bFileWrite(&zip->f,endofcd.data,endofcd.size);
- if(zip->f.error||uncompressed.error||compressed.error)bLog("bZipAdd:smth went wwrong");//todo
- bIndexZipEntryAdd(&zip->entries,(bZipEntry){.size=usize64,.filename=fn,.offset=cd});
- bStringFree(&endofcd),bStringFree(&oldcentraldir),bStringFree(¢ralheader),bStringFree(&fn);
- bStringFree(&ex),bStringFree(&loc),bFileFree(&uncompressed),bFileFree(&compressed);
- return 0;
- }
- /******************************** bZlib ****************************************************************/
- #if bUSE_ZLIB
- bString bZlibUncompress(bString compressed,bString *dictionary);
- int bZlibUncompressFile(char *fileCompressed,char *fileUncompressed,bString *dictionary);
- bString bZlibCompress(bString uncompressed,bString *dictionary,int zlibHeader,int level/*0...9*/);
- int bZlibCompressFile(char *fileUncompressed,char *fileCompressed,bString *dictionary,int zlibHeader,
- int level/*0...9*/);
- #if defined(BEXT_IMPLEMENTATION)
- #define bZLIB_CHUNK 4194304
- bString bZlibUncompress(bString compressed,bString *dictionary){
- bString ret=bStringFrom(0,compressed.size*3);
- if(ret.capacity==(unsigned)-2||compressed.size<5)return ret;
- z_stream strm={.next_in=compressed.data,.avail_in=compressed.size};
- uint32_t header=*(bUnaligned32*)compressed.data,wb=47;
- if(!((!(header&7))&&(((header>>8)&255)!=(~(header>>24)&255)))&&(header&65535)!=35615)wb=-15;
- if(inflateInit2(&strm,wb)!=Z_OK)return ret;
- if(dictionary)inflateSetDictionary(&strm,dictionary->data,dictionary->size);
- while(1){
- bStringReserve(&ret,ret.size+compressed.size);
- if(ret.capacity==(unsigned)-2)return inflateEnd(&strm),bStringFree(&ret),ret;
- strm.next_out=ret.data+ret.size,strm.avail_out=compressed.size;
- int rc=inflate(&strm,Z_FINISH);
- ret.size+=compressed.size-strm.avail_out;
- if(rc==Z_STREAM_END)return inflateEnd(&strm),memset(ret.data+ret.size,0,ARRAY_EXTRA),ret;
- else if(rc==Z_NEED_DICT&&dictionary)inflateSetDictionary(&strm,dictionary->data,dictionary->size),
- dictionary=0;
- else if(rc!=Z_OK&&rc!=Z_BUF_ERROR)return inflateEnd(&strm),bStringFree(&ret),ret;
- }
- }
- int bZlibUncompressFile(char *fileCompressed,char *fileUncompressed,bString *dictionary){
- bFile in=bFileFrom(fileCompressed,bFILE_READ),
- out=bFileFrom(fileUncompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
- z_stream strm={0};
- uint32_t header=bFileReadUint32(&in),wb=47;
- if(!((!(header&7))&&(((header>>8)&255)!=(~(header>>24)&255)))&&(header&65535)!=35615)wb=-15;
- bFileSetCursor(&in,0);
- bString outbuf=bStringFrom(0,bZLIB_CHUNK);
- int ret=inflateInit2(&strm,wb);
- if(ret!=Z_OK||((in.error||out.error||outbuf.capacity==-2)&&(ret=-7)))goto zout;
- if(dictionary)inflateSetDictionary(&strm,dictionary->data,dictionary->size);
- do{
- bString *inbuf=bFileRead(&in,bZLIB_CHUNK);
- if((strm.avail_in=inbuf->size)==0)break;
- strm.next_in=inbuf->data;
- do{
- strm.avail_out=bZLIB_CHUNK,strm.next_out=outbuf.data;
- switch((ret=inflate(&strm,Z_FINISH))){
- case Z_NEED_DICT:
- if(dictionary)break((inflateSetDictionary(&strm,dictionary->data,dictionary->size),dictionary=0));
- ret=Z_DATA_ERROR;
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- goto zout;
- }
- bFileWrite(&out,outbuf.data,bZLIB_CHUNK-strm.avail_out);
- }while(strm.avail_out==0||ret==Z_NEED_DICT);
- }while(ret!=Z_STREAM_END);
- zout:return inflateEnd(&strm),bStringFree(&outbuf),bFileFree(&out),bFileFree(&in),ret;
- }
- bString bZlibCompress(bString uncompressed,bString *dictionary,int zlibHeader,int level/*0...9*/){
- bString ret=bStringFrom(0,(unsigned)compressBound(uncompressed.size));
- if(ret.capacity==(unsigned)-2)return ret;
- z_stream strm={.next_in=uncompressed.data,.avail_in=uncompressed.size,.next_out=ret.data,
- .avail_out=ret.capacity};
- if(deflateInit2(&strm,level,Z_DEFLATED,zlibHeader?15:-15,9,Z_DEFAULT_STRATEGY)!=Z_OK)return ret;
- if(dictionary)deflateSetDictionary(&strm,dictionary->data,dictionary->size);
- return deflate(&strm,Z_FINISH),ret.size=strm.total_out,deflateEnd(&strm),ret;
- }
- int bZlibCompressFile(char *fileUncompressed,char *fileCompressed,bString *dictionary,int zlibHeader,
- int level/*0...9*/){
- bFile in=bFileFrom(fileUncompressed,bFILE_READ),
- out=bFileFrom(fileCompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
- bString outbuf=bStringFrom(0,bZLIB_CHUNK);
- z_stream strm={0};
- int ret=deflateInit2(&strm,Z_DEFAULT_COMPRESSION,Z_DEFLATED,zlibHeader?15:-15,9,Z_DEFAULT_STRATEGY);
- if(dictionary)deflateSetDictionary(&strm,dictionary->data,dictionary->size);
- if(in.error||out.error||ret!=Z_OK)goto zout;
- do{
- bString *inbuf=bFileRead(&in,bZLIB_CHUNK);
- strm.avail_in=inbuf->size,strm.next_in=inbuf->data;
- level=inbuf->size==0?Z_FINISH:Z_NO_FLUSH;
- do{
- strm.avail_out=bZLIB_CHUNK,strm.next_out=outbuf.data;
- ret=deflate(&strm,level);
- bFileWrite(&out,outbuf.data,bZLIB_CHUNK-strm.avail_out);
- if(ret==Z_NEED_DICT&&dictionary)deflateSetDictionary(&strm,dictionary->data,dictionary->size),
- dictionary=0;
- else if(out.error||ret==Z_STREAM_ERROR)goto zout;
- outbuf.size=0;
- }while(strm.avail_out==0);
- }while(level!=Z_FINISH);
- bAssert(ret==Z_STREAM_END);
- zout:return bStringFree(&outbuf),bFileFree(&out),bFileFree(&in),ret;
- }
- #endif //BEXT_IMPLEMENTATION
- #endif //bUSE_ZLIB
- /******************************** bBzip2 ***************************************************************/
- #if defined bUSE_BZIP2
- int bBzip2UncompressFile(char *fileCompressed,char *fileUncompressed);
- int bBzip2CompressFile(char *fileUncompressed,char *fileCompressed);
- bString bBzip2Compress(bString uncompressed,int level/*1...9*/);
- bString bBzip2Uncompress(bString compressed);
- #if defined BEXT_IMPLEMENTATION || defined __CLION_IDE__
- #define BZIP2_BUFFER 4096
- int bBzip2UncompressFile(char *fileCompressed,char *fileUncompressed){
- bFile in=bFileFrom(fileCompressed,bFILE_READ),
- out=bFileFrom(fileUncompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
- bString outstr=bStringFrom(0,BZIP2_BUFFER);
- bz_stream strm={0};
- int ret=0;
- if(BZ2_bzDecompressInit(&strm,0,0)==BZ_MEM_ERROR||in.error||out.error)goto bout;
- for(int fin=0;!fin;){
- bString *instr=bFileRead(&in,BZIP2_BUFFER);
- strm.avail_in=instr->size,strm.next_in=(char*)instr->data;
- if(strm.avail_in==0)break;
- do{
- strm.avail_out=BZIP2_BUFFER,strm.next_out=(char*)outstr.data;
- if((ret=BZ2_bzDecompress(&strm))==BZ_STREAM_END)fin=1;
- else if(ret!=BZ_OK)goto bout;
- bFileWrite(&out,outstr.data,BZIP2_BUFFER-strm.avail_out);
- }while(strm.avail_in>0||strm.avail_out==0);
- }
- bout:
- bStringFree(&outstr);
- BZ2_bzDecompressEnd(&strm);
- bFileFree(&out);
- bFileFree(&in);
- return ret;
- }
- int bBzip2CompressFile(char *fileUncompressed,char *fileCompressed){
- bFile in=bFileFrom(fileUncompressed,bFILE_READ),
- out=bFileFrom(fileCompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
- bString outstr=bStringFrom(0,BZIP2_BUFFER);
- bz_stream strm={0};
- if(BZ2_bzCompressInit(&strm,9,0,30)==BZ_MEM_ERROR||in.error||out.error||outstr.capacity==(unsigned)-2)
- goto bout;
- int ret=0;
- for(bString *uncompressed;;){
- if((uncompressed=bFileRead(&in,BZIP2_BUFFER))->size==0)break;
- strm.next_in=(char*)uncompressed->data,strm.avail_in=uncompressed->size;
- while(strm.avail_in>0){
- strm.avail_out=BZIP2_BUFFER,strm.next_out=(char*)outstr.data;
- if((ret=BZ2_bzCompress(&strm,BZ_RUN))!=BZ_RUN_OK)goto bout;
- bFileWrite(&out,outstr.data,BZIP2_BUFFER-strm.avail_out);
- }
- }
- for(int fin=0;!fin;){
- strm.avail_out=BZIP2_BUFFER,strm.next_out=(char*)outstr.data;
- if((ret=BZ2_bzCompress(&strm,BZ_FINISH))==BZ_STREAM_END)fin=1;
- else if(ret!=BZ_FINISH_OK)goto bout;
- bFileWrite(&out,outstr.data,BZIP2_BUFFER-strm.avail_out);
- }
- bout:
- BZ2_bzCompressEnd(&strm);
- bStringFree(&outstr);
- bFileFree(&out);
- bFileFree(&in);
- return ret;
- }
- bString bBzip2Compress(bString uncompressed,int level/*1...9*/){
- bString ret=bStringFrom(0,uncompressed.size+(uncompressed.size/100)+600);
- unsigned destlen=ret.capacity;
- int bzError=BZ2_bzBuffToBuffCompress(ret.data,&destlen,uncompressed.data,uncompressed.size,level,0,30);
- ret.size=destlen;
- return ret;
- }
- bString bBzip2Uncompress(bString compressed){
- bString ret={0};
- unsigned destlen=0;
- int bzErr=BZ_OUTBUFF_FULL;
- while(bzErr==BZ_OUTBUFF_FULL){
- bStringReserve(&ret,bMax(compressed.size*2,ret.capacity*2));
- destlen=ret.capacity;
- bzErr=BZ2_bzBuffToBuffDecompress((char*)ret.data,&destlen,(char*)compressed.data,compressed.size,0,0);
- }
- return ret.size=destlen,ret;
- }
- #endif //BEXT_IMPLEMENTATION
- #endif //bUSE_BZIP2
- /******************************** bLZMA ****************************************************************/
- #if defined(bUSE_LZMA)
- bString bLzmaCompress(bString uncompressed,int level/*0...9*/);
- bString bLzmaUncompress(bString compressed);
- int bLzmaUncompressFile(char *fileCompressed,char *fileUncompressed);
- int bLzmaCompressFile(char *fileUncompressed,char *fileCompressed);
- typedef struct b7ZEntry{bString filename;uint64_t size;bDatetime modified;}b7ZEntry;
- bDECLARE_ARRAY(bArrayb7ZEntry,b7ZEntry);
- typedef struct{ISeekInStream vt;bFile f,flook;}b7ZSeeker;
- typedef struct{ILookInStream vt;b7ZSeeker *s;size_t pos;}b7ZLooker;
- typedef struct b7zFile{bArrayb7ZEntry entries;CSzArEx db;b7ZSeeker seeker;b7ZLooker looker;}b7zFile;
- b7zFile b7zFileFrom(char *filename);
- void b7zFileFree(b7zFile *f);
- bString b7ZExtract(b7zFile *f,unsigned index);
- #if defined (BEXT_IMPLEMENTATION)|| defined(__CLION_IDE__)
- bString bLzmaCompress(bString uncompressed,int level/*0...9*/){
- bString ret=bStringFrom(0,uncompressed.size/2);
- CLzmaEncProps props;
- LzmaEncProps_Init(&props);
- props.level=bClip(level,0,9);
- props.writeEndMark=1;
- CLzmaEncHandle enc=LzmaEnc_Create(&g_Alloc);
- SizeT headersize=LZMA_PROPS_SIZE,outlen=0;
- SRes res=LzmaEnc_SetProps(enc,&props);
- for(;ret.capacity!=(unsigned)-2;){
- outlen=ret.capacity-5,res=LzmaEnc_WriteProperties(enc,ret.data,&headersize);
- if((res=LzmaEnc_MemEncode(enc,ret.data+5,&outlen,uncompressed.data,uncompressed.size,
- 1,0,&g_Alloc,&g_Alloc)==SZ_ERROR_OUTPUT_EOF))bStringReserve(&ret,ret.capacity*2);
- else break;
- }
- LzmaEnc_Destroy(enc,&g_Alloc,&g_Alloc);
- if(res==SZ_OK)ret.size=(unsigned)outlen+5;
- return ret;
- }
- bString bLzmaUncompress(bString compressed){
- bString ret=bStringFrom(0,compressed.size*2);
- if(compressed.size<LZMA_PROPS_SIZE||ret.capacity==(unsigned)-2)return ret;
- CLzmaDec state;
- LzmaDec_Construct(&state);
- SRes res=LzmaDec_Allocate(&state,compressed.data,LZMA_PROPS_SIZE,&g_Alloc);
- if(res!=SZ_OK)return ret.capacity=(unsigned)-2,ret;
- LzmaDec_Init(&state);
- ELzmaStatus status=LZMA_STATUS_NOT_FINISHED;
- SizeT inputPos=0,outputPos=0,outlen=0,inTotal=compressed.size-LZMA_PROPS_SIZE,inlen;
- while(inputPos<inTotal){
- inlen=inTotal-inputPos,outlen=ret.capacity-outputPos;
- res=LzmaDec_DecodeToBuf(&state,ret.data+outputPos,&outlen,compressed.data+LZMA_PROPS_SIZE+inputPos,
- &inlen,LZMA_FINISH_END,&status);
- inputPos+=inlen,outputPos+=outlen;
- ret.size=(unsigned)outputPos;
- if(status==LZMA_STATUS_NOT_FINISHED)bStringReserve(&ret,ret.capacity*2);
- else break;
- }
- memset(ret.data+ret.size,0,ARRAY_EXTRA);
- LzmaDec_Free(&state,&g_Alloc);
- if(status!=LZMA_STATUS_FINISHED_WITH_MARK&&status!=LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
- ret.capacity=(unsigned)-2;
- return ret;
- }
- #define bLZMA_INBUF_SIZE 4194304
- #define bLZMA_OUTBUF_SIZE 4194304
- int bLzmaUncompressFile(char *fileCompressed,char *fileUncompressed){
- bFile in=bFileFrom(fileCompressed,bFILE_READ),
- out=bFileFrom(fileUncompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
- bString *read=bFileRead(&in,LZMA_PROPS_SIZE);
- CLzmaDec state;
- LzmaDec_Construct(&state);
- int ret=0;
- SRes res=LzmaDec_Allocate(&state,read->data,read->size,&g_Alloc);
- if(res!=SZ_OK||in.error||out.error){ret=1;goto lout;}
- LzmaDec_Init(&state);
- ELzmaStatus status=LZMA_STATUS_NOT_FINISHED;
- bString outbuf=bStringFrom(0,bLZMA_OUTBUF_SIZE);
- while(1){
- if((read=bFileRead(&in,bLZMA_INBUF_SIZE))->size==0)break;
- SizeT srcLen=read->size,srcProcessed=0,destLen,srcLenToProcess;
- while(srcProcessed<read->size){
- destLen=outbuf.capacity,srcLenToProcess=srcLen,res=LzmaDec_DecodeToBuf(&state,outbuf.data,
- &destLen,read->data+srcProcessed,&srcLenToProcess,LZMA_FINISH_ANY,&status);
- if(res!=SZ_OK){ret=1;goto lout;}
- bFileWrite(&out,outbuf.data,destLen);
- srcProcessed+=srcLenToProcess;
- srcLen-=srcLenToProcess;
- if(status==LZMA_STATUS_FINISHED_WITH_MARK)break;
- }
- if(status==LZMA_STATUS_FINISHED_WITH_MARK)break;
- }
- lout:return LzmaDec_Free(&state,&g_Alloc),bFileFree(&out),bFileFree(&in),ret;
- }
- typedef struct{ISeqInStream vt;bFile *file;}bLzmaFileInStream;
- SRes bLzmaFileInStream_Read(const ISeqInStream *pp,void *buf,size_t *size){
- bLzmaFileInStream *p=(bLzmaFileInStream*)pp;
- bString *str=bFileRead(p->file,(unsigned)*size);
- if(p->file->error) return SZ_ERROR_READ;
- memcpy(buf,str->data,str->size);
- *size=str->size;
- return SZ_OK;
- }
- typedef struct{ISeqOutStream vt;bFile *file;}bLzmaFileOutStream;
- size_t bLzmaFileOutStream_Write(const ISeqOutStream *pp,const void *buf,size_t size){
- bLzmaFileOutStream *p=(bLzmaFileOutStream*)pp;
- bFileWrite(p->file,(void*)buf,size);
- return p->file->error?0:size;
- }
- int bLzmaCompressFile(char *fileUncompressed,char *fileCompressed){
- bFile in=bFileFrom(fileUncompressed,bFILE_READ),
- out=bFileFrom(fileCompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
- SRes res=0;
- CLzmaEncProps props;
- LzmaEncProps_Init(&props);
- props.level=9,props.writeEndMark=1;
- CLzmaEncHandle enc=LzmaEnc_Create(&g_Alloc);
- if(!enc||in.error||out.error){res=1;goto lout;}
- Byte header[LZMA_PROPS_SIZE];
- SizeT headerSize=LZMA_PROPS_SIZE;
- LzmaEnc_WriteProperties(enc,header,&headerSize);
- bFileWrite(&out,header,headerSize);
- bLzmaFileInStream inStream={.vt.Read=bLzmaFileInStream_Read,.file=&in};
- bLzmaFileOutStream outStream={.vt.Write=bLzmaFileOutStream_Write,.file=&out};
- res=LzmaEnc_Encode(enc,&outStream.vt,&inStream.vt,0,&g_Alloc,&g_Alloc);
- lout:return LzmaEnc_Destroy(enc,&g_Alloc,&g_Alloc),bFileFree(&in),bFileFree(&out),res;
- }
- SRes b7ZSeeker_Read(void *pp,void *buf,size_t *size){
- bString *r=bFileRead(&((b7ZSeeker*)pp)->f,(unsigned)*size);
- return memcpy(buf,r->data,(*size)=r->size),SZ_OK;
- }
- SRes b7ZSeeker_Seek(void *pp,Int64 *pos,ESzSeek origin){
- b7ZSeeker *s=(b7ZSeeker*)pp;
- Int64 newpos=0;
- switch(origin){
- case SZ_SEEK_SET:break((newpos=*pos));
- case SZ_SEEK_CUR:break((newpos=bFileGetCursor(&s->f)+*pos));
- case SZ_SEEK_END:break((newpos=bFileGetSize(&s->f)+*pos));
- }
- if(newpos<0||newpos>(int64_t)bFileGetSize(&s->f))return SZ_ERROR_FAIL;
- bFileSetCursor(&s->f,(uint64_t)newpos);
- return (*pos)=newpos,SZ_OK;
- }
- SRes b7ZLooker_Look(void *pp,const void **buf,size_t *size){
- b7ZLooker *s=(b7ZLooker*)pp;
- bFileSetCursor(&s->s->flook,bFileGetCursor(&s->s->f));
- bString *r=bFileRead(&s->s->flook,(unsigned)*size);
- return *buf=r->data,*size=r->size,SZ_OK;
- }
- SRes b7ZLooker_Skip(void *pp,size_t offset){
- return bFileSetCursor(&((b7ZLooker*)pp)->s->f,bFileGetCursor(&((b7ZLooker*)pp)->s->f)+offset),SZ_OK;
- }
- SRes b7ZLooker_Read(void *pp,void *buf,size_t *size){
- return b7ZSeeker_Read(((b7ZLooker*)pp)->s,buf,size);
- }
- SRes b7ZLooker_Seek(void *pp,Int64 *pos,ESzSeek origin){
- return b7ZSeeker_Seek(((b7ZLooker*)pp)->s,pos,origin);
- }
- void b7ZEntryFree(b7ZEntry *entry){bStringFree(&entry->filename);}
- int b7ZEntryCollate(b7ZEntry *l,b7ZEntry *r){return bCollateStringFast(&l->filename,&r->filename);}
- bDEFINE_ARRAY(bArrayb7ZEntry,b7ZEntry,b7ZEntryFree,b7ZEntryCollate);
- b7zFile b7zFileFrom(char *filename){
- b7zFile ret={.seeker={.f=bFileFrom(filename,bFILE_READ),.flook=bFileFrom(filename,bFILE_READ),
- .vt.Seek=b7ZSeeker_Seek,.vt.Read=b7ZSeeker_Read}};
- ret.looker=(b7ZLooker){.s=&ret.seeker,
- .vt={.Read=b7ZLooker_Read,.Seek=b7ZLooker_Seek,.Look=b7ZLooker_Look,.Skip=b7ZLooker_Skip}};
- static int b7ZCrcInit=0;
- if(!b7ZCrcInit){
- bAssert(bThreadIsMain());
- CrcGenerateTable();
- b7ZCrcInit=1;
- }
- SzArEx_Init(&ret.db);
- SRes res=SzArEx_Open(&ret.db,&ret.looker.vt,&g_Alloc,&g_Alloc);
- for(UInt32 i=0;i<ret.db.NumFiles;i++){
- size_t len=SzArEx_GetFileNameUtf16(&ret.db,i,0);
- bString n16=bStringFrom(0,len*2);
- SzArEx_GetFileNameUtf16(&ret.db,i,(UInt16*)n16.data);
- bString n8=bStringFromUtf16ToUtf8((uint16_t*)n16.data);
- UInt64 fileSize=SzArEx_GetFileSize(&ret.db,i);
- CNtfsFileTime mod=ret.db.MTime.Vals[i];
- bDatetime dt=bDatetimeFromWinFiletime(bUint64(mod.Low,mod.High));
- bArrayb7ZEntryAdd(&ret.entries,(b7ZEntry){.filename=n8,.size=fileSize,.modified=dt});
- bStringFree(&n16);
- }
- return ret;
- }
- void b7zFileFree(b7zFile *f){
- bFileFree(&f->seeker.f);
- bFileFree(&f->seeker.flook);
- SzArEx_Free(&f->db,&g_Alloc);
- }
- bString b7ZExtract(b7zFile *f,unsigned index){
- if(index>=f->entries.size||SzArEx_IsDir(&f->db,index))return (bString){0};
- f->looker.s=&f->seeker;
- UInt32 blockIndex=0xFFFFFFFF;
- Byte *outBuffer=NULL;
- size_t outBufferSize=0,offset=0,outSizeProcessed=0;
- SRes res=SzArEx_Extract(&f->db,&f->looker.vt,(UInt32)index,&blockIndex,&outBuffer,&outBufferSize,
- &offset,&outSizeProcessed,&g_Alloc,&g_Alloc);
- return bStringFrom(outBuffer+offset,outSizeProcessed);
- }
- #endif //BEXT_IMPLEMENTATION
- #endif //bUSE_LZMA
- And libdeflate:
- bString bLibdeflateCompress(bString uncompressed,int level/*0...123*/,int zlibHeader){
- bString ret={0},*u=&uncompressed;
- struct libdeflate_compressor *compressor=libdeflate_alloc_compressor(level);
- bStringReserve(&ret,(unsigned)(zlibHeader==1?libdeflate_zlib_compress_bound(compressor,u->size):
- zlibHeader==2?libdeflate_gzip_compress_bound(compressor,uncompressed.size):
- libdeflate_deflate_compress_bound(compressor,uncompressed.size)));
- if(!compressor||ret.capacity==(unsigned)-2)
- return libdeflate_free_compressor(compressor),ret.capacity=(unsigned)-2,ret;
- ret.size=(unsigned)(
- zlibHeader==1?libdeflate_zlib_compress(compressor,u->data,u->size,ret.data,ret.capacity):
- zlibHeader==2?libdeflate_gzip_compress(compressor,u->data,u->size,ret.data,ret.capacity):
- libdeflate_deflate_compress(compressor,u->data,u->size,ret.data,ret.capacity));
- libdeflate_free_compressor(compressor);
- return ret;
- }
- bString bLibdeflateUncompess(bString compressed){
- bString ret=bStringFrom(0,compressed.size*3);
- uint32_t header=*(bUnaligned32*)compressed.data,pos=(header&8207)==8200?6:
- ((!(header&7))&&(((header>>8)&255)!=(~(header>>24)&255)))?2:0;
- if((header&65535)==35615&&compressed.size>10)
- if(pos=10,header&134217728){while(*(compressed.data+pos))pos++;pos++;}
- compressed.data+=pos,compressed.size-=pos;
- struct libdeflate_decompressor *d=libdeflate_alloc_decompressor();
- if(!d)return ret.capacity=(unsigned)-2,ret;
- size_t outsize=0;
- for(enum libdeflate_result result;;){
- result=libdeflate_deflate_decompress(d,compressed.data,compressed.size,ret.data,ret.capacity,&outsize);
- if(result==LIBDEFLATE_SUCCESS){break(ret.size=outsize)}
- else if(result==LIBDEFLATE_BAD_DATA){break(bStringFree(&ret))}
- else if(result==LIBDEFLATE_INSUFFICIENT_SPACE)bStringReserve(&ret,ret.capacity*2);
- }
- return libdeflate_free_decompressor(d),ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement