Advertisement
mmmmkkkkzzzz

Untitled

May 27th, 2025
454
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 30.35 KB | None | 0 0
  1. /******************************** bZip *****************************************************************/
  2. typedef struct bZipEntry{bString filename;uint64_t size,offset;}bZipEntry;
  3. void bZipEntryFree(bZipEntry *entry);
  4. int bZipEntryCollate(bZipEntry *l,bZipEntry *r);
  5. bDECLARE_INDEX(bIndexZipEntry,bZipEntry);
  6. typedef struct bZipFile{bFile f;bIndexZipEntry entries;int error;}bZipFile;
  7. #define bZIP_ERROR_FILEERROR 1
  8. #define bZIP_ERROR_A 2
  9. #define bZIP_ERROR_B 3
  10. #define bZIP_ERROR_C 4
  11. #define bZIP_ERROR_D 5
  12. void bZipFileFree(bZipFile *z);
  13. bZipFile bZipFileFrom(char *filename);
  14. int bZipExtract(bZipFile *zip,char *name,char *dest);
  15. int bZipAdd(bZipFile *zip,char *file,char *name);
  16. #if defined(ZIB_IMPLEMENTATION)||defined(__CLION_IDE__)
  17. #define bBUFSIZE 4194304
  18. void bZipEntryFree(bZipEntry *entry){bStringFree(&entry->filename);}
  19. int bZipEntryCollate(bZipEntry *l,bZipEntry *r){return bCollateStringFast(&l->filename,&r->filename);}
  20. bDEFINE_INDEX(bIndexZipEntry,bZipEntry,bZipEntryCollate,bZipEntryFree);
  21. void bZipRead64(bString extra,uint64_t *size,uint64_t *compressedsize,uint64_t *offset){
  22.  for(unsigned i=0,j,id,datasize=0;extra.size>4&&i<extra.size-4;i+=bMax(datasize+4,4)){
  23.   id=bStringReadUint16(extra,i),datasize=bStringReadUint16(extra,i+2);
  24.   if(j=4,datasize!=0&&id==1){
  25.    if(size&&*size==4294967295)*size=bStringReadUint64(extra,j),j+=8;
  26.    if(compressedsize&&*compressedsize==4294967295)*compressedsize=bStringReadUint64(extra,j),j+=8;
  27.    if(offset&&*offset==4294967295)*offset=bStringReadUint64(extra,j);
  28.    return;
  29.   }
  30.  }
  31. }
  32. bString bZipMakeFilename(char *filename,unsigned len){
  33.  bString fn=bStringFrom(filename,len);
  34.  if(fn.data[1]==':')bStringErase(&fn,0,3);
  35.  if(fn.data[0]=='/')bStringErase(&fn,0,1);
  36.  for(unsigned i=0;i<fn.size;i++)if(fn.data[i]=='\\')fn.data[i]='/';
  37.  memset(fn.data+(fn.size=bMin(65535,fn.size)),0,ARRAY_EXTRA);
  38.  return fn;
  39. }
  40. void bZipReadExtraTime(bString extra,bDatetime *created,bDatetime *modified,bDatetime *accessed){
  41.  for(unsigned i=0,j,id,datasize=0;extra.size>4&&i<extra.size-4;i+=bMax(datasize+4,4)){
  42.   id=bStringReadUint16(extra,i),datasize=bStringReadUint16(extra,i+2);
  43.   if(j=4,datasize!=0&&id==215891){
  44.    *modified=bDatetimeFromUnix(bStringReadUint32(extra,i+j+1));
  45.   }else if(datasize==32&&id==10){
  46.    *modified=bDatetimeFromWinFiletime(bStringReadUint64(extra,i+j+8));
  47.    *accessed=bDatetimeFromWinFiletime(bStringReadUint64(extra,i+j+16));
  48.    *created=bDatetimeFromWinFiletime(bStringReadUint64(extra,i+j+24));
  49.   }
  50.  }
  51. }
  52. void bZipFindCD(bZipFile *z,uint64_t *cd,uint64_t *cdend,uint64_t *cd64end,uint64_t *cdend64loc){
  53.  if(z->error)return;
  54.  unsigned p,i=101010256;
  55.  uint64_t filesize,offs=(filesize=bFileGetSize(&z->f))-111111;
  56.  if(filesize==0)return;
  57.  if(offs>filesize)offs=0;
  58.  bFileSetCursor(&z->f,offs);
  59.  bString *r=bFileRead(&z->f,111111);
  60.  if(r->size<20){z->error=z->f.error?bZIP_ERROR_FILEERROR:bZIP_ERROR_A;return;}
  61.  for(p=r->size-20;p<r->size;p--)if(bStringReadUint32(*r,p)==i&&bStringReadUint32(*r,p+4)==0)break;
  62.  if(p>=r->size){z->error=bZIP_ERROR_A;return;}
  63.  *cd=bStringReadUint32(*r,p+16),*cdend=offs+p;
  64.  if(*cd==4294967295){
  65.   while(p--<r->size)if(bStringReadUint32(*r,p)==117853008&&bStringReadUint32(*r,p+4)==0)break;
  66.   *cdend64loc=p+offs,*cd64end=bStringReadUint64(*r,p+8),p=(*cd64end-offs),*cd=bStringReadUint64(*r,p+48);
  67.  }
  68. }
  69. void bZipFileFree(bZipFile *z){
  70.  bIndexZipEntryFree(&z->entries);
  71.  bFileFree(&z->f);
  72.  memset(z,0,sizeof(*z));
  73. }
  74. bZipFile bZipFileFrom(char *filename){
  75.  bZipFile z={.f=bFileFrom(filename,bFILE_READ|bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS)};
  76.  if(z.f.error)bFileFree(&z.f),z.f=bFileFrom(filename,bFILE_READ);
  77.  if(z.f.error)return bFileFree(&z.f),z.error=bZIP_ERROR_FILEERROR,z;
  78.  uint64_t cd=(unsigned)-1,cdend=(unsigned)-1,cd64end=(unsigned)-1,cd64endloc=(unsigned)-1;
  79.  bZipFindCD(&z,&cd,&cdend,&cd64end,&cd64endloc);
  80.  bFileSetCursor(&z.f,cd);
  81.  for(;;){
  82.   bString *r=bFileRead(&z.f,46);
  83.   if(bStringReadUint32(*r,0)!=33639248)break;
  84.   uint64_t sz=bStringReadUint32(*r,24),csz=bStringReadUint32(*r,20),off=bStringReadUint32(*r,42);
  85.   unsigned fnlen=bStringReadUint16(*r,28),exln=bStringReadUint16(*r,30),commln=bStringReadUint16(*r,32);
  86.   bString fn=bZipMakeFilename((char*)bFileRead(&z.f,fnlen)->data,fnlen),*extra=bFileRead(&z.f,exln);
  87.   bZipRead64(*extra,&sz,&csz,&off);
  88.   bFileRead(&z.f,commln);
  89.   bIndexZipEntryAdd(&z.entries,(bZipEntry){.size=sz,.filename=fn,.offset=off});
  90.  }
  91.  return z;
  92. }
  93. int bZipExtract(bZipFile *zip,char *name,char *dest){
  94.  int ret=0;
  95.  bString fn=bStringFrom(name,0);
  96.  unsigned idx=bIndexZipEntryFindIndex(zip->entries,(bZipEntry){.filename=fn},0);
  97.  bStringFree(&fn);
  98.  if(idx==(unsigned)-1)return ret;
  99.  bZipEntry entry=zip->entries.data[idx];
  100.  bFileSetCursor(&zip->f,entry.offset);
  101.  bFileReadUint64(&zip->f);
  102.  unsigned metod=bFileReadUint16(&zip->f),t=bFileReadUint16(&zip->f),d=bFileReadUint16(&zip->f),
  103.   c=bFileReadUint32(&zip->f),c2=0;
  104.  bDatetime created=bDatetimeNow(),modified=bDatetimeFromDOS(t,d),accessed=bDatetimeNow();
  105.  uint64_t compressedsize=bFileReadUint32(&zip->f),uncompressedsize=bFileReadUint32(&zip->f);
  106.  unsigned filenamelen=bFileReadUint16(&zip->f),extralen=bFileReadUint16(&zip->f);
  107.  bFileRead(&zip->f,filenamelen);
  108.  bString *extra=bFileRead(&zip->f,extralen);
  109.  bZipRead64(*extra,&uncompressedsize,&compressedsize,NULL);
  110.  bZipReadExtraTime(*extra,&created,&modified,&accessed);
  111.  bString *in,outbuf=bStringFrom(0,bBUFSIZE);
  112.  bFile out=bFileFrom(dest,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS|bFILE_OVERWRITE);
  113.  switch(metod){
  114.   case 0:{
  115.    while(compressedsize!=0){
  116.     in=bFileRead(&zip->f,(unsigned)(bMin(compressedsize,bBUFSIZE)));
  117.     bFileWrite(&out,in->data,in->size);
  118.     c2=bCrc32(c,in->data,in->size),compressedsize-=in->size;
  119.    }
  120.    break;
  121.   }
  122.   case 8:{
  123.    z_stream stream={0};
  124.    inflateInit2(&stream,-15);
  125.    do{
  126.     if(compressedsize==0)break;
  127.     compressedsize-=(in=bFileRead(&zip->f,(unsigned)(bMin(bBUFSIZE,compressedsize))))->size;
  128.     if((stream.avail_in=in->size)==0)break;
  129.     stream.next_in=in->data;
  130.     do{
  131.      stream.avail_out=bBUFSIZE,stream.next_out=outbuf.data;
  132.      if((ret=inflate(&stream,Z_NO_FLUSH))<0&&ret!=Z_BUF_ERROR)break(compressedsize=0);
  133.      outbuf.size=bBUFSIZE-stream.avail_out;
  134.      bFileWrite(&out,outbuf.data,outbuf.size);
  135.      c2=bCrc32(c2,(char*)outbuf.data,outbuf.size);
  136.     }while(stream.avail_out==0);
  137.    }while(ret!=Z_STREAM_END);
  138.    /*ret=*/inflateEnd(&stream);
  139.    break;
  140.   }
  141. #if defined bUSE_BZIP2
  142.   case 12:{
  143.    bz_stream strm={0};
  144.    if(BZ2_bzDecompressInit(&strm,0,0)!=BZ_MEM_ERROR){
  145.     for(int fin=0;!fin;){
  146.      in=bFileRead(&zip->f,bBUFSIZE),strm.avail_in=in->size,strm.next_in=(char*)in->data;
  147.      if(strm.avail_in==0)break;
  148.      do{
  149.       strm.avail_out=bBUFSIZE,strm.next_out=(char*)outbuf.data;
  150.       if((ret=BZ2_bzDecompress(&strm))==BZ_STREAM_END)fin=1;
  151.       else if(ret!=BZ_OK)break(fin=1);
  152.       bFileWrite(&out,outbuf.data,bBUFSIZE-strm.avail_out);
  153.      }while(strm.avail_in>0||strm.avail_out==0);
  154.     }
  155.     BZ2_bzDecompressEnd(&strm);
  156.    }
  157.    break;
  158.   }
  159. #endif
  160. #if defined bUSE_LZMA
  161.   case 14:{
  162.    uint16_t ver=bFileReadUint16(&zip->f),propsize=bFileReadUint16(&zip->f);
  163.    if(compressedsize<=(4+propsize))break;
  164.    in=bFileRead(&zip->f,5),compressedsize-=(4+propsize);
  165.    CLzmaDec state={0};
  166.    LzmaDec_Construct(&state);
  167.    if((ret=LzmaDec_Allocate(&state,in->data,propsize,&g_Alloc))!=SZ_OK)break;
  168.    LzmaDec_Init(&state);
  169.    ELzmaStatus status;
  170.    while(compressedsize>0){
  171.     SizeT inSize=(SizeT)bMin(bBUFSIZE,compressedsize),srcPos=0;
  172.     in=bFileRead(&zip->f,(unsigned)inSize),compressedsize-=inSize;
  173.     while(srcPos<in->size){
  174.      SizeT srcLen=in->size-srcPos,destLen=outbuf.capacity;
  175.      ret=LzmaDec_DecodeToBuf(&state,outbuf.data,&destLen,in->data+srcPos,&srcLen,
  176.       (compressedsize==0&&srcPos+srcLen==in->size)?LZMA_FINISH_END:LZMA_FINISH_ANY,&status);
  177.      if(ret!=SZ_OK&&ret!=SZ_ERROR_DATA)break;
  178.      bFileWrite(&out,outbuf.data,destLen);
  179.      c2=bCrc32(c2,outbuf.data,(unsigned)destLen),srcPos+=srcLen;
  180.      if(srcLen==0&&destLen==0)break;
  181.     }
  182.    }
  183.    LzmaDec_Free(&state,&g_Alloc);
  184.    break;
  185.   }
  186. #endif
  187.    default:{
  188.     ret=bZIP_ERROR_C;
  189.     break;
  190.    }
  191.   }
  192.   ret=c==c2?0:ret?ret:bZIP_ERROR_D;
  193.   bStringFree(&outbuf);
  194.   bFileFree(&out);
  195.   return ret;//meaningless
  196.  
  197.  return bZIP_ERROR_B;
  198. }
  199. int bZipAdd(bZipFile *zip,char *file,char *name){
  200.  bFile compressed=bFileTempFile();
  201.  int ret=bZlibCompressFile(file,(char*)compressed.name.data,0,0,6);
  202.  uint32_t crc=0;
  203.  bString *r;
  204.  bFile uncompressed=bFileFrom(file,bFILE_READ);
  205.  while((r=bFileRead(&uncompressed,4194304))->size)crc=bCrc32(crc,r->data,r->size);
  206.  bFileinfo fileinfo=bFileinfoStatic(file);
  207.  uint64_t csize64=bFileGetSize(&compressed),usize64=fileinfo.size,cd=0,cdend=0,cd64end=0,cd64endloc=0;
  208.  bZipFindCD(zip,&cd,&cdend,&cd64end,&cd64endloc);
  209.  bDatetime mod=fileinfo.modified;
  210.  uint32_t fmod=(mod.year-1980)<<25|mod.month<<21|mod.day<<16|mod.hour<<11|mod.min<<5|(mod.sec/2);
  211.  bString loc=bStringFrom((char[30]){80,75,3,4,20,0,0,0,8},30),ex={0};loc.size=30;
  212.  bString fn=bZipMakeFilename(name,bStrlen(name));
  213.  uint32_t csize32=(unsigned)bMin(4294967295,csize64),usize32=(unsigned)bMin(4294967295,usize64);
  214.  uint16_t fnlen=fn.size,entries32=zip->entries.items+1;
  215.  int want64=csize64>4294967295||usize64>4294967295||bFileGetSize(&zip->f)>4294967295||cd64end!=0;
  216.  if(want64&&(loc.data[4]=45,loc.data[28]=28,ex=bStringFrom((char[28]){1,0,24},28),1))
  217.   ex.size=28,memcpy(ex.data+4,&usize64,8),memcpy(ex.data+12,&csize64,8);
  218.  memcpy(loc.data+10,&fmod,4),memcpy(loc.data+14,&crc,4);
  219.  memcpy(loc.data+18,&csize32,4),memcpy(loc.data+22,&usize32,4),memcpy(loc.data+26,&fnlen,2);
  220.  bStringAdd(&loc,(char*)fn.data,fn.size);
  221.  bString centralheader=bStringFrom(loc.data,loc.size);
  222.  if(ex.size)bStringAdd(&loc,ex.data,ex.size);
  223.  centralheader.data[2]=1,centralheader.data[3]=2;
  224.  bStringInsert(&centralheader,"\055",2,4),bStringInsert(&centralheader,(char[14]){0},14,32);
  225.  uint32_t offs32=cd>4294967295?(uint32_t)-1:cd;
  226.  memcpy(centralheader.data+42,&offs32,4);
  227.  if(ex.size&&(centralheader.data[30]=12,ex.data[2]=8,ex.size=12,memcpy(ex.data+4,&cd,8),1))
  228.   bStringAdd(&centralheader,(char*)ex.data,ex.size);
  229.  bFileSetCursor(&zip->f,cd);
  230.  r=bFileRead(&zip->f,(unsigned)((cd64end==0?cdend:cd64end)-cd));
  231.  bString oldcentraldir=bStringFrom((char*)r->data,r->size),endofcd=bStringFrom((char[22]){80,75,5,6},22);
  232.  bFileSetCursor(&zip->f,cd);
  233.  bFileWrite(&zip->f,loc.data,loc.size);
  234.  bFileSetCursor(&compressed,0);
  235.  while((r=bFileRead(&compressed,4194304))->size)bFileWrite(&zip->f,r->data,r->size);
  236.  uint64_t newcd=bFileGetCursor(&zip->f);
  237.  bFileWrite(&zip->f,oldcentraldir.data,oldcentraldir.size);
  238.  bFileWrite(&zip->f,centralheader.data,centralheader.size);
  239.  if(want64){
  240.   uint64_t newentries=zip->entries.items+1,newcdsize=oldcentraldir.size+centralheader.size;
  241.   bString z64loc=bStringFrom((char[20]){80,75,6,7},20);z64loc.data[16]=1;
  242.   bString z64=bStringFrom((char[56]){80,75,6,6,44,0,0,0,0,0,0,0,45,0,45},56);
  243.   memcpy(z64.data+24,&newentries,8),memcpy(z64.data+32,&newentries,8);
  244.   memcpy(z64.data+40,&newcdsize,8),memcpy(z64.data+48,&newcd,8);
  245.   uint64_t z64l=bFileGetCursor(&zip->f);
  246.   memcpy(z64loc.data+8,&z64l,8);
  247.   bFileWrite(&zip->f,z64.data,z64.size),bFileWrite(&zip->f,z64loc.data,z64loc.size);
  248.   bStringFree(&z64),bStringFree(&z64loc);
  249.  }
  250.  uint32_t newcdsize32=oldcentraldir.size+centralheader.size,newcd32=newcd>65535?(uint32_t)-1:newcd;
  251.  memcpy(endofcd.data+8,&entries32,2),memcpy(endofcd.data+10,&entries32,2);
  252.  memcpy(endofcd.data+12,&newcdsize32,4),memcpy(endofcd.data+16,&newcd32,4);
  253.  bFileWrite(&zip->f,endofcd.data,endofcd.size);
  254.  if(zip->f.error||uncompressed.error||compressed.error)bLog("bZipAdd:smth went wwrong");//todo
  255.  bIndexZipEntryAdd(&zip->entries,(bZipEntry){.size=usize64,.filename=fn,.offset=cd});
  256.  bStringFree(&endofcd),bStringFree(&oldcentraldir),bStringFree(&centralheader),bStringFree(&fn);
  257.  bStringFree(&ex),bStringFree(&loc),bFileFree(&uncompressed),bFileFree(&compressed);
  258.  return 0;
  259. }
  260.  
  261. /******************************** bZlib ****************************************************************/
  262. #if bUSE_ZLIB
  263. bString bZlibUncompress(bString compressed,bString *dictionary);
  264. int bZlibUncompressFile(char *fileCompressed,char *fileUncompressed,bString *dictionary);
  265. bString bZlibCompress(bString uncompressed,bString *dictionary,int zlibHeader,int level/*0...9*/);
  266. int bZlibCompressFile(char *fileUncompressed,char *fileCompressed,bString *dictionary,int zlibHeader,
  267.  int level/*0...9*/);
  268. #if defined(BEXT_IMPLEMENTATION)
  269. #define bZLIB_CHUNK 4194304
  270. bString bZlibUncompress(bString compressed,bString *dictionary){
  271.  bString ret=bStringFrom(0,compressed.size*3);
  272.  if(ret.capacity==(unsigned)-2||compressed.size<5)return ret;
  273.  z_stream strm={.next_in=compressed.data,.avail_in=compressed.size};
  274.  uint32_t header=*(bUnaligned32*)compressed.data,wb=47;
  275.  if(!((!(header&7))&&(((header>>8)&255)!=(~(header>>24)&255)))&&(header&65535)!=35615)wb=-15;
  276.  if(inflateInit2(&strm,wb)!=Z_OK)return ret;
  277.  if(dictionary)inflateSetDictionary(&strm,dictionary->data,dictionary->size);
  278.  while(1){
  279.   bStringReserve(&ret,ret.size+compressed.size);
  280.   if(ret.capacity==(unsigned)-2)return inflateEnd(&strm),bStringFree(&ret),ret;
  281.   strm.next_out=ret.data+ret.size,strm.avail_out=compressed.size;
  282.   int rc=inflate(&strm,Z_FINISH);
  283.   ret.size+=compressed.size-strm.avail_out;
  284.   if(rc==Z_STREAM_END)return inflateEnd(&strm),memset(ret.data+ret.size,0,ARRAY_EXTRA),ret;
  285.   else if(rc==Z_NEED_DICT&&dictionary)inflateSetDictionary(&strm,dictionary->data,dictionary->size),
  286.     dictionary=0;
  287.   else if(rc!=Z_OK&&rc!=Z_BUF_ERROR)return inflateEnd(&strm),bStringFree(&ret),ret;
  288.  }
  289. }
  290. int bZlibUncompressFile(char *fileCompressed,char *fileUncompressed,bString *dictionary){
  291.  bFile in=bFileFrom(fileCompressed,bFILE_READ),
  292.   out=bFileFrom(fileUncompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
  293.  z_stream strm={0};
  294.  uint32_t header=bFileReadUint32(&in),wb=47;
  295.  if(!((!(header&7))&&(((header>>8)&255)!=(~(header>>24)&255)))&&(header&65535)!=35615)wb=-15;
  296.  bFileSetCursor(&in,0);
  297.  bString outbuf=bStringFrom(0,bZLIB_CHUNK);
  298.  int ret=inflateInit2(&strm,wb);
  299.  if(ret!=Z_OK||((in.error||out.error||outbuf.capacity==-2)&&(ret=-7)))goto zout;
  300.  if(dictionary)inflateSetDictionary(&strm,dictionary->data,dictionary->size);
  301.  do{
  302.   bString *inbuf=bFileRead(&in,bZLIB_CHUNK);
  303.   if((strm.avail_in=inbuf->size)==0)break;
  304.   strm.next_in=inbuf->data;
  305.   do{
  306.    strm.avail_out=bZLIB_CHUNK,strm.next_out=outbuf.data;
  307.    switch((ret=inflate(&strm,Z_FINISH))){
  308.     case Z_NEED_DICT:
  309.      if(dictionary)break((inflateSetDictionary(&strm,dictionary->data,dictionary->size),dictionary=0));
  310.      ret=Z_DATA_ERROR;
  311.     case Z_DATA_ERROR:
  312.     case Z_MEM_ERROR:
  313.      goto zout;
  314.    }
  315.    bFileWrite(&out,outbuf.data,bZLIB_CHUNK-strm.avail_out);
  316.   }while(strm.avail_out==0||ret==Z_NEED_DICT);
  317.  }while(ret!=Z_STREAM_END);
  318.  zout:return inflateEnd(&strm),bStringFree(&outbuf),bFileFree(&out),bFileFree(&in),ret;
  319. }
  320. bString bZlibCompress(bString uncompressed,bString *dictionary,int zlibHeader,int level/*0...9*/){
  321.  bString ret=bStringFrom(0,(unsigned)compressBound(uncompressed.size));
  322.  if(ret.capacity==(unsigned)-2)return ret;
  323.  z_stream strm={.next_in=uncompressed.data,.avail_in=uncompressed.size,.next_out=ret.data,
  324.   .avail_out=ret.capacity};
  325.  if(deflateInit2(&strm,level,Z_DEFLATED,zlibHeader?15:-15,9,Z_DEFAULT_STRATEGY)!=Z_OK)return ret;
  326.  if(dictionary)deflateSetDictionary(&strm,dictionary->data,dictionary->size);
  327.  return deflate(&strm,Z_FINISH),ret.size=strm.total_out,deflateEnd(&strm),ret;
  328. }
  329. int bZlibCompressFile(char *fileUncompressed,char *fileCompressed,bString *dictionary,int zlibHeader,
  330.  int level/*0...9*/){
  331.  bFile in=bFileFrom(fileUncompressed,bFILE_READ),
  332.   out=bFileFrom(fileCompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
  333.  bString outbuf=bStringFrom(0,bZLIB_CHUNK);
  334.  z_stream strm={0};
  335.  int ret=deflateInit2(&strm,Z_DEFAULT_COMPRESSION,Z_DEFLATED,zlibHeader?15:-15,9,Z_DEFAULT_STRATEGY);
  336.  if(dictionary)deflateSetDictionary(&strm,dictionary->data,dictionary->size);
  337.  if(in.error||out.error||ret!=Z_OK)goto zout;
  338.  do{
  339.   bString *inbuf=bFileRead(&in,bZLIB_CHUNK);
  340.   strm.avail_in=inbuf->size,strm.next_in=inbuf->data;
  341.   level=inbuf->size==0?Z_FINISH:Z_NO_FLUSH;
  342.   do{
  343.    strm.avail_out=bZLIB_CHUNK,strm.next_out=outbuf.data;
  344.    ret=deflate(&strm,level);
  345.    bFileWrite(&out,outbuf.data,bZLIB_CHUNK-strm.avail_out);
  346.    if(ret==Z_NEED_DICT&&dictionary)deflateSetDictionary(&strm,dictionary->data,dictionary->size),
  347.      dictionary=0;
  348.    else if(out.error||ret==Z_STREAM_ERROR)goto zout;
  349.    outbuf.size=0;
  350.   }while(strm.avail_out==0);
  351.  }while(level!=Z_FINISH);
  352.  bAssert(ret==Z_STREAM_END);
  353.  zout:return bStringFree(&outbuf),bFileFree(&out),bFileFree(&in),ret;
  354. }
  355. #endif //BEXT_IMPLEMENTATION
  356. #endif //bUSE_ZLIB
  357.  
  358. /******************************** bBzip2 ***************************************************************/
  359. #if defined bUSE_BZIP2
  360. int bBzip2UncompressFile(char *fileCompressed,char *fileUncompressed);
  361. int bBzip2CompressFile(char *fileUncompressed,char *fileCompressed);
  362. bString bBzip2Compress(bString uncompressed,int level/*1...9*/);
  363. bString bBzip2Uncompress(bString compressed);
  364. #if defined BEXT_IMPLEMENTATION || defined __CLION_IDE__
  365. #define BZIP2_BUFFER  4096
  366. int bBzip2UncompressFile(char *fileCompressed,char *fileUncompressed){
  367.  bFile in=bFileFrom(fileCompressed,bFILE_READ),
  368.   out=bFileFrom(fileUncompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
  369.  bString outstr=bStringFrom(0,BZIP2_BUFFER);
  370.  bz_stream strm={0};
  371.  int ret=0;
  372.  if(BZ2_bzDecompressInit(&strm,0,0)==BZ_MEM_ERROR||in.error||out.error)goto bout;
  373.  for(int fin=0;!fin;){
  374.   bString *instr=bFileRead(&in,BZIP2_BUFFER);
  375.   strm.avail_in=instr->size,strm.next_in=(char*)instr->data;
  376.   if(strm.avail_in==0)break;
  377.   do{
  378.    strm.avail_out=BZIP2_BUFFER,strm.next_out=(char*)outstr.data;
  379.    if((ret=BZ2_bzDecompress(&strm))==BZ_STREAM_END)fin=1;
  380.    else if(ret!=BZ_OK)goto bout;
  381.    bFileWrite(&out,outstr.data,BZIP2_BUFFER-strm.avail_out);
  382.   }while(strm.avail_in>0||strm.avail_out==0);
  383.  }
  384.  bout:
  385.  bStringFree(&outstr);
  386.  BZ2_bzDecompressEnd(&strm);
  387.  bFileFree(&out);
  388.  bFileFree(&in);
  389.  return ret;
  390. }
  391. int bBzip2CompressFile(char *fileUncompressed,char *fileCompressed){
  392.  bFile in=bFileFrom(fileUncompressed,bFILE_READ),
  393.   out=bFileFrom(fileCompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
  394.  bString outstr=bStringFrom(0,BZIP2_BUFFER);
  395.  bz_stream strm={0};
  396.  if(BZ2_bzCompressInit(&strm,9,0,30)==BZ_MEM_ERROR||in.error||out.error||outstr.capacity==(unsigned)-2)
  397.   goto bout;
  398.  int ret=0;
  399.  for(bString *uncompressed;;){
  400.   if((uncompressed=bFileRead(&in,BZIP2_BUFFER))->size==0)break;
  401.   strm.next_in=(char*)uncompressed->data,strm.avail_in=uncompressed->size;
  402.   while(strm.avail_in>0){
  403.    strm.avail_out=BZIP2_BUFFER,strm.next_out=(char*)outstr.data;
  404.    if((ret=BZ2_bzCompress(&strm,BZ_RUN))!=BZ_RUN_OK)goto bout;
  405.    bFileWrite(&out,outstr.data,BZIP2_BUFFER-strm.avail_out);
  406.   }
  407.  }
  408.  for(int fin=0;!fin;){
  409.   strm.avail_out=BZIP2_BUFFER,strm.next_out=(char*)outstr.data;
  410.   if((ret=BZ2_bzCompress(&strm,BZ_FINISH))==BZ_STREAM_END)fin=1;
  411.   else if(ret!=BZ_FINISH_OK)goto bout;
  412.   bFileWrite(&out,outstr.data,BZIP2_BUFFER-strm.avail_out);
  413.  }
  414.  bout:
  415.  BZ2_bzCompressEnd(&strm);
  416.  bStringFree(&outstr);
  417.  bFileFree(&out);
  418.  bFileFree(&in);
  419.  return ret;
  420. }
  421. bString bBzip2Compress(bString uncompressed,int level/*1...9*/){
  422.  bString ret=bStringFrom(0,uncompressed.size+(uncompressed.size/100)+600);
  423.  unsigned destlen=ret.capacity;
  424.  int bzError=BZ2_bzBuffToBuffCompress(ret.data,&destlen,uncompressed.data,uncompressed.size,level,0,30);
  425.  ret.size=destlen;
  426.  return ret;
  427. }
  428. bString bBzip2Uncompress(bString compressed){
  429.  bString ret={0};
  430.  unsigned destlen=0;
  431.  int bzErr=BZ_OUTBUFF_FULL;
  432.  while(bzErr==BZ_OUTBUFF_FULL){
  433.   bStringReserve(&ret,bMax(compressed.size*2,ret.capacity*2));
  434.   destlen=ret.capacity;
  435.   bzErr=BZ2_bzBuffToBuffDecompress((char*)ret.data,&destlen,(char*)compressed.data,compressed.size,0,0);
  436.  }
  437.  return ret.size=destlen,ret;
  438. }
  439. #endif //BEXT_IMPLEMENTATION
  440. #endif //bUSE_BZIP2
  441.  
  442. /******************************** bLZMA ****************************************************************/
  443. #if defined(bUSE_LZMA)
  444. bString bLzmaCompress(bString uncompressed,int level/*0...9*/);
  445. bString bLzmaUncompress(bString compressed);
  446. int bLzmaUncompressFile(char *fileCompressed,char *fileUncompressed);
  447. int bLzmaCompressFile(char *fileUncompressed,char *fileCompressed);
  448. typedef struct b7ZEntry{bString filename;uint64_t size;bDatetime modified;}b7ZEntry;
  449. bDECLARE_ARRAY(bArrayb7ZEntry,b7ZEntry);
  450. typedef struct{ISeekInStream vt;bFile f,flook;}b7ZSeeker;
  451. typedef struct{ILookInStream vt;b7ZSeeker *s;size_t pos;}b7ZLooker;
  452. typedef struct b7zFile{bArrayb7ZEntry entries;CSzArEx db;b7ZSeeker seeker;b7ZLooker looker;}b7zFile;
  453. b7zFile b7zFileFrom(char *filename);
  454. void b7zFileFree(b7zFile *f);
  455. bString b7ZExtract(b7zFile *f,unsigned index);
  456. #if defined (BEXT_IMPLEMENTATION)|| defined(__CLION_IDE__)
  457. bString bLzmaCompress(bString uncompressed,int level/*0...9*/){
  458.  bString ret=bStringFrom(0,uncompressed.size/2);
  459.  CLzmaEncProps props;
  460.  LzmaEncProps_Init(&props);
  461.  props.level=bClip(level,0,9);
  462.  props.writeEndMark=1;
  463.  CLzmaEncHandle enc=LzmaEnc_Create(&g_Alloc);
  464.  SizeT headersize=LZMA_PROPS_SIZE,outlen=0;
  465.  SRes res=LzmaEnc_SetProps(enc,&props);
  466.  for(;ret.capacity!=(unsigned)-2;){
  467.   outlen=ret.capacity-5,res=LzmaEnc_WriteProperties(enc,ret.data,&headersize);
  468.   if((res=LzmaEnc_MemEncode(enc,ret.data+5,&outlen,uncompressed.data,uncompressed.size,
  469.    1,0,&g_Alloc,&g_Alloc)==SZ_ERROR_OUTPUT_EOF))bStringReserve(&ret,ret.capacity*2);
  470.   else break;
  471.  }
  472.  LzmaEnc_Destroy(enc,&g_Alloc,&g_Alloc);
  473.  if(res==SZ_OK)ret.size=(unsigned)outlen+5;
  474.  return ret;
  475. }
  476. bString bLzmaUncompress(bString compressed){
  477.  bString ret=bStringFrom(0,compressed.size*2);
  478.  if(compressed.size<LZMA_PROPS_SIZE||ret.capacity==(unsigned)-2)return ret;
  479.  CLzmaDec state;
  480.  LzmaDec_Construct(&state);
  481.  SRes res=LzmaDec_Allocate(&state,compressed.data,LZMA_PROPS_SIZE,&g_Alloc);
  482.  if(res!=SZ_OK)return ret.capacity=(unsigned)-2,ret;
  483.  LzmaDec_Init(&state);
  484.  ELzmaStatus status=LZMA_STATUS_NOT_FINISHED;
  485.  SizeT inputPos=0,outputPos=0,outlen=0,inTotal=compressed.size-LZMA_PROPS_SIZE,inlen;
  486.  while(inputPos<inTotal){
  487.   inlen=inTotal-inputPos,outlen=ret.capacity-outputPos;
  488.   res=LzmaDec_DecodeToBuf(&state,ret.data+outputPos,&outlen,compressed.data+LZMA_PROPS_SIZE+inputPos,
  489.    &inlen,LZMA_FINISH_END,&status);
  490.   inputPos+=inlen,outputPos+=outlen;
  491.   ret.size=(unsigned)outputPos;
  492.   if(status==LZMA_STATUS_NOT_FINISHED)bStringReserve(&ret,ret.capacity*2);
  493.   else break;
  494.  }
  495.  memset(ret.data+ret.size,0,ARRAY_EXTRA);
  496.  LzmaDec_Free(&state,&g_Alloc);
  497.  if(status!=LZMA_STATUS_FINISHED_WITH_MARK&&status!=LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
  498.   ret.capacity=(unsigned)-2;
  499.  return ret;
  500. }
  501. #define bLZMA_INBUF_SIZE 4194304
  502. #define bLZMA_OUTBUF_SIZE 4194304
  503. int bLzmaUncompressFile(char *fileCompressed,char *fileUncompressed){
  504.  bFile in=bFileFrom(fileCompressed,bFILE_READ),
  505.   out=bFileFrom(fileUncompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
  506.  bString *read=bFileRead(&in,LZMA_PROPS_SIZE);
  507.  CLzmaDec state;
  508.  LzmaDec_Construct(&state);
  509.  int ret=0;
  510.  SRes res=LzmaDec_Allocate(&state,read->data,read->size,&g_Alloc);
  511.  if(res!=SZ_OK||in.error||out.error){ret=1;goto lout;}
  512.  LzmaDec_Init(&state);
  513.  ELzmaStatus status=LZMA_STATUS_NOT_FINISHED;
  514.  bString outbuf=bStringFrom(0,bLZMA_OUTBUF_SIZE);
  515.  while(1){
  516.   if((read=bFileRead(&in,bLZMA_INBUF_SIZE))->size==0)break;
  517.   SizeT srcLen=read->size,srcProcessed=0,destLen,srcLenToProcess;
  518.   while(srcProcessed<read->size){
  519.    destLen=outbuf.capacity,srcLenToProcess=srcLen,res=LzmaDec_DecodeToBuf(&state,outbuf.data,
  520.     &destLen,read->data+srcProcessed,&srcLenToProcess,LZMA_FINISH_ANY,&status);
  521.    if(res!=SZ_OK){ret=1;goto lout;}
  522.    bFileWrite(&out,outbuf.data,destLen);
  523.    srcProcessed+=srcLenToProcess;
  524.    srcLen-=srcLenToProcess;
  525.    if(status==LZMA_STATUS_FINISHED_WITH_MARK)break;
  526.   }
  527.   if(status==LZMA_STATUS_FINISHED_WITH_MARK)break;
  528.  }
  529.  lout:return LzmaDec_Free(&state,&g_Alloc),bFileFree(&out),bFileFree(&in),ret;
  530. }
  531. typedef struct{ISeqInStream vt;bFile *file;}bLzmaFileInStream;
  532. SRes bLzmaFileInStream_Read(const ISeqInStream *pp,void *buf,size_t *size){
  533.  bLzmaFileInStream *p=(bLzmaFileInStream*)pp;
  534.  bString *str=bFileRead(p->file,(unsigned)*size);
  535.  if(p->file->error) return SZ_ERROR_READ;
  536.  memcpy(buf,str->data,str->size);
  537.  *size=str->size;
  538.  return SZ_OK;
  539. }
  540. typedef struct{ISeqOutStream vt;bFile *file;}bLzmaFileOutStream;
  541. size_t bLzmaFileOutStream_Write(const ISeqOutStream *pp,const void *buf,size_t size){
  542.  bLzmaFileOutStream *p=(bLzmaFileOutStream*)pp;
  543.  bFileWrite(p->file,(void*)buf,size);
  544.  return p->file->error?0:size;
  545. }
  546. int bLzmaCompressFile(char *fileUncompressed,char *fileCompressed){
  547.  bFile in=bFileFrom(fileUncompressed,bFILE_READ),
  548.   out=bFileFrom(fileCompressed,bFILE_WRITE|bFILE_CREATE_IF_NOT_EXISTS);
  549.  SRes res=0;
  550.  CLzmaEncProps props;
  551.  LzmaEncProps_Init(&props);
  552.  props.level=9,props.writeEndMark=1;
  553.  CLzmaEncHandle enc=LzmaEnc_Create(&g_Alloc);
  554.  if(!enc||in.error||out.error){res=1;goto lout;}
  555.  Byte header[LZMA_PROPS_SIZE];
  556.  SizeT headerSize=LZMA_PROPS_SIZE;
  557.  LzmaEnc_WriteProperties(enc,header,&headerSize);
  558.  bFileWrite(&out,header,headerSize);
  559.  bLzmaFileInStream inStream={.vt.Read=bLzmaFileInStream_Read,.file=&in};
  560.  bLzmaFileOutStream outStream={.vt.Write=bLzmaFileOutStream_Write,.file=&out};
  561.  res=LzmaEnc_Encode(enc,&outStream.vt,&inStream.vt,0,&g_Alloc,&g_Alloc);
  562.  lout:return LzmaEnc_Destroy(enc,&g_Alloc,&g_Alloc),bFileFree(&in),bFileFree(&out),res;
  563. }
  564. SRes b7ZSeeker_Read(void *pp,void *buf,size_t *size){
  565.  bString *r=bFileRead(&((b7ZSeeker*)pp)->f,(unsigned)*size);
  566.  return memcpy(buf,r->data,(*size)=r->size),SZ_OK;
  567. }
  568. SRes b7ZSeeker_Seek(void *pp,Int64 *pos,ESzSeek origin){
  569.  b7ZSeeker *s=(b7ZSeeker*)pp;
  570.  Int64 newpos=0;
  571.  switch(origin){
  572.   case SZ_SEEK_SET:break((newpos=*pos));
  573.   case SZ_SEEK_CUR:break((newpos=bFileGetCursor(&s->f)+*pos));
  574.   case SZ_SEEK_END:break((newpos=bFileGetSize(&s->f)+*pos));
  575.  }
  576.  if(newpos<0||newpos>(int64_t)bFileGetSize(&s->f))return SZ_ERROR_FAIL;
  577.  bFileSetCursor(&s->f,(uint64_t)newpos);
  578.  return (*pos)=newpos,SZ_OK;
  579. }
  580. SRes b7ZLooker_Look(void *pp,const void **buf,size_t *size){
  581.  b7ZLooker *s=(b7ZLooker*)pp;
  582.  bFileSetCursor(&s->s->flook,bFileGetCursor(&s->s->f));
  583.  bString *r=bFileRead(&s->s->flook,(unsigned)*size);
  584.  return *buf=r->data,*size=r->size,SZ_OK;
  585. }
  586. SRes b7ZLooker_Skip(void *pp,size_t offset){
  587.  return bFileSetCursor(&((b7ZLooker*)pp)->s->f,bFileGetCursor(&((b7ZLooker*)pp)->s->f)+offset),SZ_OK;
  588. }
  589. SRes b7ZLooker_Read(void *pp,void *buf,size_t *size){
  590.  return b7ZSeeker_Read(((b7ZLooker*)pp)->s,buf,size);
  591. }
  592. SRes b7ZLooker_Seek(void *pp,Int64 *pos,ESzSeek origin){
  593.  return b7ZSeeker_Seek(((b7ZLooker*)pp)->s,pos,origin);
  594. }
  595. void b7ZEntryFree(b7ZEntry *entry){bStringFree(&entry->filename);}
  596. int b7ZEntryCollate(b7ZEntry *l,b7ZEntry *r){return bCollateStringFast(&l->filename,&r->filename);}
  597. bDEFINE_ARRAY(bArrayb7ZEntry,b7ZEntry,b7ZEntryFree,b7ZEntryCollate);
  598. b7zFile b7zFileFrom(char *filename){
  599.  b7zFile ret={.seeker={.f=bFileFrom(filename,bFILE_READ),.flook=bFileFrom(filename,bFILE_READ),
  600.   .vt.Seek=b7ZSeeker_Seek,.vt.Read=b7ZSeeker_Read}};
  601.  ret.looker=(b7ZLooker){.s=&ret.seeker,
  602.   .vt={.Read=b7ZLooker_Read,.Seek=b7ZLooker_Seek,.Look=b7ZLooker_Look,.Skip=b7ZLooker_Skip}};
  603.  static int b7ZCrcInit=0;
  604.  if(!b7ZCrcInit){
  605.   bAssert(bThreadIsMain());
  606.   CrcGenerateTable();
  607.   b7ZCrcInit=1;
  608.  }
  609.  SzArEx_Init(&ret.db);
  610.  SRes res=SzArEx_Open(&ret.db,&ret.looker.vt,&g_Alloc,&g_Alloc);
  611.  for(UInt32 i=0;i<ret.db.NumFiles;i++){
  612.   size_t len=SzArEx_GetFileNameUtf16(&ret.db,i,0);
  613.   bString n16=bStringFrom(0,len*2);
  614.   SzArEx_GetFileNameUtf16(&ret.db,i,(UInt16*)n16.data);
  615.   bString n8=bStringFromUtf16ToUtf8((uint16_t*)n16.data);
  616.   UInt64 fileSize=SzArEx_GetFileSize(&ret.db,i);
  617.   CNtfsFileTime mod=ret.db.MTime.Vals[i];
  618.   bDatetime dt=bDatetimeFromWinFiletime(bUint64(mod.Low,mod.High));
  619.   bArrayb7ZEntryAdd(&ret.entries,(b7ZEntry){.filename=n8,.size=fileSize,.modified=dt});
  620.   bStringFree(&n16);
  621.  }
  622.  return ret;
  623. }
  624. void b7zFileFree(b7zFile *f){
  625.  bFileFree(&f->seeker.f);
  626.  bFileFree(&f->seeker.flook);
  627.  SzArEx_Free(&f->db,&g_Alloc);
  628. }
  629. bString b7ZExtract(b7zFile *f,unsigned index){
  630.  if(index>=f->entries.size||SzArEx_IsDir(&f->db,index))return (bString){0};
  631.  f->looker.s=&f->seeker;
  632.  UInt32 blockIndex=0xFFFFFFFF;
  633.  Byte *outBuffer=NULL;
  634.  size_t outBufferSize=0,offset=0,outSizeProcessed=0;
  635.  SRes res=SzArEx_Extract(&f->db,&f->looker.vt,(UInt32)index,&blockIndex,&outBuffer,&outBufferSize,
  636.   &offset,&outSizeProcessed,&g_Alloc,&g_Alloc);
  637.  return bStringFrom(outBuffer+offset,outSizeProcessed);
  638. }
  639. #endif //BEXT_IMPLEMENTATION
  640. #endif //bUSE_LZMA
  641.  
  642.  
  643. And libdeflate:
  644. bString bLibdeflateCompress(bString uncompressed,int level/*0...123*/,int zlibHeader){
  645.  bString ret={0},*u=&uncompressed;
  646.  struct libdeflate_compressor *compressor=libdeflate_alloc_compressor(level);
  647.  bStringReserve(&ret,(unsigned)(zlibHeader==1?libdeflate_zlib_compress_bound(compressor,u->size):
  648.   zlibHeader==2?libdeflate_gzip_compress_bound(compressor,uncompressed.size):
  649.   libdeflate_deflate_compress_bound(compressor,uncompressed.size)));
  650.  if(!compressor||ret.capacity==(unsigned)-2)
  651.   return libdeflate_free_compressor(compressor),ret.capacity=(unsigned)-2,ret;
  652.  ret.size=(unsigned)(
  653.   zlibHeader==1?libdeflate_zlib_compress(compressor,u->data,u->size,ret.data,ret.capacity):
  654.   zlibHeader==2?libdeflate_gzip_compress(compressor,u->data,u->size,ret.data,ret.capacity):
  655.   libdeflate_deflate_compress(compressor,u->data,u->size,ret.data,ret.capacity));
  656.  libdeflate_free_compressor(compressor);
  657.  return ret;
  658. }
  659. bString bLibdeflateUncompess(bString compressed){
  660.  bString ret=bStringFrom(0,compressed.size*3);
  661.  uint32_t header=*(bUnaligned32*)compressed.data,pos=(header&8207)==8200?6:
  662.   ((!(header&7))&&(((header>>8)&255)!=(~(header>>24)&255)))?2:0;
  663.  if((header&65535)==35615&&compressed.size>10)
  664.   if(pos=10,header&134217728){while(*(compressed.data+pos))pos++;pos++;}
  665.  compressed.data+=pos,compressed.size-=pos;
  666.  struct libdeflate_decompressor *d=libdeflate_alloc_decompressor();
  667.  if(!d)return ret.capacity=(unsigned)-2,ret;
  668.  size_t outsize=0;
  669.  for(enum libdeflate_result result;;){
  670.   result=libdeflate_deflate_decompress(d,compressed.data,compressed.size,ret.data,ret.capacity,&outsize);
  671.   if(result==LIBDEFLATE_SUCCESS){break(ret.size=outsize)}
  672.   else if(result==LIBDEFLATE_BAD_DATA){break(bStringFree(&ret))}
  673.   else if(result==LIBDEFLATE_INSUFFICIENT_SPACE)bStringReserve(&ret,ret.capacity*2);
  674.  }
  675.  return libdeflate_free_decompressor(d),ret;
  676. }
  677.  
  678.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement