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

📄 varbit.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * varbit.c *	  Functions for the SQL datatypes BIT() and BIT VARYING(). * * Code originally contributed by Adriaan Joubert. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.47 2005/10/15 02:49:30 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "catalog/pg_type.h"#include "libpq/pqformat.h"#include "utils/array.h"#include "utils/fmgroids.h"#include "utils/memutils.h"#include "utils/varbit.h"#define HEXDIG(z)	 ((z)<10 ? ((z)+'0') : ((z)-10+'A'))/*---------- *	attypmod -- contains the length of the bit string in bits, or for *			   varying bits the maximum length. * *	The data structure contains the following elements: *	  header  -- length of the whole data structure (incl header) *				 in bytes. (as with all varying length datatypes) *	  data section -- private data section for the bits data structures *		bitlength -- length of the bit string in bits *		bitdata   -- bit string, most significant byte first * *	The length of the bitdata vector should always be exactly as many *	bytes as are needed for the given bitlength.  If the bitlength is *	not a multiple of 8, the extra low-order padding bits of the last *	byte must be zeroes. *---------- *//* * bit_in - *	  converts a char string to the internal representation of a bitstring. *		  The length is determined by the number of bits required plus *		  VARHDRSZ bytes or from atttypmod. */Datumbit_in(PG_FUNCTION_ARGS){	char	   *input_string = PG_GETARG_CSTRING(0);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		atttypmod = PG_GETARG_INT32(2);	VarBit	   *result;			/* The resulting bit string			  */	char	   *sp;				/* pointer into the character string  */	bits8	   *r;				/* pointer into the result */	int			len,			/* Length of the whole data structure */				bitlen,			/* Number of bits in the bit string   */				slen;			/* Length of the input string		  */	bool		bit_not_hex;	/* false = hex string  true = bit string */	int			bc;	bits8		x = 0;	/* Check that the first character is a b or an x */	if (input_string[0] == 'b' || input_string[0] == 'B')	{		bit_not_hex = true;		sp = input_string + 1;	}	else if (input_string[0] == 'x' || input_string[0] == 'X')	{		bit_not_hex = false;		sp = input_string + 1;	}	else	{		/*		 * Otherwise it's binary.  This allows things like cast('1001' as bit)		 * to work transparently.		 */		bit_not_hex = true;		sp = input_string;	}	slen = strlen(sp);	/* Determine bitlength from input string */	if (bit_not_hex)		bitlen = slen;	else		bitlen = slen * 4;	/*	 * Sometimes atttypmod is not supplied. If it is supplied we need to make	 * sure that the bitstring fits.	 */	if (atttypmod <= 0)		atttypmod = bitlen;	else if (bitlen != atttypmod)		ereport(ERROR,				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				 errmsg("bit string length %d does not match type bit(%d)",						bitlen, atttypmod)));	len = VARBITTOTALLEN(atttypmod);	/* set to 0 so that *r is always initialised and string is zero-padded */	result = (VarBit *) palloc0(len);	VARATT_SIZEP(result) = len;	VARBITLEN(result) = atttypmod;	r = VARBITS(result);	if (bit_not_hex)	{		/* Parse the bit representation of the string */		/* We know it fits, as bitlen was compared to atttypmod */		x = BITHIGH;		for (; *sp; sp++)		{			if (*sp == '1')				*r |= x;			else if (*sp != '0')				ereport(ERROR,						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),						 errmsg("\"%c\" is not a valid binary digit",								*sp)));			x >>= 1;			if (x == 0)			{				x = BITHIGH;				r++;			}		}	}	else	{		/* Parse the hex representation of the string */		for (bc = 0; *sp; sp++)		{			if (*sp >= '0' && *sp <= '9')				x = (bits8) (*sp - '0');			else if (*sp >= 'A' && *sp <= 'F')				x = (bits8) (*sp - 'A') + 10;			else if (*sp >= 'a' && *sp <= 'f')				x = (bits8) (*sp - 'a') + 10;			else				ereport(ERROR,						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),						 errmsg("\"%c\" is not a valid hexadecimal digit",								*sp)));			if (bc)			{				*r++ |= x;				bc = 0;			}			else			{				*r = x << 4;				bc = 1;			}		}	}	PG_RETURN_VARBIT_P(result);}Datumbit_out(PG_FUNCTION_ARGS){#if 1	/* same as varbit output */	return varbit_out(fcinfo);#else/* This is how one would print a hex string, in case someone wants to   write a formatting function. */	VarBit	   *s = PG_GETARG_VARBIT_P(0);	char	   *result,			   *r;	bits8	   *sp;	int			i,				len,				bitlen;	bitlen = VARBITLEN(s);	len = (bitlen + 3) / 4;	result = (char *) palloc(len + 2);	sp = VARBITS(s);	r = result;	*r++ = 'X';	/* we cheat by knowing that we store full bytes zero padded */	for (i = 0; i < len; i += 2, sp++)	{		*r++ = HEXDIG((*sp) >> 4);		*r++ = HEXDIG((*sp) & 0xF);	}	/*	 * Go back one step if we printed a hex number that was not part of the	 * bitstring anymore	 */	if (i > len)		r--;	*r = '\0';	PG_RETURN_CSTRING(result);#endif}/* *		bit_recv			- converts external binary format to bit */Datumbit_recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		atttypmod = PG_GETARG_INT32(2);	VarBit	   *result;	int			len,				bitlen;	int			ipad;	bits8		mask;	bitlen = pq_getmsgint(buf, sizeof(int32));	if (bitlen < 0)		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("invalid length in external bit string")));	/*	 * Sometimes atttypmod is not supplied. If it is supplied we need to make	 * sure that the bitstring fits.	 */	if (atttypmod > 0 && bitlen != atttypmod)		ereport(ERROR,				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				 errmsg("bit string length %d does not match type bit(%d)",						bitlen, atttypmod)));	len = VARBITTOTALLEN(bitlen);	result = (VarBit *) palloc(len);	VARATT_SIZEP(result) = len;	VARBITLEN(result) = bitlen;	pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));	/* Make sure last byte is zero-padded if needed */	ipad = VARBITPAD(result);	if (ipad > 0)	{		mask = BITMASK << ipad;		*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;	}	PG_RETURN_VARBIT_P(result);}/* *		bit_send			- converts bit to binary format */Datumbit_send(PG_FUNCTION_ARGS){	/* Exactly the same as varbit_send, so share code */	return varbit_send(fcinfo);}/* bit() * Converts a bit() type to a specific internal length. * len is the bitlength specified in the column definition. * * If doing implicit cast, raise error when source data is wrong length. * If doing explicit cast, silently truncate or zero-pad to specified length. */Datumbit(PG_FUNCTION_ARGS){	VarBit	   *arg = PG_GETARG_VARBIT_P(0);	int32		len = PG_GETARG_INT32(1);	bool		isExplicit = PG_GETARG_BOOL(2);	VarBit	   *result;	int			rlen;	int			ipad;	bits8		mask;	/* No work if typmod is invalid or supplied data matches it already */	if (len <= 0 || len == VARBITLEN(arg))		PG_RETURN_VARBIT_P(arg);	if (!isExplicit)		ereport(ERROR,				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				 errmsg("bit string length %d does not match type bit(%d)",						VARBITLEN(arg), len)));	rlen = VARBITTOTALLEN(len);	/* set to 0 so that string is zero-padded */	result = (VarBit *) palloc0(rlen);	VARATT_SIZEP(result) = rlen;	VARBITLEN(result) = len;	memcpy(VARBITS(result), VARBITS(arg),		   Min(VARBITBYTES(result), VARBITBYTES(arg)));	/*	 * Make sure last byte is zero-padded if needed.  This is useless but safe	 * if source data was shorter than target length (we assume the last byte	 * of the source data was itself correctly zero-padded).	 */	ipad = VARBITPAD(result);	if (ipad > 0)	{		mask = BITMASK << ipad;		*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;	}	PG_RETURN_VARBIT_P(result);}/* * varbit_in - *	  converts a string to the internal representation of a bitstring. *		This is the same as bit_in except that atttypmod is taken as *		the maximum length, not the exact length to force the bitstring to. */Datumvarbit_in(PG_FUNCTION_ARGS){	char	   *input_string = PG_GETARG_CSTRING(0);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		atttypmod = PG_GETARG_INT32(2);	VarBit	   *result;			/* The resulting bit string			  */	char	   *sp;				/* pointer into the character string  */	bits8	   *r;				/* pointer into the result */	int			len,			/* Length of the whole data structure */				bitlen,			/* Number of bits in the bit string   */				slen;			/* Length of the input string		  */	bool		bit_not_hex;	/* false = hex string  true = bit string */	int			bc;	bits8		x = 0;	/* Check that the first character is a b or an x */	if (input_string[0] == 'b' || input_string[0] == 'B')	{		bit_not_hex = true;		sp = input_string + 1;	}	else if (input_string[0] == 'x' || input_string[0] == 'X')	{		bit_not_hex = false;		sp = input_string + 1;	}	else	{		bit_not_hex = true;		sp = input_string;	}	slen = strlen(sp);	/* Determine bitlength from input string */	if (bit_not_hex)		bitlen = slen;	else		bitlen = slen * 4;	/*	 * Sometimes atttypmod is not supplied. If it is supplied we need to make	 * sure that the bitstring fits.	 */	if (atttypmod <= 0)		atttypmod = bitlen;	else if (bitlen > atttypmod)		ereport(ERROR,				(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),				 errmsg("bit string too long for type bit varying(%d)",						atttypmod)));	len = VARBITTOTALLEN(bitlen);	/* set to 0 so that *r is always initialised and string is zero-padded */	result = (VarBit *) palloc0(len);	VARATT_SIZEP(result) = len;	VARBITLEN(result) = Min(bitlen, atttypmod);	r = VARBITS(result);	if (bit_not_hex)	{		/* Parse the bit representation of the string */		/* We know it fits, as bitlen was compared to atttypmod */		x = BITHIGH;		for (; *sp; sp++)		{			if (*sp == '1')				*r |= x;			else if (*sp != '0')				ereport(ERROR,						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),						 errmsg("\"%c\" is not a valid binary digit",								*sp)));			x >>= 1;			if (x == 0)			{				x = BITHIGH;				r++;			}		}	}	else	{		/* Parse the hex representation of the string */		for (bc = 0; *sp; sp++)		{			if (*sp >= '0' && *sp <= '9')				x = (bits8) (*sp - '0');			else if (*sp >= 'A' && *sp <= 'F')				x = (bits8) (*sp - 'A') + 10;			else if (*sp >= 'a' && *sp <= 'f')				x = (bits8) (*sp - 'a') + 10;			else				ereport(ERROR,						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),						 errmsg("\"%c\" is not a valid hexadecimal digit",								*sp)));			if (bc)			{				*r++ |= x;				bc = 0;			}			else			{				*r = x << 4;				bc = 1;			}		}	}	PG_RETURN_VARBIT_P(result);}/* varbit_out - *	  Prints the string as bits to preserve length accurately */Datumvarbit_out(PG_FUNCTION_ARGS){	VarBit	   *s = PG_GETARG_VARBIT_P(0);	char	   *result,			   *r;	bits8	   *sp;	bits8		x;	int			i,				k,				len;	len = VARBITLEN(s);	result = (char *) palloc(len + 1);	sp = VARBITS(s);	r = result;	for (i = 0; i < len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++)	{		x = *sp;		for (k = 0; k < BITS_PER_BYTE; k++)		{			*r++ = (x & BITHIGH) ? '1' : '0';			x <<= 1;		}	}	x = *sp;	for (k = i; k < len; k++)	{		*r++ = (x & BITHIGH) ? '1' : '0';		x <<= 1;	}	*r = '\0';	PG_RETURN_CSTRING(result);}/* *		varbit_recv			- converts external binary format to varbit

⌨️ 快捷键说明

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