#include #include #include #include #include #define MIN_MATCH 3 #define MAX_MATCH 258 #define WS_SMALL 1023 #define WS_LARGE 131071 #define HASH_SIZE 65536 #define HASH_MASK (HASH_SIZE - 1) #define BLOCK_SIZE 65536 #define RING_BITS 18 #define RING_SIZE ((size_t)1 << RING_BITS) static inline size_t ridx(int64_t base, uint64_t p) { return (size_t)((int64_t)(p) - base); } #define REP_SIZE 4 static const int REP_INIT[REP_SIZE]={1,8,32,128}; // ========= FILE MAGIC + VERSION (v2.9: + REP-hit yes/no com contexto) ========= // v2.8: version 8 = bit lenctx (len_code via Huffman order-1 por classe). // v2.9: version 9 = + bit repctx por bloco (só se rep_en): 1 = bit yes/no do REP // (0=hit,1=miss) via RC binário order-1 (ctx = outcome anterior, 2 modelos, // frescos por bloco) em payload próprio; índice 2b continua nos corpos. // Decoder aceita v2..v9. #define LZSS_MAGIC 0x53535A4Cu /* "LZSS" LE: bytes 4C 5A 53 53 */ #define LZSS_VERSION 9u /* 9 = v2.8 + repctx */ #define LZSS_HEADER_LEN 20 /* magic u32 + version u32 + len u64 + adler u32 */ #define LITMODE_BITS 3 /* v5+: 5 modos */ #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;}} typedef struct { FILE *f; uint8_t buf; int cnt; int eof; } BitReader; void br_init(BitReader *r,FILE *f){r->f=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;icnt=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 34 // lzip-style slots for real distance d in [1,131071] (z=d-1) // 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 34 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>MAX_MATCH?MAX_MATCH: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==MAX_MATCH){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==MAX_MATCH) break;} craw=prev[match_pos & (uint64_t)WS_LARGE]; } 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; } 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)); if(!buf||!head||!prev||!toks||!m1||!lcc||!lcl||!lcb){printf("Memory allocation failure.\n"); fclose(fin); free(buf); free(head); free(prev); free(toks); free(m1); free(lcc); free(lcl); free(lcb); 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); 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; 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=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(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(save2>cur_save){toks[ntoks].flg=0; toks[ntoks].lit=buf[ridx(ring_base,internal_p)]; ntoks++; freq[buf[ridx(ring_base,internal_p)]]++; fixed_payload_bits+=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++; fixed_payload_bits+=(size_t)cur_cost; internal_p++; for(int k=1;k0) 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;_t0){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?34+(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?34+(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?34+(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?34+(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?34+(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=34+(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); 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) bw_write_bits(&bw,toks[t].len-3,8); } } } else if(mode_lit>=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) bw_write_bits(&bw,toks[t].len-3,8); } } } else { bw_write_bits(&bw,0,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 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) bw_write_bits(&bw,toks[t].len-3,8); } } } } if(fctx && mode_lit>=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(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; } } 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); printf("LZSS v2.9 REP engine complete (rep ctx + slots ctx + len ctx + flags ctx).\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;} } 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) while(global_pBLOCK_SIZE||global_p+decomp_len>total_original_len){printf("Invalid decomp_len.\n"); free(buf); free(m1dec); fclose(fin); fclose(fout); return 1;} 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;_c15){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 lens[256]={0}; for(int s=0;s<256;s++) lens[s]=(uint8_t)br_read_bit(&br); uint8_t ll[256]={0}; 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 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=(len_code<7)?(len_code+3):(mbr_bits(&mbd,8)+3); 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=(len_code<7)?(len_code+3):(br_read_bits(&br,8)+3); 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; }