varbit.c.patch

text/plain

Filename: varbit.c.patch
Type: text/plain
Part: 0
Message: Re: BIT/BIT VARYING status
*** src/backend/utils/adt/varbit.c.old	Sun Oct 29 11:05:11 2000
--- src/backend/utils/adt/varbit.c	Mon Oct 30 04:58:35 2000
***************
*** 1053,1060 ****
  	/* 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);
--- 1053,1060 ----
  	/* 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);
***************
*** 1145,1148 ****
--- 1145,1242 ----
  	result >>= VARBITPAD(arg);
  
  	PG_RETURN_INT32(result);
+ }
+ 
+ /* Determines the position of S1 in the bitstring S2 (1-based string).
+  * If S1 does not appear in S2 this function returns 0.
+  * If S1 is of length 0 this function returns 1.
+  */
+ Datum
+ bitposition(PG_FUNCTION_ARGS)
+ {
+ 	VarBit		*substr = PG_GETARG_VARBIT_P(0);
+ 	VarBit		*arg = PG_GETARG_VARBIT_P(1);
+ 	int			substr_length, 
+ 				arg_length,
+ 				i,
+ 				is;
+ 	bits8		*s,				/* pointer into substring */
+ 				*p;				/* pointer into arg */
+ 	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 */
+ 				arg_mask;		/* pad mask for last argument byte */
+ 	bool		is_match;
+ 
+ 	/* Get the substring length */
+ 	substr_length = VARBITLEN(substr);
+ 	arg_length = VARBITLEN(arg);
+ 
+ 	/* Argument has 0 length or substring longer than argument, return 0 */
+ 	if (arg_length == 0 || substr_length > arg_length)
+ 		PG_RETURN_INT32(0);	
+ 	
+ 	/* 0-length means return 1 */
+ 	if (substr_length == 0)
+ 		PG_RETURN_INT32(1);
+ 
+ 	/* Initialise the padding masks */
+ 	end_mask = BITMASK << VARBITPAD(substr);
+ 	arg_mask = BITMASK << VARBITPAD(arg);
+ 	for (i = 0; i < VARBITBYTES(arg) - VARBITBYTES(substr) + 1; i++) 
+ 	{
+ 		for (is = 0; is < BITS_PER_BYTE; is++) {
+ 			is_match = true;
+ 			p = VARBITS(arg) + 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(arg) - 1) {
+ 						/* Check that there is enough of arg left */
+ 						if (mask1 & ~arg_mask) {
+ 							is_match = false;
+ 							break;
+ 						}
+ 						mask1 &= arg_mask;
+ 					}
+ 				}
+ 				is_match = ((cmp ^ *p) & mask1) == 0;
+ 				if (!is_match)
+ 					break;
+ 				// Move on to the next byte
+ 				p++;
+ 				if (p == VARBITEND(arg)) {
+ 					mask2 = end_mask << (BITS_PER_BYTE - is);
+ 					is_match = mask2 == 0;
+ 					elog(NOTICE,"S. %d %d em=%2x sm=%2x r=%d",
+ 						 i,is,end_mask,mask2,is_match);
+ 					break;
+ 				}
+ 				cmp = *s << (BITS_PER_BYTE - is);
+ 				if (s == VARBITEND(substr) - 1) 
+ 				{
+ 					mask2 &= end_mask << (BITS_PER_BYTE - is);
+ 					if (p == VARBITEND(arg) - 1) {
+ 						if (mask2 & ~arg_mask) {
+ 							is_match = false;
+ 							break;
+ 						}
+ 						mask2 &= arg_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);
  }