📄 compress.c
字号:
} size = fread((char *)gc_buf, 1, n_bits, in_fp); if (size <= 0) return -1; /* end of file */ gc_offset = 0; /* Round size down to integral number of codes */ size = (size << 3) - (n_bits - 1); } r_off = gc_offset; bits = n_bits;#ifdef vax asm("extzv r10,r9,(r8),r11");#else /* not a vax */ /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* Get first part (low order bits) */ code = (*bp++ >> r_off); bits -= (8 - r_off); r_off = 8 - r_off; /* now, offset into code word */ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if (bits >= 8) { code |= *bp++ << r_off; r_off += 8; bits -= 8; } /* high order bits. */ code |= (*bp & rmask[bits]) << r_off;#endif /* vax */ gc_offset += n_bits; return code;}#ifdef DO_COMPRESS /***************************************************************************** * output(): Output the supplied code to the supplied file pointer; * Supplying a code of -1 means end of file. * * Assumptions: * Chars are 8 bits long. *****************************************************************************/static void output(code)code_t code;{ /* * On the VAX, it is important to have the register declarations in * exactly the order given, or the asm will break. */ register int r_off = offset, bits = n_bits; register char *bp = buf; if (code >= 0) {#ifdef vax /* * VAX DEPENDENT!! Implementation on other machines is below. * * Translation: Insert BITS bits from the argument starting at offset * bits from the beginning of buf. */ 0; /* Work around for pcc -O bug with asm and if stmt */ asm("insv 4(ap),r11,r10,(r9)");#else /* not a vax */ /* * byte/bit numbering on the VAX is simulated by the following code */ /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* * Since code is always >= 8 bits, only need to mask the first hunk * on the left. */ *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; bp++; bits -= (8 - r_off); code >>= 8 - r_off; /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if (bits >= 8) { *bp++ = code; code >>= 8; bits -= 8; } /* Last bits. */ if (bits) *bp = code;#endif /* vax */ offset += n_bits; if (offset == (n_bits << 3)) { bp = buf; bits = n_bits; bytes_out += bits; do putc(*bp++, out_fp); while (--bits); offset = 0; } /* * If the next entry is going to be too big for the code size, then * increase it, if possible. */ if (free_ent > maxcode || (clear_flg > 0)) { /* * Write the whole buffer, because the input side won't discover * the size increase until after it has read it. */ if (offset > 0) { if (fwrite(buf, 1, n_bits, out_fp) != n_bits) t_write_error(); bytes_out += n_bits; } offset = 0; if (clear_flg) { maxcode = MAXCODE(n_bits = INIT_BITS); clear_flg = 0; } else { n_bits++; if (n_bits == BITS) maxcode = MAXMAXCODE; else maxcode = MAXCODE(n_bits); } } } else { /* * At EOF, write the rest of the buffer. */ if (offset > 0) fwrite(buf, 1, (offset + 7) / 8, out_fp); bytes_out += (offset + 7) / 8; offset = 0; t_fflush(out_fp); /* Flush, and throw EX_WRITE on error */ }}/****************************************************************************** * clear_block(): Clear hash table for block compression. */ static void clear_block() /* table clear for block compress */{ register long int rat; checkpoint = in_count + CHECK_GAP; if (in_count > 0x007fffff) { /* shift will overflow */ rat = bytes_out >> 8; if (rat == 0) { /* Don't divide by zero */ rat = 0x7fffffff; } else { rat = in_count / rat; } } else { rat = (in_count << 8) / bytes_out; /* 8 fractional bits */ } if (rat > ratio) { ratio = rat; } else { ratio = 0; clear_hash((long)HSIZE); free_ent = FIRST; clear_flg = 1; output((code_t)CLEAR); }}/****************************************************************************** * clear_hash(): clear and reset the hash table for codes. */static void clear_hash(hsize)register long hsize;{ register long *htab_p = htab + hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p - 16) = m1; *(htab_p - 15) = m1; *(htab_p - 14) = m1; *(htab_p - 13) = m1; *(htab_p - 12) = m1; *(htab_p - 11) = m1; *(htab_p - 10) = m1; *(htab_p - 9) = m1; *(htab_p - 8) = m1; *(htab_p - 7) = m1; *(htab_p - 6) = m1; *(htab_p - 5) = m1; *(htab_p - 4) = m1; *(htab_p - 3) = m1; *(htab_p - 2) = m1; *(htab_p - 1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for (i += 16; i > 0; i--) *--htab_p = m1;}/* * compress(): compress input file pointer to output file pointer * * May throw EX_WRITE if write errors are encountered. * * Lifted almost completely from Compress 4.0 -- thanks to all those * who wrote compress and put it in the public domain. *//* VARARGS 2 */void compress(in, out, in_ptr, in_bytes)FILE *in;FILE *out;unsigned char *in_ptr;int in_bytes;{ register long fcode; register code_t i = 0; register int c; register code_t ent; register int disp; register int hshift; in_fp = in; out_fp = out; putc(g_magic[0], out_fp); putc(g_magic[1], out_fp); putc((char)(BITS | BLOCK_MASK), out_fp); t_ferror(out_fp); /* Throw EX_WRITE on error */ offset = 0; bytes_out = 3; /* includes 3-byte header mojo */ clear_flg = 0; ratio = 0; in_count = 1; checkpoint = CHECK_GAP; maxcode = MAXCODE(n_bits = INIT_BITS); free_ent = FIRST; if (in_fp != NULL) ent = getc(in_fp); else if (--in_bytes >= 0) ent = *in_ptr++; else throwv(EX_FAILURE, "Empty source buffer passed to compress."); hshift = 0; for (fcode = (long)HSIZE; fcode < 65536L; fcode *= 2L) hshift++; hshift = 8 - hshift; /* set hash code range bound */ clear_hash((long)HSIZE); while (in_fp != NULL && (c = getc(in_fp)) != EOF || --in_bytes >= 0 && ((c = *in_ptr++), TRUE)) { in_count++; fcode = (long) (((long) c << BITS) + ent); i = ((c << hshift) ^ ent); /* xor hashing */ if (htabof(i) == fcode) { ent = codetabof(i); continue; } else if ((long) htabof(i) < 0) /* empty slot */ goto nomatch; disp = HSIZE - i; /* secondary hash (after G. Knott) */ if (i == 0) disp = 1;probe: if ((i -= disp) < 0) i += HSIZE; if (htabof(i) == fcode) { ent = codetabof(i); continue; } if ((long) htabof(i) > 0) goto probe;nomatch: output((code_t)ent); ent = c; if (free_ent < MAXMAXCODE) { codetabof(i) = free_ent++; /* code -> hashtable */ htabof(i) = fcode; } else if ((long) in_count >= checkpoint && BLOCK_MASK) clear_block(); } /* * Put out the final code. */ output((code_t) ent); output((code_t) -1);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -