#include #include #include #include #include #define MIN_MATCH 3 #define MAX_MATCH 65535 #define GREEDY_MAX 258 #define LONG_BASE 258 static inline int len_extra_bits(int L){ return (L<10)?0:((L escape len==0 */ #define LZSS_HEADER_LEN 20 /* magic u32 + version u32 + len u64 + adler u32 */ #define LITMODE_BITS 3 /* v5+: 5 modos */ #define BCJ_MARGIN 256 /* cover extra (bytes) p/ ligar o BCJ (~2Kb salvos) */ #define BCJ_GATE 8 /* E8/E9 mínimos no bloco p/ tentar */ #define DP_NCAND 32 /* total: 12+12+8 (+3 pinos); arrays têm +4 */ #define DP_NLEN 12 /* top por len (cover global) */ #define DP_NSAVE 12 /* top por save (global) */ #define DP_NREC 8 /* top por save entre recentes (dist<=4096) */ #define DP_RECDIST 4096 #define DP_DEPTH 256 /* profundidade da chain por posição (igual greedy) */ #define JUDGE_DECAY 0.99f /* janela ~100 literais (modo MIX) */ #define NLENCTX 3 static inline int len_cls(int len){ return (len<6)?0:((len<10)?1:2); } #define EMIT_REPBIT(b) do{ if(!repctx) bw_write_bit(&bw,(b)); }while(0) // ========= ENDIAN SAFE LE64/LE32 (fixes v2.0d bug on BE) ========= static void write_le32(FILE *f, uint32_t v){ uint8_t b[4]; b[0]=(uint8_t)(v); b[1]=(uint8_t)(v>>8); b[2]=(uint8_t)(v>>16); b[3]=(uint8_t)(v>>24); fwrite(b,1,4,f); } static void write_le64(FILE *f, uint64_t v){ uint8_t b[8]; b[0]=(uint8_t)(v); b[1]=(uint8_t)(v>>8); b[2]=(uint8_t)(v>>16); b[3]=(uint8_t)(v>>24); b[4]=(uint8_t)(v>>32); b[5]=(uint8_t)(v>>40); b[6]=(uint8_t)(v>>48); b[7]=(uint8_t)(v>>56); fwrite(b,1,8,f); } static int read_le32(FILE *f, uint32_t *out){ uint8_t b[4]; if(fread(b,1,4,f)!=4) return 0; *out = ((uint32_t)b[0]) | ((uint32_t)b[1]<<8) | ((uint32_t)b[2]<<16) | ((uint32_t)b[3]<<24); return 1; } static int read_le64(FILE *f, uint64_t *out){ uint8_t b[8]; if(fread(b,1,8,f)!=8) return 0; *out = ((uint64_t)b[0]) | ((uint64_t)b[1]<<8) | ((uint64_t)b[2]<<16) | ((uint64_t)b[3]<<24) | ((uint64_t)b[4]<<32) | ((uint64_t)b[5]<<40) | ((uint64_t)b[6]<<48) | ((uint64_t)b[7]<<56); return 1; } // ---- 20B header: magic + version + total_len + adler (all LE) ---- static void write_header_placeholder(FILE *f){ write_le32(f, LZSS_MAGIC); write_le32(f, LZSS_VERSION); write_le64(f, 0); write_le32(f, 0); } static void write_header_backpatch(FILE *f, uint64_t total_len, uint32_t adler){ write_le32(f, LZSS_MAGIC); write_le32(f, LZSS_VERSION); write_le64(f, total_len); write_le32(f, adler); } // returns 0 ok, 1 bad-magic (incl. legacy magic-less files), 2 newer version, // 3 truncated, 4 older version (use older binary or re-compress). // v2.3 decoda v2 e v3 (versao sai em *version). static int read_header(FILE *f, uint64_t *total_len, uint32_t *adler, uint32_t *pver){ uint32_t magic = 0, ver = 0; if(!read_le32(f, &magic)) return 3; // Legacy detect: v2.0d and older start with total_len u64 LE, no magic. // A legacy len < 2^32 has low byte != 0x4C or second dword != version range, // but instead of heuristics: strict magic check, clear message. if(magic != LZSS_MAGIC) return 1; if(!read_le32(f, &ver)) return 3; if(ver > LZSS_VERSION) return 2; if(ver < 2) return 4; // v2.0d- (sem magic) e v1: outro binário if(pver) *pver = ver; if(!read_le64(f, total_len)) return 3; if(!read_le32(f, adler)) return 3; return 0; } uint32_t calcular_adler32(const uint8_t *data, size_t len){ uint32_t a=1,b=0; for(size_t i=0;i> 1) & 1) typedef struct { uint32_t freq; int sym; } FreqSym; typedef struct { uint32_t freq; int left; int right; int sym; } HNode; static int cmp_freq(const void *a, const void *b){ const FreqSym *fa=a,*fb=b; if(fa->freq!=fb->freq) return (fa->freqfreq)?-1:1; return fa->sym-fb->sym; } static void huff_assign_depth(HNode *nodes,int idx,int depth,uint8_t *lens){ if(idx<0) return; if(nodes[idx].sym>=0){if(depth<1) depth=1; if(depth>15) depth=16; lens[nodes[idx].sym]=(uint8_t)depth; return;} huff_assign_depth(nodes,nodes[idx].left,depth+1,lens); huff_assign_depth(nodes,nodes[idx].right,depth+1,lens); } static int build_huffman_lengths(const uint32_t *freq,uint8_t *lens){ memset(lens,0,256); FreqSym fs[256]; int n=0; for(int i=0;i<256;i++) if(freq[i]){fs[n].freq=freq[i]; fs[n].sym=i; n++;} if(n==0) return 0; if(n==1){lens[fs[0].sym]=1; return 1;} qsort(fs,n,sizeof(FreqSym),cmp_freq); HNode nodes[511]; for(int i=0;i1){int m1=-1,m2=-1; for(int i=0;i=511) break;} int root=avail[0]; huff_assign_depth(nodes,root,0,lens); int cnt=0; for(int i=0;i<256;i++) if(lens[i]){if(lens[i]>15) return -1; cnt++;} return cnt; } static void build_canonical(const uint8_t *lens,uint32_t *codes){ memset(codes,0,256*sizeof(uint32_t)); int bl_count[16]={0}; for(int i=0;i<256;i++) if(lens[i]) bl_count[lens[i]]++; uint32_t code=0; uint32_t next_code[16]={0}; for(int bits=1;bits<=15;bits++){code=(code+bl_count[bits-1])<<1; next_code[bits]=code;} int order[256]; int on=0; for(int l=1;l<=15;l++) for(int s=0;s<256;s++) if(lens[s]==l) order[on++]=s; for(int i=0;ilens,lens,256); build_canonical(lens,d->codes); d->nsyms=0; for(int i=0;i<256;i++) if(lens[i]) d->nsyms++;} typedef struct { FILE *f; uint8_t cur; int nbits; } BitWriter; void bw_init(BitWriter *w,FILE *f){w->f=f; w->cur=0; w->nbits=0;} /* EMIT_FLAG: em blocos flagctx as flags match/lit vão p/ stream RC próprio */ #define EMIT_FLAG(b) do{ if(!fctx) bw_write_bit(&bw,(b)); }while(0) void bw_write_bit(BitWriter *w,int bit){w->cur=(uint8_t)((w->cur<<1)|(bit&1)); w->nbits++; if(w->nbits==8){fputc(w->cur,w->f); w->cur=0; w->nbits=0;}} void bw_write_bits(BitWriter *w,uint32_t v,int n){for(int i=n-1;i>=0;i--) bw_write_bit(w,(v>>i)&1);} void bw_flush(BitWriter *w){if(w->nbits>0){w->cur<<=(8-w->nbits); fputc(w->cur,w->f); w->cur=0; w->nbits=0;}} /* v3.9: árvore compacta — kind 00 vazia (só len-ctx), 01 singleton + símbolo direto (len sempre 1, convenção do build), 10 bitmap legado + lens 4b. */ static void bw_tree(BitWriter *w,uint8_t *lens,int n,int symbits){ int cnt=0,sym=0; for(int s=0;sf=f; r->buf=0; r->cnt=0; r->eof=0;} int br_read_bit(BitReader *r){if(r->cnt==0){int c=fgetc(r->f); if(c==EOF){r->eof=1; return 0;} r->buf=(uint8_t)c; r->cnt=8;} r->cnt--; return (r->buf>>r->cnt)&1;} uint32_t br_read_bits(BitReader *r,int n){uint32_t v=0; for(int i=0;i=18): 00 vazia, 01 singleton (len 1), 10 bitmap + lens 4b. Retorna nº de símbolos ou -1 (erro). ll deve ter 256B zerados. */ static int br_tree(BitReader *r,uint8_t *ll,int n,int symbits){ int k=(int)br_read_bits(r,2); if(r->eof) return -1; if(k==0) return 0; if(k==1){ int s=(int)br_read_bits(r,symbits); if(r->eof||s<0||s>=n) return -1; ll[s]=1; return 1; } if(k!=2) return -1; for(int s=0;seof) return -1; } for(int s=0;seof||ll[s]==0||ll[s]>15) return -1; } int cnt=0; for(int s=0;scnt=0;} static int huffdec_decode(BitReader *r,HuffDec *d){uint32_t code=0; for(int len=1;len<=15;len++){if(r->eof) return -1; code=(code<<1)|(uint32_t)br_read_bit(r); for(int s=0;s<256;s++) if(d->lens[s]==len&&d->codes[s]==code) return s;} return -1;} // ========= RANGE CODER order-0 adaptive, bytewise, carry-cache (v2.3 teste) ========= // Nucleo estilo LZMA/bzip: low 32b + range 32b, renormaliza quando range < 2^24, // cache de carry com contador. Modelo adaptativo 256 simbolos, init 1, teto 16383. // Encoder e decoder partem do mesmo estado -> tabela zero, ideal p/ medir ganho // real sobre o Huffman com tabela da v2.2 e base p/ dual-fase (A/B + juiz). typedef struct { FILE *f; uint32_t low, range; uint8_t cache; int cacheSize; } RCEnc_UNUSED; typedef struct { uint32_t freq[256]; uint32_t tot; } RCModel; static void rcmodel_init(RCModel *m){ for(int i=0;i<256;i++) m->freq[i]=1; m->tot=256; } static void rcmodel_rescale(RCModel *m){ m->tot=0; for(int i=0;i<256;i++){ m->freq[i]>>=1; if(m->freq[i]==0) m->freq[i]=1; m->tot+=m->freq[i]; } } // ---- núcleo range ativo: RCW (encoder p/ FILE) + RCMem (decoder de memória) ---- typedef struct { FILE *f; uint64_t low; uint32_t range; uint8_t cache; uint32_t cacheSize; } RCW; static void rcw_init(RCW *e, FILE *f){ e->f=f; e->low=0; e->range=0xFFFFFFFFu; e->cache=0; e->cacheSize=1; } static void rcw_shift(RCW *e){ /* ShiftLow canonico: descarrega quando topo<0xFF ou carry pendente (low>>32). Topo==0xFF sem carry: so conta (carry futuro pode propaga-lo). */ if((uint32_t)e->low < 0xFF000000u || (e->low >> 32) != 0){ uint8_t tmp = e->cache; do { fputc((int)(tmp + (uint8_t)(e->low >> 32)), e->f); tmp = 0xFF; } while(--e->cacheSize != 0); e->cache = (uint8_t)(((uint32_t)e->low >> 24) & 0xFF); } e->cacheSize++; e->low = (uint64_t)(uint32_t)(e->low << 8); // wrap 32b: acima do bit 31 só vive carry do += do encode } static void rcw_encode(RCW *e, RCModel *m, int sym){ uint32_t cum=0; for(int i=0;ifreq[i]; uint32_t total=m->tot, fsym=m->freq[sym]; e->low += (uint64_t)cum * (e->range /= total); e->range *= fsym; while(e->range < 0x01000000u){ rcw_shift(e); e->range <<= 8; } m->freq[sym]++; m->tot++; if(m->tot > 16383) rcmodel_rescale(m); } static void rcw_flush(RCW *e){ for(int i=0;i<5;i++){ rcw_shift(e); e->range <<= 8; } } typedef struct { FILE *f; uint32_t code, range; uint64_t low; int init; } RCR; // decoder espelho: lê 5 bytes iniciais, depois renormaliza igual typedef struct { const uint8_t *p; size_t n, pos; uint32_t code, range; } RCMem; static void rcp_init(RCMem *d, const uint8_t *buf, size_t n){ d->p=buf; d->n=n; d->pos=0; d->code=0; d->range=0xFFFFFFFFu; for(int i=0;i<5 && d->poscode=(d->code<<8)|d->p[d->pos++]; } } static int rcp_decode(RCMem *d, RCModel *m){ uint32_t total=m->tot; uint32_t count = d->code / (d->range /= total); // encontra símbolo pelo cumulativo (decoder usa range já dividido: reconstroi) // forma canônica: count = code / (range/total) uint32_t cum=0; int sym=0; for(sym=0;sym<256;sym++){ uint32_t f=m->freq[sym]; if(count < cum+f) break; cum+=f; } if(sym>=256) return -1; d->code -= cum * d->range; d->range *= m->freq[sym]; while(d->range < 0x01000000u){ uint8_t b = (d->posn)? d->p[d->pos++] : 0; d->code = (d->code<<8)|b; d->range <<= 8; } m->freq[sym]++; m->tot++; if(m->tot > 16383) rcmodel_rescale(m); return sym; } // ========= RANGE order-1 byte-context (v2.4): N_CTX classes x 256 syms, adaptativo === // ctx = byte anterior >> 4 (nibble alto): 16 classes, warmup 16x menor que 256. // Sem tabela: encoder e decoder partem de freq 1. ~16KB via malloc. #define N_CTX 16 /* R1_RESCALE: teto do total por contexto order-1 (agressividade). 1024=agressivo, 16384=calmo. Override via -DR1_RESCALE=... */ #ifndef R1_RESCALE #define R1_RESCALE 4096 #endif typedef struct { uint32_t f[N_CTX][256]; uint32_t tot[N_CTX]; } RCModel1; static void rcmodel1_reset(RCModel1 *m){ for(int c=0;cf[c][s]=1; m->tot[c]=256; } } static void rcmodel1_rescale_ctx(RCModel1 *m, int ctx){ m->tot[ctx]=0; for(int i=0;i<256;i++){ m->f[ctx][i]>>=1; if(m->f[ctx][i]==0) m->f[ctx][i]=1; m->tot[ctx]+=m->f[ctx][i]; } } static void rcw_encode1(RCW *e, RCModel1 *m, int ctx, int sym){ uint32_t cum=0; for(int i=0;if[ctx][i]; uint32_t total=m->tot[ctx], fsym=m->f[ctx][sym]; e->low += (uint64_t)cum * (e->range /= total); e->range *= fsym; while(e->range < 0x01000000u){ rcw_shift(e); e->range <<= 8; } m->f[ctx][sym]++; m->tot[ctx]++; if(m->tot[ctx] > R1_RESCALE) rcmodel1_rescale_ctx(m,ctx); } static int rcp_decode1(RCMem *d, RCModel1 *m, int ctx){ uint32_t total=m->tot[ctx]; uint32_t count = d->code / (d->range /= total); uint32_t cum=0; int sym=0; for(sym=0;sym<256;sym++){ uint32_t f=m->f[ctx][sym]; if(count < cum+f) break; cum+=f; } if(sym>=256) return -1; d->code -= cum * d->range; d->range *= m->f[ctx][sym]; while(d->range < 0x01000000u){ uint8_t b = (d->posn)? d->p[d->pos++] : 0; d->code = (d->code<<8)|b; d->range <<= 8; } m->f[ctx][sym]++; m->tot[ctx]++; if(m->tot[ctx] > R1_RESCALE) rcmodel1_rescale_ctx(m,ctx); return sym; } /* custo pós-update em 1/256 bit (ordem idêntica encoder/decoder; ver modo MIX) */ static float rccost(uint32_t f, uint32_t tot){ float p=(float)f/(float)tot; if(p<0.0005f) p=0.0005f; return -256.0f*log2f(p); } /* ========= RC binário order-1 p/ flags (v2.6): 2 ctx x 2 syms, fresco/bloco ==== */ typedef struct { uint32_t f0,f1,tot; } BModel2; static void bmodel2_init(BModel2 *m){ m->f0=m->f1=1; m->tot=2; } static void bmodel2_upd(BModel2 *m,int bit){ if(bit){ m->f1++; } else { m->f0++; } m->tot++; if(m->tot>512){ m->f0=(m->f0+1)>>1; m->f1=(m->f1+1)>>1; if(!m->f0)m->f0=1; if(!m->f1)m->f1=1; m->tot=m->f0+m->f1; } } static void rcb_encode(RCW *e, BModel2 *m, int bit){ uint32_t cum = bit ? m->f0 : 0; uint32_t fs = bit ? m->f1 : m->f0; uint32_t total = m->tot; e->low += (uint64_t)cum * (e->range /= total); e->range *= fs; while(e->range < 0x01000000u){ rcw_shift(e); e->range <<= 8; } bmodel2_upd(m,bit); } static int rcb_decode(RCMem *d, BModel2 *m){ uint32_t total = m->tot; uint32_t count = d->code / (d->range /= total); int bit = (count >= m->f0) ? 1 : 0; d->code -= (bit ? m->f0 : 0) * d->range; d->range *= bit ? m->f1 : m->f0; while(d->range < 0x01000000u){ uint8_t b = (d->posn)? d->p[d->pos++] : 0; d->code = (d->code<<8)|b; d->range <<= 8; } bmodel2_upd(m,bit); return bit; } /* ========= leitor de bits em memória (corpos do flagctx, v2.6) ========= */ typedef struct { const uint8_t *p; size_t n, bytepos; uint8_t cur; int bits; int eof; } MBR; static void mbr_init(MBR *m, const uint8_t *p, size_t n){ m->p=p; m->n=n; m->bytepos=0; m->cur=0; m->bits=0; m->eof=0; } static int mbr_bit(MBR *m){ if(m->bits==0){ if(m->bytepos>=m->n){ m->eof=1; return 0; } m->cur=m->p[m->bytepos++]; m->bits=8; } m->bits--; return (m->cur>>m->bits)&1; } static uint32_t mbr_bits(MBR *m,int n){ uint32_t v=0; for(int i=0;ieof) return -1; code=(code<<1)|(uint32_t)mbr_bit(r); for(int s=0;s<256;s++) if(d->lens[s]==len&&d->codes[s]==code) return s; } return -1; } #define NSLOTS 38 // lzip-style slots for real distance d in [1,524287] (z=d-1) #define FAR_LIM 131071 /* além da janela v36: pedágio só no greedy */ #ifndef FAR_PEN #define FAR_PEN 16 /* save extra exigido p/ greedy pegar match far (DP segue livre, com custos exatos + guard) */ #endif // slot on zero-based z: 0..3 direct; else (msb_pos-1)*2+nextbit (lzip table) static inline int get_slot(uint32_t d){ uint32_t z = d - 1; if(z < 4) return (int)z; int m = 0; uint32_t v = z; while(v){ m++; v >>= 1; } return (m - 1) * 2 + (int)((z >> (m - 2)) & 1); } static inline int slot_footer_bits(int s){ return (s < 4) ? 0 : ((s >> 1) - 1); } static inline uint32_t slot_base(int s){ return ((2u | ((uint32_t)(s & 1))) << (uint32_t)((s >> 1) - 1)); } // s>=4 /* ========= RC order-1 p/ slots (v2.7): 4 classes x NSLOTS syms, fresco/bloco ===== */ #define NSLOTCTX 4 static inline int slot_cls(int s){ return (s<4)?0:((s<8)?1:((s<16)?2:3)); } typedef struct { uint32_t f[NSLOTCTX][NSLOTS]; uint32_t tot[NSLOTCTX]; } SModel; static void smodel_init(SModel *m){ for(int c=0;cf[c][s]=1; m->tot[c]=NSLOTS; } } static void smodel_upd(SModel *m,int ctx,int sym){ m->f[ctx][sym]++; m->tot[ctx]++; if(m->tot[ctx]>1024){ m->tot[ctx]=0; for(int i=0;if[ctx][i]>>=1; if(!m->f[ctx][i]) m->f[ctx][i]=1; m->tot[ctx]+=m->f[ctx][i]; } } } static void src_encode(RCW *e, SModel *m, int ctx, int sym){ uint32_t cum=0; for(int i=0;if[ctx][i]; uint32_t total=m->tot[ctx], fsym=m->f[ctx][sym]; e->low += (uint64_t)cum * (e->range /= total); e->range *= fsym; while(e->range < 0x01000000u){ rcw_shift(e); e->range <<= 8; } smodel_upd(m,ctx,sym); } static int src_decode(RCMem *d, SModel *m, int ctx){ uint32_t total=m->tot[ctx]; uint32_t count = d->code / (d->range /= total); uint32_t cum=0; int sym=0; for(sym=0;symf[ctx][sym]; if(count < cum+f) break; cum+=f; } if(sym>=NSLOTS) return -1; d->code -= cum * d->range; d->range *= m->f[ctx][sym]; while(d->range < 0x01000000u){ uint8_t b = (d->posn)? d->p[d->pos++] : 0; d->code = (d->code<<8)|b; d->range <<= 8; } smodel_upd(m,ctx,sym); return sym; } static inline uint32_t quick_hash(const uint8_t *ptr){return ((uint32_t)(ptr[0]<<8) ^ (uint32_t)(ptr[1]<<4) ^ (uint32_t)ptr[2]) & HASH_MASK;} // DS32 BE-safe match: uses memcmp (endian agnostic) not uint64 compare int find_match_ds32(uint8_t *in,int64_t rbase,uint64_t tab_epoch,uint64_t global_pos,uint64_t block_end,int32_t *head,int32_t *prev,int *best_off,int *use_large){ int best_len_s=0,best_off_s=0,best_len_l=0,best_off_l=0; if(block_end<=global_pos) return 0; uint64_t remain=block_end-global_pos; uint64_t max=remain>GREEDY_MAX?GREEDY_MAX:remain; if(max=global_pos) break; uint64_t distance=global_pos-match_pos; if(distance>(uint64_t)WS_LARGE) break; if(distance==0) break; int l=0; // BE-safe fast path: memcmp 8 bytes (not uint64 equality that is ok but pedantic) while((uint64_t)l+8<=max){ if(memcmp(&in[ridx(rbase,match_pos+l)], &in[ridx(rbase,global_pos+l)], 8)!=0) break; l+=8; } while((uint64_t)l=MIN_MATCH && l>best_len_s){best_len_s=l; best_off_s=(int)distance; if(best_len_s==GREEDY_MAX){best_len_l=best_len_s; best_off_l=best_off_s; break;}} if(l>=MIN_MATCH && l>best_len_l){best_len_l=l; best_off_l=(int)distance; if(best_len_l==GREEDY_MAX) break;} craw=prev[match_pos & (uint64_t)WS_LARGE]; } if(best_len_s==LONG_BASE) best_len_s=LONG_BASE-1; if(best_len_l==LONG_BASE) best_len_l=LONG_BASE; if(best_len_s7){*best_off=best_off_l; *use_large=1; return best_len_l;} else {*best_off=best_off_s; *use_large=0; return best_len_s;} } static void hash_insert(uint8_t *buf,int64_t rbase,uint64_t ring_lim,uint64_t pos,int32_t *head,int32_t *prev){ if(pos+MIN_MATCH>ring_lim) return; uint32_t h=quick_hash(&buf[ridx(rbase,pos)]); prev[pos & (uint64_t)WS_LARGE]=head[h]; head[h]=(int32_t)pos; } // ========= BCJ x86 (v3.0): E8/E9 rel32 <-> abs, base = offset global ========= // Só opcode completo ([p,p+5) dentro do bloco). Ida e volta exatas. static void bcj_fwd(uint8_t *buf,int64_t rbase,uint64_t start,uint64_t end){ for(uint64_t p=start;p+5<=end;){ uint8_t op=buf[ridx(rbase,p)]; if(op==0xE8||op==0xE9){ uint32_t rel=(uint32_t)buf[ridx(rbase,p+1)]|((uint32_t)buf[ridx(rbase,p+2)]<<8)|((uint32_t)buf[ridx(rbase,p+3)]<<16)|((uint32_t)buf[ridx(rbase,p+4)]<<24); uint32_t ab=(uint32_t)(p+rel+5); buf[ridx(rbase,p+1)]=(uint8_t)ab; buf[ridx(rbase,p+2)]=(uint8_t)(ab>>8); buf[ridx(rbase,p+3)]=(uint8_t)(ab>>16); buf[ridx(rbase,p+4)]=(uint8_t)(ab>>24); p+=5; } else p++; } } static void bcj_inv(uint8_t *buf,int64_t rbase,uint64_t start,uint64_t end){ for(uint64_t p=start;p+5<=end;){ uint8_t op=buf[ridx(rbase,p)]; if(op==0xE8||op==0xE9){ uint32_t ab=(uint32_t)buf[ridx(rbase,p+1)]|((uint32_t)buf[ridx(rbase,p+2)]<<8)|((uint32_t)buf[ridx(rbase,p+3)]<<16)|((uint32_t)buf[ridx(rbase,p+4)]<<24); uint32_t rel=ab-(uint32_t)(p+5); buf[ridx(rbase,p+1)]=(uint8_t)rel; buf[ridx(rbase,p+2)]=(uint8_t)(rel>>8); buf[ridx(rbase,p+3)]=(uint8_t)(rel>>16); buf[ridx(rbase,p+4)]=(uint8_t)(rel>>24); p+=5; } else p++; } } // v3.0: parse LZSS extraído (permite reparse raw x BCJ sem duplicar código) // (v3.2: corpo = DP ótimo; ver dp_parse adiante) typedef struct { uint16_t len; uint8_t pc; uint8_t rsv; uint32_t off; } DPar; static void dp_parse(uint8_t *buf,int64_t ring_base,uint64_t tab_epoch,uint64_t ring_end, uint64_t block_start,uint64_t block_end,int32_t *head,int32_t *prev,Tok17 *toks, uint32_t *dpCost,DPar *dpPar,uint8_t *litA,uint8_t *slotA,uint8_t llenA[3][256], size_t *pntoks,uint32_t *freq,uint32_t *sfreq,uint32_t *repHist,int rep_on); /* v3.3: historia REP de referencia por posicao de byte. hist[4*i+r] = rh[r] ANTES de consumir o token que cobre o byte i (aproximacao de ponto fixo: caminho de referencia ~= caminho otimo). Preenche n+1 entradas (sentinela no fim = historia apos ultimo token). */ static void build_rep_hist(Tok17 *toks,size_t ntoks,uint32_t *repHist,uint32_t n){ int rh[REP_SIZE]; for(int i=0;i0){int tmp=rh[code]; for(int r=code;r>0;r--) rh[r]=rh[r-1]; rh[0]=tmp;} else if(code<0){for(int r=REP_SIZE-1;r>0;r--) rh[r]=rh[r-1]; rh[0]=O;} } pos+=L; } for(int r=0;r0){int tmp=rh[code]; for(int r=code;r>0;r--) rh[r]=rh[r-1]; rh[0]=tmp;} } else { e+=(size_t)(llenA[plc][_c]?llenA[plc][_c]:3)+(slotL[_s]?slotL[_s]:8)+slot_footer_bits((uint32_t)_s)+(size_t)len_extra_bits(L)+(repen?1:0); if(repen){ for(int r=REP_SIZE-1;r>0;r--) rh[r]=rh[r-1]; rh[0]=O; } } fn[pf][1]++; pf=1; nfl++; plc=len_cls(L); } } /* troca flags cruas (1b) por entropia order-1: e = e - nfl + H */ { double h=0; for(int a=0;a<2;a++){ uint32_t tot=fn[a][0]+fn[a][1]; if(!tot) continue; for(int b=0;b<2;b++){ if(!fn[a][b]) continue; double p=(double)fn[a][b]/(double)tot; h+=(double)fn[a][b]*(-log(p)/log(2.0)); } } e=(e>=nfl)?(e-nfl+(size_t)(h+0.5)):e; } return e; } /* v3.3: melhor REP 0/1 com as tabelas dadas (espelha a decisao final rep_en, que usa save_bits>overhead; aqui compara o est real das duas opcoes). */ static size_t est_best(Tok17 *toks,size_t ntoks, uint8_t *litL,uint8_t *slotL,uint8_t llen[3][256],int *prepen){ size_t e0=est_bits_tbl(toks,ntoks,litL,slotL,llen,0); size_t e1=est_bits_tbl(toks,ntoks,litL,slotL,llen,1); if(prepen) *prepen=(e1=pos) e o DP perdia matches cross-block. */ size_t hsz=HASH_SIZE*sizeof(int32_t), psz=(WS_LARGE+1)*sizeof(int32_t); /* PASS 1: greedy+lazy original (v3.1 verbatim) */ memcpy(head,h0head,hsz); memcpy(prev,h0prev,psz); size_t ntoks=0; uint64_t internal_p=block_start; size_t fpb=0; memset(freq,0,256*sizeof(uint32_t)); memset(sfreq,0,256*sizeof(uint32_t)); while(internal_p=MIN_MATCH && use_large && off<=1023) use_large=0; int cur_cost=0,cur_save=-1000000; if(ml>=MIN_MATCH){int bits_offset=3+slot_footer_bits(get_slot((uint32_t)off)); cur_cost=(ml>=10)?(1+3+bits_offset+8):(1+3+bits_offset); cur_save=ml*9-cur_cost; if(off>(int)FAR_LIM) cur_save-=FAR_PEN;} if(ml>=MIN_MATCH && cur_save>0){ hash_insert(buf,ring_base,ring_end,internal_p,head,prev); int off2=0,use_large2=0,ml2=0; if(internal_p+1+MIN_MATCH<=block_end) ml2=find_match_ds32(buf,ring_base,tab_epoch,internal_p+1,block_end,head,prev,&off2,&use_large2); if(ml2>=MIN_MATCH && use_large2 && off2<=1023) use_large2=0; if(ml2>=MIN_MATCH){int bits2=3+slot_footer_bits(get_slot((uint32_t)off2)); int cost2=(ml2>=10)?(1+3+bits2+8):(1+3+bits2); int save2=ml2*9-cost2; if(off2>(int)FAR_LIM) save2-=FAR_PEN; if(save2>cur_save){toks[ntoks].flg=0; toks[ntoks].lit=buf[ridx(ring_base,internal_p)]; ntoks++; freq[buf[ridx(ring_base,internal_p)]]++; fpb+=9; internal_p++; continue;}} toks[ntoks].flg=1; toks[ntoks].off=(uint32_t)off; toks[ntoks].flg|=(uint8_t)(use_large<<1); toks[ntoks].len=(uint16_t)ml; sfreq[get_slot((uint32_t)off)]++; ntoks++; fpb+=(size_t)cur_cost; internal_p++; for(int k=1;k %s%d | g lit=%zu m=%zu cov=%zu | d1 lit=%zu m=%zu cov=%zu | d2 lit=%zu m=%zu cov=%zu\n", estA,repA,est1,rep1,est2,rep2,(_best+256 %s%d | g lit=%zu m=%zu cov=%zu | d1 lit=%zu m=%zu cov=%zu\n", estA,repA,est1,rep1,(_best+256block_end) return 0; uint64_t remain=block_end-pos, mx=remain>GREEDY_MAX?GREEDY_MAX:remain; uint64_t mxfull=remain>MAX_MATCH?MAX_MATCH:remain; uint32_t h=quick_hash(&buf[ridx(ring_base,pos)]); int32_t craw=head[h]; int depth=0; int bestsave=-1000000; uint32_t besto=0; uint16_t bestl=0; int shlen=0; uint32_t shoff=0; int lglen=0; uint32_t lgoff=0; uint32_t ao[DP_DEPTH]; uint16_t al[DP_DEPTH]; int an=0; while(craw!=-1 && depth++=pos) break; uint64_t dist=pos-mp; if(dist>(uint64_t)WS_LARGE||dist==0) break; int l=0; while((uint64_t)l+8<=mx && memcmp(&buf[ridx(ring_base,mp+l)],&buf[ridx(ring_base,pos+l)],8)==0) l+=8; while((uint64_t)l=MIN_MATCH){ int lf=l; /* v3.8: estende full-len só as 8 primeiras (mais recentes); o resto fica cap 258 p/ ranking. Custo limitado e ótimo achado. */ #ifndef NOEXT if(an<8 && (uint64_t)l>=mx && mxfull>mx){ while((uint64_t)lf+8<=mxfull && memcmp(&buf[ridx(ring_base,mp+lf)],&buf[ridx(ring_base,pos+lf)],8)==0) lf+=8; while((uint64_t)lfshlen){ shlen=lf; shoff=(uint32_t)dist; } if(lf>lglen){ lglen=lf; lgoff=(uint32_t)dist; } {int _sv=cand_save((uint32_t)dist,lf); if(_sv>bestsave){bestsave=_sv; besto=(uint32_t)dist; bestl=(uint16_t)lf;}} } craw=prev[mp & (uint64_t)WS_LARGE]; } if(an==0) return 0; { uint8_t picked[DP_DEPTH]; memset(picked,0,sizeof(picked)); for(int r=0;ral[bi])) bi=k; if(bi<0) break; picked[bi]=1; offs[n]=ao[bi]; lens[n]=al[bi]; n++; } for(int r=0;rbs){bi=k;bs=_s;}} if(bi<0) break; picked[bi]=1; offs[n]=ao[bi]; lens[n]=al[bi]; n++; } for(int r=0;rbs){bi=k;bs=_s;}} if(bi<0) break; picked[bi]=1; offs[n]=ao[bi]; lens[n]=al[bi]; n++; } } /* pinos garantidos: best-save + longest-curto + longest-geral (opções do greedy) */ if(bestl>=MIN_MATCH){ int f=0; for(int k=0;k=MIN_MATCH){ int f=0; for(int k=0;k=MIN_MATCH){ int f=0; for(int k=0;k=MIN_MATCH){ offs[0]=besto; lens[0]=bestl; n=1; } else n=0; #endif return n; } // v3.3: DP REP-aware — historia fixa por posicao (ponto fixo do caminho de // referencia). Se rep_on: hit = flag+repbit+indice(2)+len(+extra), // miss = flag+repbit+len+slot+footer(+extra). Se !rep_on: custos v3.2. // dp[3][n+1], estado = classe de len anterior. Retorna toks (+freq/sfreq). static void dp_parse(uint8_t *buf,int64_t ring_base,uint64_t tab_epoch,uint64_t ring_end, uint64_t block_start,uint64_t block_end,int32_t *head,int32_t *prev,Tok17 *toks, uint32_t *dpCost,DPar *dpPar,uint8_t *litA,uint8_t *slotA,uint8_t llenA[3][256], size_t *pntoks,uint32_t *freq,uint32_t *sfreq,uint32_t *repHist,int rep_on){ uint32_t n=(uint32_t)(block_end-block_start); uint32_t (*dp)[BLOCK_SIZE+1]=(uint32_t(*)[BLOCK_SIZE+1])dpCost; DPar (*par)[BLOCK_SIZE+1]=(DPar(*)[BLOCK_SIZE+1])dpPar; for(int c=0;c<3;c++) for(uint32_t i=0;i<=n;i++) dp[c][i]=0xFFFFFFFFu; dp[0][0]=0; uint32_t offs[DP_NCAND+4]; uint16_t lens[DP_NCAND+4]; for(uint32_t i=0;in) continue; int _s=get_slot((uint32_t)O), _lc=L<10?L-3:7; uint32_t lcbits=(uint32_t)(llenA[c][_lc]?llenA[c][_lc]:3); uint32_t mc; if(rep_on){ int hit=0; for(int r=0;r0){ DPar P=par[c][i]; if(P.len==0){ uint8_t b=buf[ridx(ring_base,block_start+i-1)]; w--; toks[w].flg=0; toks[w].lit=b; freq[b]++; i--; c=P.pc; } else { w--; toks[w].flg=1; toks[w].off=P.off; toks[w].flg|=(uint8_t)(((P.off>1023)?1:0)<<1); toks[w].len=P.len; sfreq[get_slot(P.off)]++; i-=(uint32_t)P.len; c=P.pc; } } size_t nt=BLOCK_SIZE-w; memmove(toks,&toks[w],nt*sizeof(Tok17)); *pntoks=nt; } int executar_compressao(const char* entrada,const char* saida){ FILE *fin=fopen(entrada,"rb"); if(!fin){printf("Error opening input.\n"); return 1;} uint8_t *buf=malloc(RING_SIZE); int32_t *head=malloc(HASH_SIZE*sizeof(int32_t)); int32_t *prev=malloc((WS_LARGE+1)*sizeof(int32_t)); Tok17 *toks=malloc(BLOCK_SIZE*sizeof(Tok17)); RCModel1 *m1=(RCModel1*)malloc(sizeof(RCModel1)); uint8_t *lcc=(uint8_t*)malloc(BLOCK_SIZE); uint8_t *lcl=(uint8_t*)malloc(BLOCK_SIZE); uint32_t *lcb=(uint32_t*)malloc(BLOCK_SIZE*sizeof(uint32_t)); uint8_t *rawsave=(uint8_t*)malloc(BLOCK_SIZE); int32_t *h0head=(int32_t*)malloc(HASH_SIZE*sizeof(int32_t)); int32_t *h0prev=(int32_t*)malloc((WS_LARGE+1)*sizeof(int32_t)); uint32_t *dpCost=(uint32_t*)malloc(3*(BLOCK_SIZE+1)*sizeof(uint32_t)); DPar *dpPar=(DPar*)malloc(3*(BLOCK_SIZE+1)*sizeof(DPar)); Tok17 *toksSave=(Tok17*)malloc(BLOCK_SIZE*sizeof(Tok17)); Tok17 *toksDP1=(Tok17*)malloc(BLOCK_SIZE*sizeof(Tok17)); uint32_t *repHist=(uint32_t*)malloc(REP_SIZE*(BLOCK_SIZE+1)*sizeof(uint32_t)); if(!buf||!head||!prev||!toks||!m1||!lcc||!lcl||!lcb||!rawsave||!h0head||!h0prev||!dpCost||!dpPar||!toksSave||!toksDP1||!repHist){printf("Memory allocation failure.\n"); fclose(fin); free(buf); free(head); free(prev); free(toks); free(m1); free(lcc); free(lcl); free(lcb); free(rawsave); free(h0head); free(h0prev); free(dpCost); free(dpPar); free(toksSave); free(toksDP1); free(repHist); return 1;} rcmodel1_reset(m1); // order-1 live: contínuo no arquivo inteiro uint32_t ad_a=1,ad_b=0; uint64_t total_len=0; FILE *fout=fopen(saida,"wb"); if(!fout){printf("Error creating output.\n"); fclose(fin); free(buf); free(head); free(prev); free(toks); free(m1); free(lcc); free(lcl); free(lcb); free(rawsave); free(h0head); free(h0prev); free(dpCost); free(dpPar); free(toksSave); free(toksDP1); free(repHist); return 1;} write_header_placeholder(fout); // 20B: magic + version + len + adler memset(head,0xFF,HASH_SIZE*sizeof(int32_t)); memset(prev,0xFF,(WS_LARGE+1)*sizeof(int32_t)); uint64_t tab_epoch=0; BitWriter bw; bw_init(&bw,fout); int64_t ring_base=0; uint64_t ring_end=0; int input_eof=0; uint64_t global_p=0; /* v3.11 repeat-block: estado do bloco anterior (bytes crus). */ uint32_t prev_raw_len=0; int prev_bcj=0; int have_prev=0; while(1){ uint64_t block_start=global_p; if((block_start & 0xFFFFFFFF00000000ULL)!=tab_epoch){tab_epoch=block_start & 0xFFFFFFFF00000000ULL; memset(head,0xFF,HASH_SIZE*sizeof(int32_t)); memset(prev,0xFF,(WS_LARGE+1)*sizeof(int32_t));} {uint64_t hist=block_start>(uint64_t)WS_LARGE?(uint64_t)WS_LARGE:block_start; uint64_t want_start=block_start-hist; if(want_start>(uint64_t)ring_base){size_t have=(size_t)(ring_end-(uint64_t)ring_base); size_t drop=(size_t)(want_start-(uint64_t)ring_base); if(dropblock_start)?(size_t)(ring_end-block_start):0; if(avail==0) break; uint32_t block_raw_len=avail>=BLOCK_SIZE?BLOCK_SIZE:(uint32_t)avail; uint64_t block_end=block_start+block_raw_len; for(uint64_t _p=block_start;_p=prev_raw_len){ uint8_t *_cur=&buf[ridx(ring_base,block_start)]; uint8_t *_prv=&buf[ridx(ring_base,block_start-prev_raw_len)]; if(memcmp(_cur,_prv,block_raw_len)==0){ bw_write_bit(&bw,1); bw_write_bits(&bw,0,32); /* len==0 = repeat */ for(uint64_t _p=block_start;_p=(size_t)BCJ_GATE){ size_t coverA=toks_cover(toks,ntoks); memcpy(rawsave,&buf[ridx(ring_base,block_start)],block_raw_len); bcj_fwd(buf,ring_base,block_start,block_end); memcpy(head,h0head,HASH_SIZE*sizeof(int32_t)); memcpy(prev,h0prev,(WS_LARGE+1)*sizeof(int32_t)); parse_block_lz(buf,ring_base,tab_epoch,ring_end,block_start,block_end,head,prev,toks,&ntoks,freq,sfreq,&fixed_payload_bits,dpCost,dpPar,toksSave,toksDP1,repHist,h0head,h0prev); size_t coverB=toks_cover(toks,ntoks); if(coverB>coverA+(size_t)BCJ_MARGIN){ bcj=1; } else { memcpy(&buf[ridx(ring_base,block_start)],rawsave,block_raw_len); memcpy(head,h0head,HASH_SIZE*sizeof(int32_t)); memcpy(prev,h0prev,(WS_LARGE+1)*sizeof(int32_t)); parse_block_lz(buf,ring_base,tab_epoch,ring_end,block_start,block_end,head,prev,toks,&ntoks,freq,sfreq,&fixed_payload_bits,dpCost,dpPar,toksSave,toksDP1,repHist,h0head,h0prev); } #ifdef BCJDBG fprintf(stderr,"bcjblk e8=%zu coverA=%zu coverB=%zu -> %d\n",_e8,coverA,coverB,bcj); #endif } } uint8_t slens[256]; uint32_t scodes[256]; int snsyms=build_huffman_lengths(sfreq,slens); if(snsyms<0){ memset(slens,0,256); snsyms=0; } if(snsyms>0) build_canonical(slens,scodes); // slot table (empty ok: block needs no slot coding) /* v2.8 lenctx: len_code (0-6,7=esc) via Huffman order-1 por classe de len anterior (3 ctx x 8 syms, 2-pass exato). Pré-computa (código,tamanho) por token p/ todos os loops usarem sem condicional. */ uint32_t lfreq[NLENCTX][256]; memset(lfreq,0,sizeof(lfreq)); size_t nmatch=0; { int _pl=0; for(size_t _t=0;_t0) build_canonical(llens[_c],lcodes[_c]); } /* lcc/lcl/lcb: pré-computados por token (símbolo/tamanho/código) */ int lenctx=0; if(nmatch>0){ { int _pl=0; for(size_t _t=0;_t3) save_bits+=(size_t)(bo-3);} if(hit){int code=-1; for(int r=0;r0){int tmp=rh[code]; for(int r=code;r>0;r--) rh[r]=rh[r-1]; rh[0]=tmp;}} else {for(int r=REP_SIZE-1;r>0;r--) rh[r]=rh[r-1]; rh[0]=o;}} size_t overhead=nm*1+1; if(save_bits>overhead) rep_en=1;} /* v2.2 slots: remap needs window flag, removed. has_slots skips the slot tree when no match needs slot coding (all literals, or rep-hits only). */ int has_slots=0; {int rhs[REP_SIZE]; for(int i=0;i0){int tmp=rhs[code]; for(int r=code;r>0;r--) rhs[r]=rhs[r-1]; rhs[0]=tmp;}} else {for(int r=REP_SIZE-1;r>0;r--) rhs[r]=rhs[r-1]; rhs[0]=o;}} } uint8_t lens[256]; uint32_t codes[256]; int nsyms=build_huffman_lengths(freq,lens); size_t huff_payload_bits=0,huff_overhead_bits=0; if(nsyms>0){build_canonical(lens,codes); for(size_t t=0;t0){int tmp=rh2[code]; for(int r=code;r>0;r--) rh2[r]=rh2[r-1]; rh2[0]=tmp;}} else {for(int r=REP_SIZE-1;r>0;r--) rh2[r]=rh2[r-1]; rh2[0]=o;}}} huff_payload_bits+=2; huff_overhead_bits=1+256+(size_t)nsyms*4+(has_slots?NSLOTS+(size_t)snsyms*4:0);} else {huff_payload_bits=fixed_payload_bits; huff_overhead_bits=(size_t)1<<30;} {size_t fp=0; int rh3[REP_SIZE]; for(int i=0;i0){int tmp=rh3[code]; for(int r=code;r>0;r--) rh3[r]=rh3[r-1]; rh3[0]=tmp;}} else {for(int r=REP_SIZE-1;r>0;r--) rh3[r]=rh3[r-1]; rh3[0]=o;}}} fp+=2; fixed_payload_bits=fp;} size_t fixed_block_bits=1+32+LITMODE_BITS+fixed_payload_bits+(has_slots?NSLOTS+(size_t)snsyms*4:0)+(lenctx?ltree+1:0); size_t huff_block_bits=1+32+(huff_overhead_bits+2)+huff_payload_bits+(lenctx?ltree+1:0); int fixed_beats_raw=(fixed_payload_bits+7)/8 < block_raw_len; /* v2.3 range: literais via RC order-0 adaptativo (sem tabela). Bitstream leva flags+matches+slots (igual fixed); valores dos literais vao no paylen+bytes range. Mede exato via tmpfile e escolhe o menor dos 3. */ size_t range_bytes=0, range_block_bits=(size_t)-1; FILE *rrtmp=NULL; size_t nlit=0; for(size_t _t=0;_t0){ rrtmp=tmpfile(); if(rrtmp){ RCW rcw; rcw_init(&rcw,rrtmp); RCModel rcm; rcmodel_init(&rcm); for(size_t _t=0;_t0) range_bytes=(size_t)_rb; if(range_bytes>0){ size_t nonlit = fixed_payload_bits - 8*nlit; // fp tem 9b/lit (1 flag+8 val); no range o flag continua, só o valor vai p/ o paylen // nonlit==fp-9*nlit mantendo o +2; abaixo somamos litmode(2)+paylen(32)+align(7) range_block_bits=1+32+LITMODE_BITS+nonlit+(has_slots?NSLOTS+(size_t)snsyms*4:0)+(lenctx?ltree+1:0)+32+range_bytes*8+7; } else { fclose(rrtmp); rrtmp=NULL; } } } /* v2.4 range order-1: mesmo framing do order-0, ctx = literal anterior. Modelo CONTÍNUO entre blocos (warmup amortizado; decoder espelha). Simula em snapshot; o live avança SOMENTE se o modo 3 vencer. */ size_t range1_bytes=0, range1_block_bits=(size_t)-1; FILE *rrtmp1=NULL; RCModel1 *snap1=NULL; if(nlit>0 && m1){ snap1=(RCModel1*)malloc(sizeof(RCModel1)); if(snap1){ memcpy(snap1,m1,sizeof(RCModel1)); rrtmp1=tmpfile(); if(rrtmp1){ RCW rcw1; rcw_init(&rcw1,rrtmp1); int prev1=0; for(size_t _t=0;_t>4,toks[_t].lit); prev1=toks[_t].lit; } rcw_flush(&rcw1); fflush(rrtmp1); long _rb1=ftell(rrtmp1); if(_rb1>0) range1_bytes=(size_t)_rb1; if(range1_bytes>0){ size_t nonlit1 = fixed_payload_bits - 8*nlit; range1_block_bits=1+32+LITMODE_BITS+nonlit1+(has_slots?NSLOTS+(size_t)snsyms*4:0)+(lenctx?ltree+1:0)+32+range1_bytes*8+7; } else { fclose(rrtmp1); rrtmp1=NULL; } } if(!rrtmp1){ free(snap1); snap1=NULL; } } } /* v2.5 MIX: juiz por literal M0(order-0) x M1(16ctx), ambos avançam sempre. Frescos por bloco, notas zeradas por bloco, custos pós-update. */ size_t rangeM_bytes=0, rangeM_block_bits=(size_t)-1; FILE *rrtmpM=NULL; if(nlit>0){ rrtmpM=tmpfile(); if(rrtmpM){ RCW rcwM; rcw_init(&rcwM,rrtmpM); RCModel mM0; rcmodel_init(&mM0); RCModel1 mM1; rcmodel1_reset(&mM1); float sM0=0,sM1=0; int prevM=0; for(size_t _t=0;_t>4, _useB=(sM116383) rcmodel_rescale(&mM0); } else { mM1.f[_cx][_s]++; mM1.tot[_cx]++; if(mM1.tot[_cx]>R1_RESCALE) rcmodel1_rescale_ctx(&mM1,_cx); } sM0=sM0*JUDGE_DECAY+rccost(mM0.freq[_s],mM0.tot); sM1=sM1*JUDGE_DECAY+rccost(mM1.f[_cx][_s],mM1.tot[_cx]); prevM=_s; } rcw_flush(&rcwM); fflush(rrtmpM); long _rbM=ftell(rrtmpM); if(_rbM>0) rangeM_bytes=(size_t)_rbM; if(rangeM_bytes>0){ size_t nonlitM = fixed_payload_bits - 8*nlit; rangeM_block_bits=1+32+LITMODE_BITS+nonlitM+(has_slots?NSLOTS+(size_t)snsyms*4:0)+(lenctx?ltree+1:0)+32+rangeM_bytes*8+7; } else { fclose(rrtmpM); rrtmpM=NULL; } } } int mode_lit=0; // -1 stored, 0 fixed, 1 huff, 2 range0, 3 range1, 4 MIX { size_t best=(size_t)-1; int bmode=-1; if(fixed_beats_raw){ best=fixed_block_bits; bmode=0; } if(nsyms>0 && huff_block_bits %d nlit=%zu\n", block_raw_len,fixed_block_bits,huff_block_bits, rrtmp?range_block_bits:(size_t)-1,rrtmp1?range1_block_bits:(size_t)-1,mode_lit,nlit); #endif /* snapshot vira live SOMENTE se o modo 3 venceu (espelho do decoder) */ if(mode_lit==3 && snap1){ memcpy(m1,snap1,sizeof(RCModel1)); } if(snap1){ free(snap1); snap1=NULL; } /* v2.6 flagctx: flags match/lit via RC binário order-1 (ctx=flag anterior). Corpos ficam no bitstream; só as flags mudam de lugar. */ int fctx=0; size_t flag_bytes=0; FILE *frtmp=NULL; long bodylen_pos=0; if(mode_lit>=0 && ntoks>0){ frtmp=tmpfile(); if(frtmp){ RCW frcw; rcw_init(&frcw,frtmp); BModel2 fm[2]; bmodel2_init(&fm[0]); bmodel2_init(&fm[1]); int pf=0; for(size_t _t=0;_t0) flag_bytes=(size_t)_fb; /* delta: -ntoks(flags cruas) +1(fctx) +32+7(paylen+align) +32+7(corpos) */ if(flag_bytes*8 + 72 < ntoks) fctx=1; else { fclose(frtmp); frtmp=NULL; flag_bytes=0; } } } /* v2.7 slotctx: seletor de slot via RC order-1 por classe (4 ctx x 34). Substitui árvore Huffman + códigos: delta = -(tree+Σbo) +(1+32+7+bytes). REP walk idêntico ao do emit (só non-REP consome código). */ int slotctx=0; size_t slotRC_bytes=0; FILE *srtmp=NULL; size_t seqnD=0, curboD=0, treeD=0; if(mode_lit>=0 && has_slots){ uint8_t *seq=(uint8_t*)malloc(ntoks?ntoks:1); if(seq){ int rh9[REP_SIZE]; for(int i=0;i0){int tmp=rh9[code]; for(int r=code;r>0;r--) rh9[r]=rh9[r-1]; rh9[0]=tmp;} } else { int _s=get_slot((uint32_t)o); curbo+=(size_t)slens[_s]; // SÓ seletor: footers ficam nos corpos nos dois layouts seq[seqn++]=(uint8_t)_s; for(int r=REP_SIZE-1;r>0;r--) rh9[r]=rh9[r-1]; rh9[0]=o; } } size_t treebits=NSLOTS+(size_t)snsyms*4; srtmp=tmpfile(); if(srtmp && seqn>0){ RCW srcw; rcw_init(&srcw,srtmp); SModel sm; smodel_init(&sm); int ps=0; for(size_t i=0;i0) slotRC_bytes=(size_t)_sb; } if(!(srtmp && slotRC_bytes>0 && treebits+curbo > 1+32+7+slotRC_bytes*8)){ if(srtmp){fclose(srtmp); srtmp=NULL;} slotRC_bytes=0; } else slotctx=1; seqnD=seqn; curboD=curbo; treeD=treebits; #ifdef V27DBG fprintf(stderr,"slotblk has=%d seqn=%zu tree=%zu curbo=%zu rc=%zu -> %d\n", has_slots,seqnD,treeD,curboD,slotRC_bytes,slotctx); #endif free(seq); } } /* v2.9 repctx: bit yes/no do REP (0=hit,1=miss) via RC binário order-1 (ctx = outcome anterior). Só se rep_en. Delta: -nmatches +(1+32+7). */ int repctx=0; size_t rep_bytes=0; FILE *rptmp=NULL; size_t nmatches=0; if(mode_lit>=0 && rep_en){ for(size_t _t=0;_t0){ RCW rpcw; rcw_init(&rpcw,rptmp); BModel2 rpm[2]; bmodel2_init(&rpm[0]); bmodel2_init(&rpm[1]); int rhR[REP_SIZE]; for(int i=0;i0){int tmp=rhR[code]; for(int r=code;r>0;r--) rhR[r]=rhR[r-1]; rhR[0]=tmp;} } else { for(int r=REP_SIZE-1;r>0;r--) rhR[r]=rhR[r-1]; rhR[0]=o; } } rcw_flush(&rpcw); fflush(rptmp); long _rb=ftell(rptmp); if(_rb>0) rep_bytes=(size_t)_rb; if(rep_bytes*8 + 40 < nmatches) repctx=1; else { fclose(rptmp); rptmp=NULL; rep_bytes=0; } } else if(rptmp){ fclose(rptmp); rptmp=NULL; } } if(mode_lit>=0){ bw_write_bit(&bw,1); bw_write_bits(&bw,block_raw_len,32); bw_write_bit(&bw,bcj); // v3.0: filtro BCJ ativo? (v3.12: sem repeat-bit; repeat = len==0) if(mode_lit==1){ bw_write_bits(&bw,1,LITMODE_BITS); bw_write_bit(&bw,rep_en); bw_write_bit(&bw,has_slots); bw_write_bit(&bw,fctx); if(has_slots) bw_write_bit(&bw,slotctx); bw_write_bit(&bw,lenctx); if(rep_en) bw_write_bit(&bw,repctx); if(lenctx){ for(int _c=0;_c0){ size_t _wn=_sl>sizeof(_sb2)?sizeof(_sb2):_sl; size_t _gr=fread(_sb2,1,_wn,srtmp); if(_gr==0) break; fwrite(_sb2,1,_gr,fout); _sl-=_gr; } fclose(srtmp); srtmp=NULL; } } if(repctx){ bw_flush(&bw); write_le32(fout,(uint32_t)rep_bytes); if(rptmp){ rewind(rptmp); size_t _rl=rep_bytes; uint8_t _rb2[4096]; while(_rl>0){ size_t _wn=_rl>sizeof(_rb2)?sizeof(_rb2):_rl; size_t _gr=fread(_rb2,1,_wn,rptmp); if(_gr==0) break; fwrite(_rb2,1,_gr,fout); _rl-=_gr; } fclose(rptmp); rptmp=NULL; } } if(fctx){ bw_flush(&bw); write_le32(fout,(uint32_t)flag_bytes); if(frtmp){ rewind(frtmp); size_t _fl=flag_bytes; uint8_t _fb[4096]; while(_fl>0){ size_t _wn=_fl>sizeof(_fb)?sizeof(_fb):_fl; size_t _gr=fread(_fb,1,_wn,frtmp); if(_gr==0) break; fwrite(_fb,1,_gr,fout); _fl-=_gr; } fclose(frtmp); frtmp=NULL; } fflush(fout); bodylen_pos=ftell(fout); write_le32(fout,0); } int rhe[REP_SIZE]; for(int i=0;i=0){EMIT_REPBIT(0); bw_write_bits(&bw,(uint32_t)code,2); if(code>0){int tmp=rhe[code]; for(int r=code;r>0;r--) rhe[r]=rhe[r-1]; rhe[0]=tmp;}} else {EMIT_REPBIT(1); for(int r=REP_SIZE-1;r>0;r--) rhe[r]=rhe[r-1]; rhe[0]=o;} } else { EMIT_FLAG(1); for(int r=REP_SIZE-1;r>0;r--) rhe[r]=rhe[r-1]; rhe[0]=o; } bw_write_bits(&bw,lcb[t],lcl[t]); if(!(rep_en&&code>=0)){int _s=get_slot(toks[t].off); if(!slotctx){bw_write_bits(&bw,scodes[_s],slens[_s]);} {uint32_t _z=toks[t].off-1; int _n=slot_footer_bits(_s); uint32_t _e=(_n==0)?0:(_z-slot_base(_s)); bw_write_bits(&bw,_e,_n);}} if(toks[t].len>=10){ if(toks[t].len=2){ /* range order-0/1/MIX: literais no paylen+bytes, bitstream só flags+matches+slots */ FILE *rrsel=(mode_lit==4)?rrtmpM:((mode_lit==3)?rrtmp1:rrtmp); size_t rbsel=(mode_lit==4)?rangeM_bytes:((mode_lit==3)?range1_bytes:range_bytes); bw_write_bits(&bw,(uint32_t)mode_lit,LITMODE_BITS); bw_write_bit(&bw,rep_en); bw_write_bit(&bw,has_slots); bw_write_bit(&bw,fctx); if(has_slots) bw_write_bit(&bw,slotctx); bw_write_bit(&bw,lenctx); if(rep_en) bw_write_bit(&bw,repctx); if(lenctx){ for(int _c=0;_c0){ size_t _wn=_sl>sizeof(_sb2)?sizeof(_sb2):_sl; size_t _gr=fread(_sb2,1,_wn,srtmp); if(_gr==0) break; fwrite(_sb2,1,_gr,fout); _sl-=_gr; } fclose(srtmp); srtmp=NULL; } } bw_flush(&bw); write_le32(fout,(uint32_t)rbsel); if(rrsel){ rewind(rrsel); size_t _left=rbsel; uint8_t _cb[4096]; while(_left>0){ size_t _wn=_left>sizeof(_cb)?sizeof(_cb):_left; size_t _gr=fread(_cb,1,_wn,rrsel); if(_gr==0) break; fwrite(_cb,1,_gr,fout); _left-=_gr; } fclose(rrsel); if(mode_lit==4) rrtmpM=NULL; else if(mode_lit==3) rrtmp1=NULL; else rrtmp=NULL; } if(repctx){ bw_flush(&bw); write_le32(fout,(uint32_t)rep_bytes); if(rptmp){ rewind(rptmp); size_t _rl=rep_bytes; uint8_t _rb2[4096]; while(_rl>0){ size_t _wn=_rl>sizeof(_rb2)?sizeof(_rb2):_rl; size_t _gr=fread(_rb2,1,_wn,rptmp); if(_gr==0) break; fwrite(_rb2,1,_gr,fout); _rl-=_gr; } fclose(rptmp); rptmp=NULL; } } if(fctx){ bw_flush(&bw); write_le32(fout,(uint32_t)flag_bytes); if(frtmp){ rewind(frtmp); size_t _fl=flag_bytes; uint8_t _fb[4096]; while(_fl>0){ size_t _wn=_fl>sizeof(_fb)?sizeof(_fb):_fl; size_t _gr=fread(_fb,1,_wn,frtmp); if(_gr==0) break; fwrite(_fb,1,_gr,fout); _fl-=_gr; } fclose(frtmp); frtmp=NULL; } fflush(fout); bodylen_pos=ftell(fout); write_le32(fout,0); } int rhg[REP_SIZE]; for(int i=0;i=0){EMIT_REPBIT(0); bw_write_bits(&bw,(uint32_t)code,2); if(code>0){int tmp=rhg[code]; for(int r=code;r>0;r--) rhg[r]=rhg[r-1]; rhg[0]=tmp;}} else {EMIT_REPBIT(1); for(int r=REP_SIZE-1;r>0;r--) rhg[r]=rhg[r-1]; rhg[0]=o;} } else { EMIT_FLAG(1); for(int r=REP_SIZE-1;r>0;r--) rhg[r]=rhg[r-1]; rhg[0]=o; } bw_write_bits(&bw,lcb[t],lcl[t]); if(!(rep_en&&code>=0)){int _s=get_slot(toks[t].off); if(!slotctx){bw_write_bits(&bw,scodes[_s],slens[_s]);} {uint32_t _z=toks[t].off-1; int _n=slot_footer_bits(_s); uint32_t _e=(_n==0)?0:(_z-slot_base(_s)); bw_write_bits(&bw,_e,_n);}} if(toks[t].len>=10){ if(toks[t].len0){ size_t _wn=_sl>sizeof(_sb2)?sizeof(_sb2):_sl; size_t _gr=fread(_sb2,1,_wn,srtmp); if(_gr==0) break; fwrite(_sb2,1,_gr,fout); _sl-=_gr; } fclose(srtmp); srtmp=NULL; } } if(repctx){ bw_flush(&bw); write_le32(fout,(uint32_t)rep_bytes); if(rptmp){ rewind(rptmp); size_t _rl=rep_bytes; uint8_t _rb2[4096]; while(_rl>0){ size_t _wn=_rl>sizeof(_rb2)?sizeof(_rb2):_rl; size_t _gr=fread(_rb2,1,_wn,rptmp); if(_gr==0) break; fwrite(_rb2,1,_gr,fout); _rl-=_gr; } fclose(rptmp); rptmp=NULL; } } if(fctx){ bw_flush(&bw); write_le32(fout,(uint32_t)flag_bytes); if(frtmp){ rewind(frtmp); size_t _fl=flag_bytes; uint8_t _fb[4096]; while(_fl>0){ size_t _wn=_fl>sizeof(_fb)?sizeof(_fb):_fl; size_t _gr=fread(_fb,1,_wn,frtmp); if(_gr==0) break; fwrite(_fb,1,_gr,fout); _fl-=_gr; } fclose(frtmp); frtmp=NULL; } fflush(fout); bodylen_pos=ftell(fout); write_le32(fout,0); } int rhf[REP_SIZE]; for(int i=0;i=0){EMIT_REPBIT(0); bw_write_bits(&bw,(uint32_t)code,2); if(code>0){int tmp=rhf[code]; for(int r=code;r>0;r--) rhf[r]=rhf[r-1]; rhf[0]=tmp;}} else {EMIT_REPBIT(1); for(int r=REP_SIZE-1;r>0;r--) rhf[r]=rhf[r-1]; rhf[0]=o;} } else { EMIT_FLAG(1); for(int r=REP_SIZE-1;r>0;r--) rhf[r]=rhf[r-1]; rhf[0]=o; } bw_write_bits(&bw,lcb[t],lcl[t]); if(!(rep_en&&code>=0)){int _s=get_slot(toks[t].off); if(!slotctx){bw_write_bits(&bw,scodes[_s],slens[_s]);} {uint32_t _z=toks[t].off-1; int _n=slot_footer_bits(_s); uint32_t _e=(_n==0)?0:(_z-slot_base(_s)); bw_write_bits(&bw,_e,_n);}} if(toks[t].len>=10){ if(toks[t].len=0){ /* fecha corpos: backpatch do tamanho */ bw_flush(&bw); fflush(fout); long _end=ftell(fout); uint32_t _blen=(uint32_t)(_end-(bodylen_pos+4)); fseek(fout,bodylen_pos,SEEK_SET); write_le32(fout,_blen); fseek(fout,_end,SEEK_SET); } if(mode_lit<0){ if(bcj){ memcpy(&buf[ridx(ring_base,block_start)],rawsave,block_raw_len); bcj=0; } if(rrtmp){fclose(rrtmp); rrtmp=NULL;} if(rrtmp1){fclose(rrtmp1); rrtmp1=NULL;} if(rrtmpM){fclose(rrtmpM); rrtmpM=NULL;} if(frtmp){fclose(frtmp); frtmp=NULL;} if(srtmp){fclose(srtmp); srtmp=NULL;} if(rptmp){fclose(rptmp); rptmp=NULL;} bw_write_bit(&bw,0); bw_flush(&bw); write_le32(fout,block_raw_len); fwrite(&buf[ridx(ring_base,block_start)],1,block_raw_len,fout);} else { if(rrtmp){ fclose(rrtmp); rrtmp=NULL; } if(rrtmp1){ fclose(rrtmp1); rrtmp1=NULL; } if(rrtmpM){ fclose(rrtmpM); rrtmpM=NULL; } if(frtmp){ fclose(frtmp); frtmp=NULL; } if(srtmp){ fclose(srtmp); srtmp=NULL; } if(rptmp){ fclose(rptmp); rptmp=NULL; } } /* v3.11: atualiza prev (stored sempre raw; comprimido so se bcj==0). */ prev_raw_len=block_raw_len; prev_bcj=(mode_lit>=0)?bcj:0; have_prev=1; global_p=block_end; total_len=global_p; } bw_flush(&bw); {uint32_t checksum=(ad_b<<16)|ad_a; if(fseek(fout,0,SEEK_SET)==0){write_header_backpatch(fout,total_len,checksum);}} fclose(fout); fclose(fin); free(buf); free(head); free(prev); free(toks); free(m1); free(lcc); free(lcl); free(lcb); free(rawsave); free(h0head); free(h0prev); free(dpCost); free(dpPar); free(toksSave); free(toksDP1); free(repHist); printf("LZSS v3.12 engine complete (repeat len-0 escape + tiny + longs + 512K + skip DP2 + quota + bcj).\n"); return 0; } int executar_descompressao(const char* entrada,const char* saida){ FILE *fin=fopen(entrada,"rb"); if(!fin){printf("Error opening compressed file.\n"); return 1;} uint64_t total_original_len=0; uint32_t checksum_original=0; uint32_t fver=LZSS_VERSION; { int hr = read_header(fin, &total_original_len, &checksum_original, &fver); if(hr == 3){printf("Header fault: truncated header (need %dB magic+version+len+adler).\n", LZSS_HEADER_LEN); fclose(fin); return 1;} if(hr == 1){printf("Bad magic: not an LZSS v2.1+ file.\n" "This decoder needs magic 'LZSS' + version %u.\n" "v2.0d and older files have no magic (12B len+adler header)\n" "and a different token format: decode them with the\n" "matching older binary, or re-compress with this one.\n", LZSS_VERSION); fclose(fin); return 1;} if(hr == 2){printf("Unsupported version: file needs a newer decoder (this one writes v%u).\n", LZSS_VERSION); fclose(fin); return 1;} if(hr == 4){printf("Older version: file predates v2 (slot distances arrived in v2).\n" "Re-compress with this binary, or decode with the older binary.\n"); fclose(fin); return 1;} if(fver == 19){printf("Superseded version 19 (v3.11 repeat-bit, never released).\n" "Re-compress with this binary (v20 len-0 escape).\n"); fclose(fin); return 1;} } uint8_t *buf=NULL; FILE *fout=NULL; uint32_t da=1,db=0; int64_t ring_base=0; RCModel1 *m1dec=NULL; if(total_original_len>0){buf=malloc(RING_SIZE); m1dec=(RCModel1*)malloc(sizeof(RCModel1)); if(!buf||!m1dec){printf("Memory fail.\n"); fclose(fin); free(buf); free(m1dec); return 1;} fout=fopen(saida,"wb"); if(!fout){printf("Error creating output.\n"); fclose(fin); free(buf); free(m1dec); return 1;}} else {fclose(fin); FILE *f=fopen(saida,"wb"); if(f) fclose(f); uint32_t c=calcular_adler32((uint8_t*)"",0); if(c==checksum_original){printf("Decompression Complete. Status: 100%% INTEGRAL (Adler-32 Checked).\n"); return 0;} else {printf("CRITICAL VALIDATION ERROR.\n"); return 2;}} BitReader br; br_init(&br,fin); uint64_t global_p=0; rcmodel1_reset(m1dec); // order-1 live: contínuo no arquivo inteiro (espelho do encoder) uint32_t prev_len_d=0; int prev_bcj_d=0, have_prev_d=0; // v3.12: prev p/ escape len==0 while(global_pBLOCK_SIZE||global_p+decomp_len>total_original_len){printf("Invalid repeat len.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} {uint64_t h=global_p>(uint64_t)WS_LARGE?(uint64_t)WS_LARGE:global_p; uint64_t nb=global_p-h; size_t have=(size_t)(global_p-(uint64_t)ring_base); size_t drop=(size_t)(nb-(uint64_t)ring_base); memmove(buf,buf+drop,have-drop); ring_base=(int64_t)nb;} uint64_t src=global_p-decomp_len; for(uint32_t i=0;iBLOCK_SIZE||global_p+decomp_len>total_original_len){printf("Invalid decomp_len.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} int bcjblk=0; if(fver>=10){ bcjblk=br_read_bit(&br); } // v3.0: anel filtrado? uint32_t da0=da, db0=db; // base p/ recomputo do Adler se BCJ int litmode=0; // 0 fixed, 1 huff, 2 range0 (v3), 3 range1 (v4), 4 MIX (v5) if(fver>=5){ litmode=(int)br_read_bits(&br,LITMODE_BITS); } else if(fver>=3){ litmode=(int)br_read_bits(&br,2); } else { litmode=br_read_bit(&br); } if(litmode<0||litmode>4||(litmode==2&&fver<3)||(litmode==3&&fver<4)||(litmode==4&&fver<5)){printf("Invalid litmode.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} int rep_en_d=br_read_bit(&br); int has_slots_d=br_read_bit(&br); int fctxd=0; if(fver>=6){ fctxd=br_read_bit(&br); } int slotctxd=0; if(has_slots_d && fver>=7){ slotctxd=br_read_bit(&br); } int lenctxd=0; if(fver>=8){ lenctxd=br_read_bit(&br); } int repctxd=0; if(rep_en_d && fver>=9){ repctxd=br_read_bit(&br); } HuffDec hd; memset(&hd,0,sizeof(hd)); HuffDec lhd[NLENCTX]; for(int _c=0;_c=18){ if(br_tree(&br,_l,8,3)<0){printf("Invalid len lens.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} } else { uint8_t _m[256]={0}; for(int _s=0;_s<8;_s++) _m[_s]=(uint8_t)br_read_bit(&br); for(int _s=0;_s<8;_s++) if(_m[_s]){_l[_s]=(uint8_t)br_read_bits(&br,4); if(br.eof||_l[_s]==0||_l[_s]>15){printf("Invalid len lens.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;}} } huffdec_build(&lhd[_c],_l); } } if(litmode==1){uint8_t ll[256]={0}; if(fver>=18){ if(br_tree(&br,ll,256,8)<0){printf("Invalid huff lens.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} } else {uint8_t lens[256]={0}; for(int s=0;s<256;s++) lens[s]=(uint8_t)br_read_bit(&br); for(int s=0;s<256;s++) if(lens[s]){ll[s]=(uint8_t)br_read_bits(&br,4); if(br.eof||ll[s]==0||ll[s]>15){printf("Invalid huff lens.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;}}} huffdec_build(&hd,ll); if(hd.nsyms==0){printf("Empty huffman table.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;}} HuffDec sd; memset(&sd,0,sizeof(sd)); if(has_slots_d && !slotctxd){uint8_t sll[256]={0}; if(fver>=18){ if(br_tree(&br,sll,NSLOTS,6)<0){printf("Invalid slot lens.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} } else {uint8_t slm[256]={0}; for(int s=0;s15){printf("Invalid slot lens.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;}}} huffdec_build(&sd,sll);} /* v2.3/v2.4/v2.5 range payload: alinhado a byte após a árvore de slots */ /* v2.7 slot payload (ordem espelha o encoder: árvore/slot, range, flags, corpos) */ uint8_t *sgbuf=NULL; RCMem sdm; SModel smdl; int psl=0; if(slotctxd){ if(fver<7){printf("slotctx in old version.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} br_align(&br); uint32_t spay=0; if(!read_le32(fin,&spay)||spay==0||spay>(uint32_t)(decomp_len+16)){printf("Invalid slot paylen.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} sgbuf=(uint8_t*)malloc(spay); if(!sgbuf){printf("Memory fail.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} { size_t _g=0; while(_g (uint32_t)(decomp_len+16)){printf("Invalid range paylen.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} rgbuf=(uint8_t*)malloc(paylen); if(!rgbuf){printf("Memory fail.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} size_t _got=0; while(_got(uint32_t)(decomp_len+16)){printf("Invalid rep paylen.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} rpbuf=(uint8_t*)malloc(rpay); if(!rpbuf){printf("Memory fail.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} { size_t _g=0; while(_g(uint32_t)(decomp_len+16)){printf("Invalid flag paylen.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} fgbuf=(uint8_t*)malloc(fpay); if(!fgbuf){printf("Memory fail.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} { size_t _g=0; while(_g(uint32_t)(decomp_len*2+64)){printf("Invalid body paylen.\n"); free(fgbuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} bdbBuf=(uint8_t*)malloc(blen); if(!bdbBuf){printf("Memory fail.\n"); free(fgbuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} { size_t _g=0; while(_g(uint64_t)WS_LARGE?(uint64_t)WS_LARGE:blk_start; uint64_t nb=blk_start-h; size_t have=(size_t)(global_p-(uint64_t)ring_base); size_t drop=(size_t)(nb-(uint64_t)ring_base); memmove(buf,buf+drop,have-drop); ring_base=(int64_t)nb;} int rhd[REP_SIZE]; for(int i=0;i>4); if(sym<0){printf("Range1 decode fault.\n"); free(fgbuf); free(bdbBuf); free(rgbuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} lit=(uint8_t)sym; prevd=lit;} else if(litmode==4){int _cx=prevd>>4,_use=(s1d16383) rcmodel_rescale(&m0dX);} else {m1dX.f[_cx][_s]++; m1dX.tot[_cx]++; if(m1dX.tot[_cx]>R1_RESCALE) rcmodel1_rescale_ctx(&m1dX,_cx);} s0d=s0d*JUDGE_DECAY+rccost(m0dX.freq[_s],m0dX.tot); s1d=s1d*JUDGE_DECAY+rccost(m1dX.f[_cx][_s],m1dX.tot[_cx]); lit=(uint8_t)_s; prevd=_s;} else { if(mbd.eof){printf("Truncated token.\n"); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} lit=(uint8_t)mbr_bits(&mbd,8); } buf[ridx(ring_base,global_p)]=lit; da=(da+lit)%65521; db=(db+da)%65521; global_p++; } else { int is_rep_d=0; int repcode_d=-1; if(rep_en_d){int rf; if(repctxd){ rf=rcb_decode(&rpm,&rpmdl[rpprev]); rpprev=(rf==0)?1:0; } else { rf=mbr_bit(&mbd); if(mbd.eof){printf("Truncated token.\n"); free(rpbuf); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} } if(rf==0){is_rep_d=1; repcode_d=(int)mbr_bits(&mbd,2);}} uint32_t len_code; { int _lc=lenctxd?mbr_huffdec(&mbd,&lhd[plc]):(int)mbr_bits(&mbd,3); if(_lc<0||_lc>7){printf("Invalid len code.\n"); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} len_code=(uint32_t)_lc; } uint32_t offset=0; if(is_rep_d){offset=(uint32_t)rhd[repcode_d];} else {int _sc=slotctxd?src_decode(&sdm,&smdl,slot_cls(psl)):mbr_huffdec(&mbd,&sd); if(_sc<0||_sc>=NSLOTS){printf("Slot decode fault.\n"); free(fgbuf); free(bdbBuf); free(sgbuf); free(rgbuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} int _n=slot_footer_bits(_sc); uint32_t _e=_n?mbr_bits(&mbd,_n):0; uint32_t _z=(_sc<4)?(uint32_t)_sc:(slot_base(_sc)+_e); offset=_z+1; if(!is_rep_d) psl=_sc;} if(mbd.eof){printf("Truncated match.\n"); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} if(offset==0||offset>global_p||offset>(uint32_t)(WS_LARGE+1)){printf("CRITICAL GUARD: Pointer underflow blocked!\n"); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} uint32_t ml; if(len_code<7){ ml=len_code+3; } else { uint32_t _e8=mbr_bits(&mbd,8); ml=(_e8<255)?(_e8+3):(LONG_BASE+mbr_bits(&mbd,16)); } if(mlMAX_MATCH){printf("Invalid match length.\n"); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} plc=len_cls((int)ml); if(global_p+ml>block_end_p){printf("Match overruns block.\n"); free(fgbuf); free(bdbBuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} if(is_rep_d){if(repcode_d>0){int tmp=rhd[repcode_d]; for(int r=repcode_d;r>0;r--) rhd[r]=rhd[r-1]; rhd[0]=tmp;}} else {for(int r=REP_SIZE-1;r>0;r--) rhd[r]=rhd[r-1]; rhd[0]=(int)offset;} { uint64_t start_pos=global_p-offset; for(uint32_t i=0;i>4); if(sym<0){printf("Range1 decode fault.\n"); free(rgbuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} lit=(uint8_t)sym; prevd=lit;} else if(litmode==4){int _cx=prevd>>4,_use=(s1d16383) rcmodel_rescale(&m0dX);} else {m1dX.f[_cx][_s]++; m1dX.tot[_cx]++; if(m1dX.tot[_cx]>R1_RESCALE) rcmodel1_rescale_ctx(&m1dX,_cx);} s0d=s0d*JUDGE_DECAY+rccost(m0dX.freq[_s],m0dX.tot); s1d=s1d*JUDGE_DECAY+rccost(m1dX.f[_cx][_s],m1dX.tot[_cx]); lit=(uint8_t)_s; prevd=_s;} else {lit=(uint8_t)br_read_bits(&br,8);} buf[ridx(ring_base,global_p)]=lit; da=(da+lit)%65521; db=(db+da)%65521; global_p++; } else { int is_rep_d=0; int repcode_d=-1; if(rep_en_d){int rf; if(repctxd){ rf=rcb_decode(&rpm,&rpmdl[rpprev]); rpprev=(rf==0)?1:0; } else { rf=br_read_bit(&br); if(rf==0){is_rep_d=1; repcode_d=(int)br_read_bits(&br,2);}}} uint32_t len_code; { int _lc=lenctxd?huffdec_decode(&br,&lhd[plc]):(int)br_read_bits(&br,3); if(_lc<0||_lc>7){printf("Invalid len code.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} len_code=(uint32_t)_lc; } uint32_t offset=0; if(is_rep_d){offset=(uint32_t)rhd[repcode_d];} else {int _sc=slotctxd?src_decode(&sdm,&smdl,slot_cls(psl)):huffdec_decode(&br,&sd); if(_sc<0||_sc>=NSLOTS){printf("Slot decode fault.\n"); free(sgbuf); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} int _n=slot_footer_bits(_sc); uint32_t _e=_n?br_read_bits(&br,_n):0; uint32_t _z=(_sc<4)?(uint32_t)_sc:(slot_base(_sc)+_e); offset=_z+1; if(!is_rep_d) psl=_sc;} if(br.eof){printf("Truncated match.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} if(offset==0||offset>global_p||offset>(uint32_t)(WS_LARGE+1)){printf("CRITICAL GUARD: Pointer underflow blocked!\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} uint32_t ml; if(len_code<7){ ml=len_code+3; } else { uint32_t _e8=br_read_bits(&br,8); ml=(_e8<255)?(_e8+3):(LONG_BASE+br_read_bits(&br,16)); } if(mlMAX_MATCH){printf("Invalid match length.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} plc=len_cls((int)ml); if(global_p+ml>block_end_p){printf("Match overruns block.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} if(is_rep_d){if(repcode_d>0){int tmp=rhd[repcode_d]; for(int r=repcode_d;r>0;r--) rhd[r]=rhd[r-1]; rhd[0]=tmp;}} else {for(int r=REP_SIZE-1;r>0;r--) rhd[r]=rhd[r-1]; rhd[0]=(int)offset;} uint64_t start_pos=global_p-offset; for(uint32_t i=0;iBLOCK_SIZE||global_p+raw_len>total_original_len){printf("Invalid stored len.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} {uint64_t nb=global_p>(uint64_t)WS_LARGE?global_p-(uint64_t)WS_LARGE:0; size_t have=(size_t)(global_p-(uint64_t)ring_base); size_t drop=(size_t)(nb-(uint64_t)ring_base); memmove(buf,buf+drop,have-drop); ring_base=(int64_t)nb; uint32_t got=0; while(got \n Decompress: %s -d \n",argv[0],argv[0]); return 1;} if(strcmp(argv[1],"-c")==0) return executar_compressao(argv[2],argv[3]); if(strcmp(argv[1],"-d")==0) return executar_descompressao(argv[2],argv[3]); printf("Invalid layout mode.\n"); return 1; }