📄 nrv2b.c
字号:
|| m_off > c->conf.max_offset) return -1; assert(m_off > 0); m_len = m_len - 2 - (m_off > M2_MAX_OFFSET); if (m_off == c->last_m_off) b = 1 + 2; else { b = 1 + 10; m_off = (m_off - 1) >> 8; while (m_off > 0) { b += 2; m_off >>= 1; } } b += 2; if (m_len < 3) return b; m_len -= 3; do { b += 2; m_len >>= 1; } while (m_len > 0); return b;}int ucl_nrv2b_99_compress( const uint8_t *in, unsigned long in_len, uint8_t *out, unsigned long *out_len, unsigned int *result){ const uint8_t *ii; unsigned int lit; unsigned int m_len, m_off; struct ucl_compress c_buffer; struct ucl_compress * const c = &c_buffer; struct ucl_swd *swd; unsigned int result_buffer[16]; int r;/* max compression */#define SC_TRY_LAZY 2#define SC_GOOD_LENGTH F#define SC_MAX_LAZY F#define SC_NICE_LENGTH F#define SC_MAX_CHAIN 4096#define SC_FLAGS 1#define SC_MAX_OFFSET N memset(c, 0, sizeof(*c)); c->ip = c->in = in; c->in_end = in + in_len; c->out = out; c->result = result ? result : result_buffer; memset(c->result, 0, 16*sizeof(*c->result)); c->result[0] = c->result[2] = c->result[4] = UINT_MAX; result = NULL; memset(&c->conf, 0xff, sizeof(c->conf)); r = bbConfig(c, ENDIAN, BITSIZE); if (r == 0) r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size); if (r != 0) return UCL_E_INVALID_ARGUMENT; c->bb_op = out; ii = c->ip; /* point to start of literal run */ lit = 0; swd = (struct ucl_swd *) malloc(sizeof(*swd)); if (!swd) return UCL_E_OUT_OF_MEMORY; swd->f = F; swd->n = N; if (in_len >= 256 && in_len < swd->n) swd->n = in_len; if (swd->f < 8 || swd->n < 256) return UCL_E_INVALID_ARGUMENT; r = init_match(c,swd,NULL,0, SC_FLAGS); if (r != UCL_E_OK) { free(swd); return r; } if (SC_MAX_CHAIN > 0) swd->max_chain = SC_MAX_CHAIN; if (SC_NICE_LENGTH > 0) swd->nice_length = SC_NICE_LENGTH; if (c->conf.max_match < swd->nice_length) swd->nice_length = c->conf.max_match; c->last_m_off = 1; r = find_match(c,swd,0,0); if (r != UCL_E_OK) return r; while (c->look > 0) { unsigned int ahead; unsigned int max_ahead; int l1, l2; c->codesize = c->bb_op - out; m_len = c->m_len; m_off = c->m_off; assert(c->bp == c->ip - c->look); assert(c->bp >= in); if (lit == 0) ii = c->bp; assert(ii + lit == c->bp); assert(swd->b_char == *(c->bp)); if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET)) || m_off > c->conf.max_offset) { /* a literal */ lit++; swd->max_chain = SC_MAX_CHAIN; r = find_match(c,swd,1,0); assert(r == 0); continue; } /* a match */ assert_match(swd,m_len,m_off); /* shall we try a lazy match ? */ ahead = 0; if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off == c->last_m_off) { /* no */ l1 = 0; max_ahead = 0; } else { /* yes, try a lazy match */ l1 = len_of_coded_match(c,m_len,m_off); assert(l1 > 0); max_ahead = SC_TRY_LAZY; if ((m_len - 1) < max_ahead) { max_ahead = m_len -1; } } while (ahead < max_ahead && c->look > m_len) { if (m_len >= SC_GOOD_LENGTH) swd->max_chain = SC_MAX_CHAIN >> 2; else swd->max_chain = SC_MAX_CHAIN; r = find_match(c,swd,1,0); ahead++; assert(r == 0); assert(c->look > 0); assert(ii + lit + ahead == c->bp); if (c->m_len < 2) continue; l2 = len_of_coded_match(c,c->m_len,c->m_off); if (l2 < 0) continue; if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 + (int)(ahead) * 9) { c->lazy++; assert_match(swd,c->m_len,c->m_off); lit += ahead; assert(ii + lit == c->bp); goto lazy_match_done; } } assert(ii + lit + ahead == c->bp); /* 1 - code run */ code_run(c,ii,lit); lit = 0; /* 2 - code match */ code_match(c,m_len,m_off); swd->max_chain = SC_MAX_CHAIN; r = find_match(c,swd,m_len,1+ahead); assert(r == 0); lazy_match_done: ; } /* store final run */ code_run(c,ii,lit); /* EOF */ bbPutBit(c, 0); code_prefix_ss11(c, 0x1000000U); bbPutByte(c, 0xff); bbFlushBits(c, 0); assert(c->textsize == in_len); c->codesize = c->bb_op - out; *out_len = c->bb_op - out; #if 0 printf("%7ld %7ld -> %7ld %7ld %7ld %ld (max: %d %d %d)\n", (long) c->textsize, (long) in_len, (long) c->codesize, c->match_bytes, c->lit_bytes, c->lazy, c->result[1], c->result[3], c->result[5]);#endif assert(c->lit_bytes + c->match_bytes == in_len); swd_exit(swd); free(swd); return UCL_E_OK;}void Encode(void) /* compression */{ uint8_t *in, *out; unsigned long in_len, out_len; uint32_t tw; int r; fseek(infile, 0, SEEK_END); in_len = ftell(infile);#ifdef VERBOSE if ((signed long)in_len < 0) Fprintf((stderr, "Errno: %d", errno));#endif#if UCLPACK_COMPAT { uint8_t byte; if (fwrite(magic, sizeof(magic), 1, outfile) != 1) Error("Can't write."); tw = htonl(0); /* flags */ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1) Error("Can't write."); byte = 0x2b; /* method */ if (fwrite(&byte, sizeof(byte), 1, outfile) != 1) Error("Can't write."); byte = 10; /* level */ if (fwrite(&byte, sizeof(byte), 1, outfile) != 1) Error("Can't write."); tw = htonl(256*1024); /* block_size */ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1) Error("Can't write."); tw = htonl(in_len); if (fwrite(&tw, sizeof(tw), 1, outfile) != 1) Error("Can't write."); /* output size of text */ }#else tw = host_to_i86ul(in_len); if (fwrite(&tw, sizeof(tw), 1, outfile) != 1) Error("Can't write."); /* output size of text */#endif if (in_len == 0) return; rewind(infile); in = malloc(in_len); out_len = in_len + (in_len/8) + 256; out = malloc(out_len); if (!in || !out) { Error("Can't malloc"); } if (fread(in, in_len, 1, infile) != 1) { Error("Can't read"); } r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 ); if (r != UCL_E_OK) Error("Compression failure\n");#if UCLPACK_COMPAT tw = htonl(out_len); if (fwrite(&tw, sizeof(tw), 1, outfile) != 1) Error("Can't write."); /* file size of text */#endif if (fwrite(out, out_len, 1, outfile) != 1) { Error("Write error\n"); }#if UCLPACK_COMPAT tw = htonl(0); /* EOF marker */ if (fwrite(&tw, sizeof(tw), 1, outfile) != 1) Error("Can't write.");#endif#ifdef LONG_REPORT Fprintf((stderr, "input size %ld bytes\n", in_len)); Fprintf((stderr, "output size %ld bytes\n", out_len)); Fprintf((stderr, "input/output %.3f\n", (double)in_len / out_len));#else Fprintf((stderr, "input/output = %ld/%ld = %.3f\n", in_len, out_len, (double)in_len / out_len));#endif }#endif#ifdef DECODE#define GETBIT_8(bb, src, ilen) \ (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)#define GETBIT_LE16(bb, src, ilen) \ (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))#define GETBIT_LE32(bb, src, ilen) \ (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\ bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))#define GETBIT_LE64(bb, src, ilen) \ (bc > 0 ? ((bb>>--bc)&1) : (bc=63, \ bb=*(const uint64_t *)((src)+ilen),ilen+=8,(bb>>63)&1))#if ENDIAN == 0 && BITSIZE == 8#define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)#endif#if ENDIAN == 0 && BITSIZE == 16#define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)#endif#if ENDIAN == 0 && BITSIZE == 32#define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)#endif#if ENDIAN == 0 && BITSIZE == 64#define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)#endif#ifndef GETBIT#error "Bad Combination of ENDIAN and BITSIZE values specified"#endif#undef SAFE#ifdef SAFE#define FAIL(x,r) if (x) { Error(r); }#else#define FAIL(x,r)#endifvoid Decode(void) /* recover */{ uint32_t tw; uint8_t *src, *dst; unsigned long max_src_len, src_len, dst_len; unsigned long ilen = 0, olen = 0, last_m_off = 1;#if BITSIZE <= 32 uint32_t bb = 0;#elif BITSIZE == 64 uint64_t bb = 0;#endif unsigned bc = 0;#if UCLPACK_COMPAT if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw), SEEK_SET) != 0) Error("Seek Error"); if (fread(&tw, sizeof(tw), 1, infile) < 1) Error("Can't read"); /* read size of text */ dst_len = ntohl(tw); if (fread(&tw, sizeof(tw), 1, infile) < 1) Error("Can't read"); /* read size of file */ max_src_len = ntohl(tw);#else if (fread(&tw, sizeof(tw), 1, infile) < 1) Error("Can't read"); /* read size of text */ dst_len = i86ul_to_host(tw); max_src_len = dst_len + (dst_len/8) + 256;#endif if (dst_len == 0) return; dst = malloc(dst_len); if (!dst) Error("Can't malloc"); src = malloc(max_src_len); if (!src) Error("Can't malloc"); src_len = fread(src, 1, max_src_len, infile); if (src_len <= 0) Error("Can't read"); for(;;) { unsigned int m_off, m_len; while(GETBIT(bb, src, ilen)) { FAIL(ilen >= src_len, "input overrun"); FAIL(olen >= dst_len, "output overrun"); dst[olen++] = src[ilen++]; } m_off = 1; do { m_off = m_off*2 + GETBIT(bb, src, ilen); FAIL(ilen >= src_len, "input overrun"); FAIL(m_off > 0xffffffU +3, "lookbehind overrun"); } while (!GETBIT(bb, src, ilen)); if (m_off == 2) { m_off = last_m_off; } else { FAIL(ilen >= src_len, "input overrun"); m_off = (m_off - 3)*256 + src[ilen++]; if (m_off == 0xffffffffU) break; last_m_off = ++m_off; } m_len = GETBIT(bb, src, ilen); m_len = m_len*2 + GETBIT(bb, src, ilen); if (m_len == 0) { m_len++; do { m_len = m_len*2 + GETBIT(bb, src, ilen); FAIL(ilen >= src_len, "input overrun"); FAIL(m_len >= dst_len, "output overrun"); } while(!GETBIT(bb, src, ilen)); m_len += 2; } m_len += (m_off > 0xd00); FAIL(olen + m_len > dst_len, "output overrun"); FAIL(m_off > olen, "lookbeind overrun"); { const uint8_t *m_pos; m_pos = dst + olen - m_off; dst[olen++] = *m_pos++; do { dst[olen++] = *m_pos++; } while(--m_len > 0); } } FAIL(ilen < src_len, "input not consumed"); FAIL(ilen > src_len, "input overrun"); assert(ilen == src_len); Fprintf((stderr, "%12ld\n", olen)); if (dst_len != olen) { fprintf(stderr, "length != expected length\n"); } if (fwrite(dst, olen, 1, outfile) != 1) Error("Write error\n"); free(src); free(dst);}#endif#ifdef MAINint main(int argc, char *argv[]){ char *s; FILE *f; int c; if (argc == 2) { outfile = stdout; if ((f = tmpfile()) == NULL) { perror("tmpfile"); return EXIT_FAILURE; } while ((c = getchar()) != EOF) fputc(c, f); rewind(infile = f); } else if (argc != 4) { Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n" "'nrv2b d file2 file1' decodes file2 into file1.\n")); return EXIT_FAILURE; } if (argc == 4) { if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL) || (s = argv[2], (infile = fopen(s, "rb")) == NULL) || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) { Fprintf((stderr, "??? %s\n", s)); return EXIT_FAILURE; } } if (toupper(*argv[1]) == 'E') Encode(); else Decode(); fclose(infile); fclose(outfile); return EXIT_SUCCESS;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -