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

📄 pg_lzcompress.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		{			len = thislen;			off = thisoff;		}		/*		 * Advance to the next history entry		 */		hent = hent->next;		/*		 * Be happy with lesser good matches the more entries we visited. But		 * no point in doing calculation if we're at end of list.		 */		if (hent)		{			if (len >= good_match)				break;			good_match -= (good_match * good_drop) / 100;		}	}	/*	 * Return match information only if it results at least in one byte	 * reduction.	 */	if (len > 2)	{		*lenp = len;		*offp = off;		return 1;	}	return 0;}/* ---------- * pglz_compress - * *		Compresses source into dest using strategy. * ---------- */intpglz_compress(char *source, int32 slen, PGLZ_Header *dest, PGLZ_Strategy *strategy){	unsigned char *bp = ((unsigned char *) dest) + sizeof(PGLZ_Header);	unsigned char *bstart = bp;	int			hist_next = 0;	bool		hist_recycle = false;	char	   *dp = source;	char	   *dend = source + slen;	unsigned char ctrl_dummy = 0;	unsigned char *ctrlp = &ctrl_dummy;	unsigned char ctrlb = 0;	unsigned char ctrl = 0;	int32		match_len;	int32		match_off;	int32		good_match;	int32		good_drop;	int32		do_compress = 1;	int32		result_size = -1;	int32		result_max;	int32		need_rate;	/*	 * Our fallback strategy is the default.	 */	if (strategy == NULL)		strategy = PGLZ_strategy_default;	/*	 * Save the original source size in the header.	 */	dest->rawsize = slen;	/*	 * If the strategy forbids compression (at all or if source chunk too	 * small), copy input to output without compression.	 */	if (strategy->match_size_good == 0)	{		memcpy(bstart, source, slen);		return (dest->varsize = slen + sizeof(PGLZ_Header));	}	else	{		if (slen < strategy->min_input_size)		{			memcpy(bstart, source, slen);			return (dest->varsize = slen + sizeof(PGLZ_Header));		}	}	/*	 * Limit the match size to the maximum implementation allowed value	 */	if ((good_match = strategy->match_size_good) > PGLZ_MAX_MATCH)		good_match = PGLZ_MAX_MATCH;	if (good_match < 17)		good_match = 17;	if ((good_drop = strategy->match_size_drop) < 0)		good_drop = 0;	if (good_drop > 100)		good_drop = 100;	/*	 * Initialize the history lists to empty.  We do not need to zero the	 * hist_entries[] array; its entries are initialized as they are used.	 */	memset((void *) hist_start, 0, sizeof(hist_start));	/*	 * Compute the maximum result size allowed by the strategy. If the input	 * size exceeds force_input_size, the max result size is the input size	 * itself. Otherwise, it is the input size minus the minimum wanted	 * compression rate.	 */	if (slen >= strategy->force_input_size)		result_max = slen;	else	{		need_rate = strategy->min_comp_rate;		if (need_rate < 0)			need_rate = 0;		else if (need_rate > 99)			need_rate = 99;		result_max = slen - ((slen * need_rate) / 100);	}	/*	 * Compress the source directly into the output buffer.	 */	while (dp < dend)	{		/*		 * If we already exceeded the maximum result size, set no compression		 * flag and stop this. But don't check too often.		 */		if (bp - bstart >= result_max)		{			do_compress = 0;			break;		}		/*		 * Try to find a match in the history		 */		if (pglz_find_match(hist_start, dp, dend, &match_len,							&match_off, good_match, good_drop))		{			/*			 * Create the tag and add history entries for all matched			 * characters.			 */			pglz_out_tag(ctrlp, ctrlb, ctrl, bp, match_len, match_off);			while (match_len--)			{				pglz_hist_add(hist_start, hist_entries,							  hist_next, hist_recycle,							  dp, dend);				dp++;			/* Do not do this ++ in the line above!		*/				/* The macro would do it four times - Jan.	*/			}		}		else		{			/*			 * No match found. Copy one literal byte.			 */			pglz_out_literal(ctrlp, ctrlb, ctrl, bp, *dp);			pglz_hist_add(hist_start, hist_entries,						  hist_next, hist_recycle,						  dp, dend);			dp++;				/* Do not do this ++ in the line above!		*/			/* The macro would do it four times - Jan.	*/		}	}	/*	 * If we are still in compressing mode, write out the last control byte	 * and determine if the compression gained the rate requested by the	 * strategy.	 */	if (do_compress)	{		*ctrlp = ctrlb;		result_size = bp - bstart;		if (result_size >= result_max)			do_compress = 0;	}	/*	 * Done - if we successfully compressed and matched the strategy's	 * constraints, return the compressed result. Otherwise copy the original	 * source over it and return the original length.	 */	if (do_compress)	{		dest->varsize = result_size + sizeof(PGLZ_Header);		return VARATT_SIZE(dest);	}	else	{		memcpy(((char *) dest) + sizeof(PGLZ_Header), source, slen);		dest->varsize = slen + sizeof(PGLZ_Header);		return VARATT_SIZE(dest);	}}/* ---------- * pglz_decompress - * *		Decompresses source into dest. * ---------- */intpglz_decompress(PGLZ_Header *source, char *dest){	unsigned char *dp;	unsigned char *dend;	unsigned char *bp;	unsigned char ctrl;	int32		ctrlc;	int32		len;	int32		off;	dp = ((unsigned char *) source) + sizeof(PGLZ_Header);	dend = ((unsigned char *) source) + VARATT_SIZE(source);	bp = (unsigned char *) dest;	if (VARATT_SIZE(source) == source->rawsize + sizeof(PGLZ_Header))	{		memcpy(dest, dp, source->rawsize);		return source->rawsize;	}	while (dp < dend)	{		/*		 * Read one control byte and process the next 8 items.		 */		ctrl = *dp++;		for (ctrlc = 0; ctrlc < 8 && dp < dend; ctrlc++)		{			if (ctrl & 1)			{				/*				 * Otherwise it contains the match length minus 3 and the				 * upper 4 bits of the offset. The next following byte				 * contains the lower 8 bits of the offset. If the length is				 * coded as 18, another extension tag byte tells how much				 * longer the match really was (0-255).				 */				len = (dp[0] & 0x0f) + 3;				off = ((dp[0] & 0xf0) << 4) | dp[1];				dp += 2;				if (len == 18)					len += *dp++;				/*				 * Now we copy the bytes specified by the tag from OUTPUT to				 * OUTPUT. It is dangerous and platform dependent to use				 * memcpy() here, because the copied areas could overlap				 * extremely!				 */				while (len--)				{					*bp = bp[-off];					bp++;				}			}			else			{				/*				 * An unset control bit means LITERAL BYTE. So we just copy				 * one from INPUT to OUTPUT.				 */				*bp++ = *dp++;			}			/*			 * Advance the control bit			 */			ctrl >>= 1;		}	}	/*	 * That's it.	 */	return (char *) bp - dest;}/* ---------- * pglz_get_next_decomp_char_from_lzdata - * *		Reads the next character from a decompression state if the *		input data to pglz_decomp_init() was in compressed format. * ---------- */intpglz_get_next_decomp_char_from_lzdata(PGLZ_DecompState *dstate){	unsigned char retval;	if (dstate->tocopy > 0)	{		/*		 * Copy one byte from output to output until we did it for the length		 * specified by the last tag. Return that byte.		 */		dstate->tocopy--;		return (*(dstate->cp_out++) = *(dstate->cp_copy++));	}	if (dstate->ctrl_count == 0)	{		/*		 * Get the next control byte if we need to, but check for EOF before.		 */		if (dstate->cp_in == dstate->cp_end)			return EOF;		/*		 * This decompression method saves time only, if we stop near the		 * beginning of the data (maybe because we're called by a comparison		 * function and a difference occurs early). Otherwise, all the checks,		 * needed here, cause too much overhead.		 *		 * Thus we decompress the entire rest at once into the temporary		 * buffer and change the decomp state to return the prepared data from		 * the buffer by the more simple calls to		 * pglz_get_next_decomp_char_from_plain().		 */		if (dstate->cp_out - dstate->temp_buf >= 256)		{			unsigned char *cp_in = dstate->cp_in;			unsigned char *cp_out = dstate->cp_out;			unsigned char *cp_end = dstate->cp_end;			unsigned char *cp_copy;			unsigned char ctrl;			int			off;			int			len;			int			i;			while (cp_in < cp_end)			{				ctrl = *cp_in++;				for (i = 0; i < 8; i++)				{					if (cp_in == cp_end)						break;					if (ctrl & 0x01)					{						len = (cp_in[0] & 0x0f) + 3;						off = ((cp_in[0] & 0xf0) << 4) | cp_in[1];						cp_in += 2;						if (len == 18)							len += *cp_in++;						cp_copy = cp_out - off;						while (len--)							*cp_out++ = *cp_copy++;					}					else						*cp_out++ = *cp_in++;					ctrl >>= 1;				}			}			dstate->cp_in = dstate->cp_out;			dstate->cp_end = cp_out;			dstate->next_char = pglz_get_next_decomp_char_from_plain;			return (int) (*(dstate->cp_in++));		}		/*		 * Not yet, get next control byte into decomp state.		 */		dstate->ctrl = (unsigned char) (*(dstate->cp_in++));		dstate->ctrl_count = 8;	}	/*	 * Check for EOF in tag/literal byte data.	 */	if (dstate->cp_in == dstate->cp_end)		return EOF;	/*	 * Handle next control bit.	 */	dstate->ctrl_count--;	if (dstate->ctrl & 0x01)	{		/*		 * Bit is set, so tag is following. Setup copy information and do the		 * copy for the first byte as above.		 */		int			off;		dstate->tocopy = (dstate->cp_in[0] & 0x0f) + 3;		off = ((dstate->cp_in[0] & 0xf0) << 4) | dstate->cp_in[1];		dstate->cp_in += 2;		if (dstate->tocopy == 18)			dstate->tocopy += *(dstate->cp_in++);		dstate->cp_copy = dstate->cp_out - off;		dstate->tocopy--;		retval = (*(dstate->cp_out++) = *(dstate->cp_copy++));	}	else	{		/*		 * Bit is unset, so literal byte follows.		 */		retval = (int) (*(dstate->cp_out++) = *(dstate->cp_in++));	}	dstate->ctrl >>= 1;	return (int) retval;}/* ---------- * pglz_get_next_decomp_char_from_plain - * *		The input data to pglz_decomp_init() was stored in uncompressed *		format. So we don't have a temporary output buffer and simply *		return bytes from the input until EOF. * ---------- */intpglz_get_next_decomp_char_from_plain(PGLZ_DecompState *dstate){	if (dstate->cp_in >= dstate->cp_end)		return EOF;	return (int) (*(dstate->cp_in++));}

⌨️ 快捷键说明

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