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

📄 varbit.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	bits8	   *p1,			   *p2,			   *r;	bits8		mask;	bitlen1 = VARBITLEN(arg1);	bitlen2 = VARBITLEN(arg2);	if (bitlen1 != bitlen2)		ereport(ERROR,				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				 errmsg("cannot OR bit strings of different sizes")));	len = VARSIZE(arg1);	result = (VarBit *) palloc(len);	VARATT_SIZEP(result) = len;	VARBITLEN(result) = bitlen1;	p1 = VARBITS(arg1);	p2 = VARBITS(arg2);	r = VARBITS(result);	for (i = 0; i < VARBITBYTES(arg1); i++)		*r++ = *p1++ | *p2++;	/* Pad the result */	mask = BITMASK << VARBITPAD(result);	if (mask)	{		r--;		*r &= mask;	}	PG_RETURN_VARBIT_P(result);}/* bitxor * perform a logical XOR on two bit strings. */Datumbitxor(PG_FUNCTION_ARGS){	VarBit	   *arg1 = PG_GETARG_VARBIT_P(0);	VarBit	   *arg2 = PG_GETARG_VARBIT_P(1);	VarBit	   *result;	int			len,				bitlen1,				bitlen2,				i;	bits8	   *p1,			   *p2,			   *r;	bits8		mask;	bitlen1 = VARBITLEN(arg1);	bitlen2 = VARBITLEN(arg2);	if (bitlen1 != bitlen2)		ereport(ERROR,				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				 errmsg("cannot XOR bit strings of different sizes")));	len = VARSIZE(arg1);	result = (VarBit *) palloc(len);	VARATT_SIZEP(result) = len;	VARBITLEN(result) = bitlen1;	p1 = VARBITS(arg1);	p2 = VARBITS(arg2);	r = VARBITS(result);	for (i = 0; i < VARBITBYTES(arg1); i++)		*r++ = *p1++ ^ *p2++;	/* Pad the result */	mask = BITMASK << VARBITPAD(result);	if (mask)	{		r--;		*r &= mask;	}	PG_RETURN_VARBIT_P(result);}/* bitnot * perform a logical NOT on a bit string. */Datumbitnot(PG_FUNCTION_ARGS){	VarBit	   *arg = PG_GETARG_VARBIT_P(0);	VarBit	   *result;	bits8	   *p,			   *r;	bits8		mask;	result = (VarBit *) palloc(VARSIZE(arg));	VARATT_SIZEP(result) = VARSIZE(arg);	VARBITLEN(result) = VARBITLEN(arg);	p = VARBITS(arg);	r = VARBITS(result);	for (; p < VARBITEND(arg); p++)		*r++ = ~*p;	/* Pad the result */	mask = BITMASK << VARBITPAD(result);	if (mask)	{		r--;		*r &= mask;	}	PG_RETURN_VARBIT_P(result);}/* bitshiftleft * do a left shift (i.e. towards the beginning of the string) */Datumbitshiftleft(PG_FUNCTION_ARGS){	VarBit	   *arg = PG_GETARG_VARBIT_P(0);	int32		shft = PG_GETARG_INT32(1);	VarBit	   *result;	int			byte_shift,				ishift,				len;	bits8	   *p,			   *r;	/* Negative shift is a shift to the right */	if (shft < 0)		PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,											VarBitPGetDatum(arg),											Int32GetDatum(-shft)));	result = (VarBit *) palloc(VARSIZE(arg));	VARATT_SIZEP(result) = VARSIZE(arg);	VARBITLEN(result) = VARBITLEN(arg);	r = VARBITS(result);	/* If we shifted all the bits out, return an all-zero string */	if (shft >= VARBITLEN(arg))	{		MemSet(r, 0, VARBITBYTES(arg));		PG_RETURN_VARBIT_P(result);	}	byte_shift = shft / BITS_PER_BYTE;	ishift = shft % BITS_PER_BYTE;	p = VARBITS(arg) + byte_shift;	if (ishift == 0)	{		/* Special case: we can do a memcpy */		len = VARBITBYTES(arg) - byte_shift;		memcpy(r, p, len);		MemSet(r + len, 0, byte_shift);	}	else	{		for (; p < VARBITEND(arg); r++)		{			*r = *p << ishift;			if ((++p) < VARBITEND(arg))				*r |= *p >> (BITS_PER_BYTE - ishift);		}		for (; r < VARBITEND(result); r++)			*r = 0;	}	PG_RETURN_VARBIT_P(result);}/* bitshiftright * do a right shift (i.e. towards the end of the string) */Datumbitshiftright(PG_FUNCTION_ARGS){	VarBit	   *arg = PG_GETARG_VARBIT_P(0);	int32		shft = PG_GETARG_INT32(1);	VarBit	   *result;	int			byte_shift,				ishift,				len;	bits8	   *p,			   *r;	/* Negative shift is a shift to the left */	if (shft < 0)		PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,											VarBitPGetDatum(arg),											Int32GetDatum(-shft)));	result = (VarBit *) palloc(VARSIZE(arg));	VARATT_SIZEP(result) = VARSIZE(arg);	VARBITLEN(result) = VARBITLEN(arg);	r = VARBITS(result);	/* If we shifted all the bits out, return an all-zero string */	if (shft >= VARBITLEN(arg))	{		MemSet(r, 0, VARBITBYTES(arg));		PG_RETURN_VARBIT_P(result);	}	byte_shift = shft / BITS_PER_BYTE;	ishift = shft % BITS_PER_BYTE;	p = VARBITS(arg);	/* Set the first part of the result to 0 */	MemSet(r, 0, byte_shift);	r += byte_shift;	if (ishift == 0)	{		/* Special case: we can do a memcpy */		len = VARBITBYTES(arg) - byte_shift;		memcpy(r, p, len);	}	else	{		if (r < VARBITEND(result))			*r = 0;				/* initialize first byte */		for (; r < VARBITEND(result); p++)		{			*r |= *p >> ishift;			if ((++r) < VARBITEND(result))				*r = (*p << (BITS_PER_BYTE - ishift)) & BITMASK;		}	}	PG_RETURN_VARBIT_P(result);}/* * This is not defined in any standard. We retain the natural ordering of * bits here, as it just seems more intuitive. */Datumbitfromint4(PG_FUNCTION_ARGS){	int32		a = PG_GETARG_INT32(0);	int32		typmod = PG_GETARG_INT32(1);	VarBit	   *result;	bits8	   *r;	int			rlen;	int			destbitsleft,				srcbitsleft;	if (typmod <= 0)		typmod = 1;				/* default bit length */	rlen = VARBITTOTALLEN(typmod);	result = (VarBit *) palloc(rlen);	VARATT_SIZEP(result) = rlen;	VARBITLEN(result) = typmod;	r = VARBITS(result);	destbitsleft = typmod;	srcbitsleft = 32;	/* drop any input bits that don't fit */	srcbitsleft = Min(srcbitsleft, destbitsleft);	/* sign-fill any excess bytes in output */	while (destbitsleft >= srcbitsleft + 8)	{		*r++ = (bits8) ((a < 0) ? BITMASK : 0);		destbitsleft -= 8;	}	/* store first fractional byte */	if (destbitsleft > srcbitsleft)	{		*r++ = (bits8) ((a >> (srcbitsleft - 8)) & BITMASK);		destbitsleft -= 8;	}	/* Now srcbitsleft and destbitsleft are the same, need not track both */	/* store whole bytes */	while (destbitsleft >= 8)	{		*r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);		destbitsleft -= 8;	}	/* store last fractional byte */	if (destbitsleft > 0)		*r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);	PG_RETURN_VARBIT_P(result);}Datumbittoint4(PG_FUNCTION_ARGS){	VarBit	   *arg = PG_GETARG_VARBIT_P(0);	uint32		result;	bits8	   *r;	/* Check that the bit string is not too long */	if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("integer out of range")));	result = 0;	for (r = VARBITS(arg); r < VARBITEND(arg); r++)	{		result <<= BITS_PER_BYTE;		result |= *r;	}	/* Now shift the result to take account of the padding at the end */	result >>= VARBITPAD(arg);	PG_RETURN_INT32(result);}Datumbitfromint8(PG_FUNCTION_ARGS){	int64		a = PG_GETARG_INT64(0);	int32		typmod = PG_GETARG_INT32(1);	VarBit	   *result;	bits8	   *r;	int			rlen;	int			destbitsleft,				srcbitsleft;	if (typmod <= 0)		typmod = 1;				/* default bit length */	rlen = VARBITTOTALLEN(typmod);	result = (VarBit *) palloc(rlen);	VARATT_SIZEP(result) = rlen;	VARBITLEN(result) = typmod;	r = VARBITS(result);	destbitsleft = typmod;#ifndef INT64_IS_BUSTED	srcbitsleft = 64;#else	srcbitsleft = 32;			/* don't try to shift more than 32 */#endif	/* drop any input bits that don't fit */	srcbitsleft = Min(srcbitsleft, destbitsleft);	/* sign-fill any excess bytes in output */	while (destbitsleft >= srcbitsleft + 8)	{		*r++ = (bits8) ((a < 0) ? BITMASK : 0);		destbitsleft -= 8;	}	/* store first fractional byte */	if (destbitsleft > srcbitsleft)	{		*r++ = (bits8) ((a >> (srcbitsleft - 8)) & BITMASK);		destbitsleft -= 8;	}	/* Now srcbitsleft and destbitsleft are the same, need not track both */	/* store whole bytes */	while (destbitsleft >= 8)	{		*r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);		destbitsleft -= 8;	}	/* store last fractional byte */	if (destbitsleft > 0)		*r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);	PG_RETURN_VARBIT_P(result);}Datumbittoint8(PG_FUNCTION_ARGS){	VarBit	   *arg = PG_GETARG_VARBIT_P(0);	uint64		result;	bits8	   *r;	/* Check that the bit string is not too long */	if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("bigint out of range")));	result = 0;	for (r = VARBITS(arg); r < VARBITEND(arg); r++)	{		result <<= BITS_PER_BYTE;		result |= *r;	}	/* Now shift the result to take account of the padding at the end */	result >>= VARBITPAD(arg);	PG_RETURN_INT64(result);}/* Determines the position of S2 in the bitstring S1 (1-based string). * If S2 does not appear in S1 this function returns 0. * If S2 is of length 0 this function returns 1. * Compatible in usage with POSITION() functions for other data types. */Datumbitposition(PG_FUNCTION_ARGS){	VarBit	   *str = PG_GETARG_VARBIT_P(0);	VarBit	   *substr = PG_GETARG_VARBIT_P(1);	int			substr_length,				str_length,				i,				is;	bits8	   *s,				/* pointer into substring */			   *p;				/* pointer into str */	bits8		cmp,			/* shifted substring byte to compare */				mask1,			/* mask for substring byte shifted right */				mask2,			/* mask for substring byte shifted left */				end_mask,		/* pad mask for last substring byte */				str_mask;		/* pad mask for last string byte */	bool		is_match;	/* Get the substring length */	substr_length = VARBITLEN(substr);	str_length = VARBITLEN(str);	/* String has zero length or substring longer than string, return 0 */	if ((str_length == 0) || (substr_length > str_length))		PG_RETURN_INT32(0);	/* zero-length substring means return 1 */	if (substr_length == 0)		PG_RETURN_INT32(1);	/* Initialise the padding masks */	end_mask = BITMASK << VARBITPAD(substr);	str_mask = BITMASK << VARBITPAD(str);	for (i = 0; i < VARBITBYTES(str) - VARBITBYTES(substr) + 1; i++)	{		for (is = 0; is < BITS_PER_BYTE; is++)		{			is_match = true;			p = VARBITS(str) + i;			mask1 = BITMASK >> is;			mask2 = ~mask1;			for (s = VARBITS(substr);				 is_match && s < VARBITEND(substr); s++)			{				cmp = *s >> is;				if (s == VARBITEND(substr) - 1)				{					mask1 &= end_mask >> is;					if (p == VARBITEND(str) - 1)					{						/* Check that there is enough of str left */						if (mask1 & ~str_mask)						{							is_match = false;							break;						}						mask1 &= str_mask;					}				}				is_match = ((cmp ^ *p) & mask1) == 0;				if (!is_match)					break;				/* Move on to the next byte */				p++;				if (p == VARBITEND(str))				{					mask2 = end_mask << (BITS_PER_BYTE - is);					is_match = mask2 == 0;#if 0					elog(DEBUG4, "S. %d %d em=%2x sm=%2x r=%d",						 i, is, end_mask, mask2, is_match);#endif					break;				}				cmp = *s << (BITS_PER_BYTE - is);				if (s == VARBITEND(substr) - 1)				{					mask2 &= end_mask << (BITS_PER_BYTE - is);					if (p == VARBITEND(str) - 1)					{						if (mask2 & ~str_mask)						{							is_match = false;							break;						}						mask2 &= str_mask;					}				}				is_match = ((cmp ^ *p) & mask2) == 0;			}			/* Have we found a match? */			if (is_match)				PG_RETURN_INT32(i * BITS_PER_BYTE + is + 1);		}	}	PG_RETURN_INT32(0);}

⌨️ 快捷键说明

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