⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zopen.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1985, 1986, 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Diomidis Spinellis and James A. Woods, derived from original * work by Spencer Thomas and Joseph Orost. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)zopen.c	8.1 (Berkeley) 6/27/93";#endif /* LIBC_SCCS and not lint *//*- * fcompress.c - File compression ala IEEE Computer, June 1984. * * Compress authors: *		Spencer W. Thomas	(decvax!utah-cs!thomas) *		Jim McKie		(decvax!mcvax!jim) *		Steve Davies		(decvax!vax135!petsd!peora!srd) *		Ken Turkowski		(decvax!decwrl!turtlevax!ken) *		James A. Woods		(decvax!ihnp4!ames!jaw) *		Joe Orost		(decvax!vax135!petsd!joe) * * Cleaned up and converted to library returning I/O streams by * Diomidis Spinellis <dds@doc.ic.ac.uk>. * * zopen(filename, mode, bits) *	Returns a FILE * that can be used for read or write.  The modes *	supported are only "r" and "w".  Seeking is not allowed.  On *	reading the file is decompressed, on writing it is compressed. *	The output is compatible with compress(1) with 16 bit tables. *	Any file produced by compress(1) can be read. */#include <sys/param.h>#include <sys/stat.h>#include <ctype.h>#include <errno.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#define	BITS		16		/* Default bits. */#define	HSIZE		69001		/* 95% occupancy *//* A code_int must be able to hold 2**BITS values of type int, and also -1. */typedef long code_int;typedef long count_int;typedef u_char char_type;static char_type magic_header[] =	{'\037', '\235'};		/* 1F 9D */#define	BIT_MASK	0x1f		/* Defines for third byte of header. */#define	BLOCK_MASK	0x80/* * Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is * a fourth header byte (for expansion). */#define	INIT_BITS 9			/* Initial number of bits/code. */#define	MAXCODE(n_bits)	((1 << (n_bits)) - 1)struct s_zstate {	FILE *zs_fp;			/* File stream for I/O */	char zs_mode;			/* r or w */	enum {		S_START, S_MIDDLE, S_EOF	} zs_state;			/* State of computation */	int zs_n_bits;			/* Number of bits/code. */	int zs_maxbits;			/* User settable max # bits/code. */	code_int zs_maxcode;		/* Maximum code, given n_bits. */	code_int zs_maxmaxcode;		/* Should NEVER generate this code. */	count_int zs_htab [HSIZE];	u_short zs_codetab [HSIZE];	code_int zs_hsize;		/* For dynamic table sizing. */	code_int zs_free_ent;		/* First unused entry. */	/*	 * Block compression parameters -- after all codes are used up,	 * and compression rate changes, start over.	 */	int zs_block_compress;	int zs_clear_flg;	long zs_ratio;	count_int zs_checkpoint;	int zs_offset;	long zs_in_count;		/* Length of input. */	long zs_bytes_out;		/* Length of compressed output. */	long zs_out_count;		/* # of codes output (for debugging). */	char_type zs_buf[BITS];	union {		struct {			long zs_fcode;			code_int zs_ent;			code_int zs_hsize_reg;			int zs_hshift;		} w;			/* Write paramenters */		struct {			char_type *zs_stackp;			int zs_finchar;			code_int zs_code, zs_oldcode, zs_incode;			int zs_roffset, zs_size;			char_type zs_gbuf[BITS];		} r;			/* Read parameters */	} u;};/* Definitions to retain old variable names */#define	fp		zs->zs_fp#define	zmode		zs->zs_mode#define	state		zs->zs_state#define	n_bits		zs->zs_n_bits#define	maxbits		zs->zs_maxbits#define	maxcode		zs->zs_maxcode#define	maxmaxcode	zs->zs_maxmaxcode#define	htab		zs->zs_htab#define	codetab		zs->zs_codetab#define	hsize		zs->zs_hsize#define	free_ent	zs->zs_free_ent#define	block_compress	zs->zs_block_compress#define	clear_flg	zs->zs_clear_flg#define	ratio		zs->zs_ratio#define	checkpoint	zs->zs_checkpoint#define	offset		zs->zs_offset#define	in_count	zs->zs_in_count#define	bytes_out	zs->zs_bytes_out#define	out_count	zs->zs_out_count#define	buf		zs->zs_buf#define	fcode		zs->u.w.zs_fcode#define	hsize_reg	zs->u.w.zs_hsize_reg#define	ent		zs->u.w.zs_ent#define	hshift		zs->u.w.zs_hshift#define	stackp		zs->u.r.zs_stackp#define	finchar		zs->u.r.zs_finchar#define	code		zs->u.r.zs_code#define	oldcode		zs->u.r.zs_oldcode#define	incode		zs->u.r.zs_incode#define	roffset		zs->u.r.zs_roffset#define	size		zs->u.r.zs_size#define	gbuf		zs->u.r.zs_gbuf/* * To save much memory, we overlay the table used by compress() with those * used by decompress().  The tab_prefix table is the same size and type as * the codetab.  The tab_suffix table needs 2**BITS characters.  We get this * from the beginning of htab.  The output stack uses the rest of htab, and * contains characters.  There is plenty of room for any possible stack * (stack used to be 8000 characters). */#define	htabof(i)	htab[i]#define	codetabof(i)	codetab[i]#define	tab_prefixof(i)	codetabof(i)#define	tab_suffixof(i)	((char_type *)(htab))[i]#define	de_stack	((char_type *)&tab_suffixof(1 << BITS))#define	CHECK_GAP 10000		/* Ratio check interval. *//* * the next two codes should not be changed lightly, as they must not * lie within the contiguous general code space. */#define	FIRST	257		/* First free entry. */#define	CLEAR	256		/* Table clear output code. */static int	cl_block __P((struct s_zstate *));static void	cl_hash __P((struct s_zstate *, count_int));static code_int	getcode __P((struct s_zstate *));static int	output __P((struct s_zstate *, code_int));static int	zclose __P((void *));static int	zread __P((void *, char *, int));static int	zwrite __P((void *, const char *, int));/*- * Algorithm from "A Technique for High Performance Data Compression", * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. * * Algorithm: * 	Modified Lempel-Ziv method (LZW).  Basically finds common * substrings and replaces them with a variable size code.  This is * deterministic, and can be done on the fly.  Thus, the decompression * procedure needs no input table, but tracks the way the table was built. *//*- * compress write * * Algorithm:  use open addressing double hashing (no chaining) on the * prefix code / next character combination.  We do a variant of Knuth's * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime * secondary probe.  Here, the modular division first probe is gives way * to a faster exclusive-or manipulation.  Also do block compression with * an adaptive reset, whereby the code table is cleared when the compression * ratio decreases, but after the table fills.  The variable-length output * codes are re-sized at this point, and a special CLEAR code is generated * for the decompressor.  Late addition:  construct the table according to * file size for noticeable speed improvement on small files.  Please direct * questions about this implementation to ames!jaw. */static intzwrite(cookie, wbp, num)	void *cookie;	const char *wbp;	int num;{	register code_int i;	register int c, disp;	struct s_zstate *zs;	const u_char *bp;	u_char tmp;	int count;	if (num == 0)		return (0);	zs = cookie;	count = num;	bp = (u_char *)wbp;	if (state == S_MIDDLE)		goto middle;	state = S_MIDDLE;	maxmaxcode = 1L << BITS;	if (fwrite(magic_header,	    sizeof(char), sizeof(magic_header), fp) != sizeof(magic_header))		return (-1);	tmp = (u_char)(BITS | block_compress);	if (fwrite(&tmp, sizeof(char), sizeof(tmp), fp) != sizeof(tmp))		return (-1);	offset = 0;	bytes_out = 3;		/* Includes 3-byte header mojo. */	out_count = 0;	clear_flg = 0;	ratio = 0;	in_count = 1;	checkpoint = CHECK_GAP;	maxcode = MAXCODE(n_bits = INIT_BITS);	free_ent = ((block_compress) ? FIRST : 256);	ent = *bp++;	--count;	hshift = 0;	for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L)		hshift++;	hshift = 8 - hshift;	/* Set hash code range bound. */	hsize_reg = hsize;	cl_hash(zs, (count_int)hsize_reg);	/* Clear hash table. */middle:	for (i = 0; count--;) {		c = *bp++;		in_count++;		fcode = (long)(((long)c << maxbits) + 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_reg - i;	/* Secondary hash (after G. Knott). */		if (i == 0)			disp = 1;probe:		if ((i -= disp) < 0)			i += hsize_reg;		if (htabof(i) == fcode) {			ent = codetabof(i);			continue;		}		if ((long)htabof(i) >= 0)			goto probe;nomatch:	if (output(zs, (code_int) ent) == -1)			return (-1);		out_count++;		ent = c;		if (free_ent < maxmaxcode) {			codetabof(i) = free_ent++;	/* code -> hashtable */			htabof(i) = fcode;		} else if ((count_int)in_count >=		    checkpoint && block_compress) {			if (cl_block(zs) == -1)				return (-1);		}	}	return (num);}static intzclose(cookie)	void *cookie;{	struct s_zstate *zs;	int rval;	zs = cookie;	if (zmode == 'w') {		/* Put out the final code. */		if (output(zs, (code_int) ent) == -1) {			(void)fclose(fp);			free(zs);			return (-1);		}		out_count++;		if (output(zs, (code_int) - 1) == -1) {			(void)fclose(fp);			free(zs);			return (-1);		}	}	rval = fclose(fp) == EOF ? -1 : 0;	free(zs);	return (rval);}/*- * Output the given code. * Inputs: * 	code:	A n_bits-bit integer.  If == -1, then EOF.  This assumes *		that n_bits =< (long)wordsize - 1. * Outputs: * 	Outputs code to the file. * Assumptions: *	Chars are 8 bits long. * Algorithm: * 	Maintain a BITS character long buffer (so that 8 codes will * fit in it exactly).  Use the VAX insv instruction to insert each * code in turn.  When the buffer fills up empty it and start over. */static char_type lmask[9] =	{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};static char_type rmask[9] =	{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};static int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -