varbit.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 1,399 行 · 第 1/3 页

C
1,399
字号
/*------------------------------------------------------------------------- * * varbit.c *	  Functions for the SQL datatypes BIT() and BIT VARYING(). * * Code originally contributed by Adriaan Joubert. * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.37 2003/09/25 06:58:05 petere 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){	/* Exactly the same as varbit_recv, so share code */	return varbit_recv(fcinfo);}/* *		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_LENGTH_MISMATCH),				 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 * * External format is the bitlen as an int32, then the byte array. */Datumvarbit_recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	VarBit	   *result;	int			len,				bitlen;	int			ipad;	bits8		mask;

⌨️ 快捷键说明

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