mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 10:30:33 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			833 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			833 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*-------------------------------------------------------------------------
 | |
|  *
 | |
|  * varbit.c
 | |
|  *	  Functions for the built-in type bit() and varying bit().
 | |
|  *
 | |
|  * IDENTIFICATION
 | |
|  *	  $Header: /cvsroot/pgsql/contrib/bit/Attic/varbit.c,v 1.1 1999/11/29 22:34:36 momjian Exp $
 | |
|  *
 | |
|  *-------------------------------------------------------------------------
 | |
|  */
 | |
| #include "postgres.h"
 | |
| #include "varbit.h"
 | |
| /*
 | |
| #include "access/htup.h"
 | |
| #include "catalog/pg_type.h"
 | |
| #include "utils/builtins.h"
 | |
| */
 | |
| 
 | |
| 
 | |
| 
 | |
| /* 
 | |
|    Prefixes:
 | |
|      zp    -- zero-padded fixed length bit string
 | |
|      var   -- varying bit string
 | |
| 
 | |
|    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 -- lenght of the bit string in bits
 | |
| 	 bitdata   -- least significant byte first string
 | |
| */
 | |
| 
 | |
| /*
 | |
|  * zpbitin -
 | |
| 
 | |
|  *	  converts a string to the internal representation of a bitstring.
 | |
|  *        The length is determined by the number of bits required plus
 | |
|  *        VARHDRSZ bytes or from atttypmod. 
 | |
|  *	  (XXX dummy is here because we pass typelem as the second argument 
 | |
|  *        for array_in. copied this, no idea what it means??)
 | |
|  */
 | |
| char *
 | |
| zpbitin(char *s, int dummy,  int32 atttypmod)
 | |
| {
 | |
|   char *result, 
 | |
|     *sp;		/* pointer into the character string  */
 | |
|   bits8 *r;
 | |
|   int len,		/* Length of the whole data structure */
 | |
|     bitlen,		/* Number of bits in the bit string   */
 | |
|     slen;		/* Length of the input string         */
 | |
|   int bit_not_hex;      /* 0 = hex string  1=bit string       */
 | |
|   int i, bc, ipad;
 | |
|   bits8 x, y;
 | |
| 
 | |
| 
 | |
|   if (s == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   /* Check that the first character is a b or an x */
 | |
|   if (s[0]=='b' || s[0]=='B') 
 | |
|       bit_not_hex = 1;
 | |
|   else if (s[0]=='x' || s[0]=='X') 
 | |
|       bit_not_hex = 0;
 | |
|   else 
 | |
|     elog(ERROR, "zpbitin: %s is not a valid bitstring",s);
 | |
| 
 | |
|   slen = strlen(s) - 1;
 | |
|   /* Determine bitlength from input string */
 | |
|   bitlen = slen;
 | |
|   if (!bit_not_hex)
 | |
|     bitlen *= 4;
 | |
|   
 | |
|   /* Sometimes atttypmod is not supplied. If it is supplied we need to make
 | |
|      sure that the bitstring fits. Note that the number of infered bits can
 | |
|      be larger than the number of actual bits needed, but only if we are 
 | |
|      reading a hex string and not by more than 3 bits, as a hex string gives 
 | |
|      and accurate length upto 4 bits */
 | |
|   if (atttypmod == -1)
 | |
|     atttypmod = bitlen;
 | |
|   else
 | |
|     if (bitlen>atttypmod && bit_not_hex || bitlen>atttypmod+3 && !bit_not_hex)
 | |
| 	  elog(ERROR, "zpbitin: bit string of size %d cannot be written into bits(%d)",
 | |
| 	       bitlen,atttypmod);
 | |
| 
 | |
| 
 | |
|   len = VARBITDATALEN(atttypmod);
 | |
| 
 | |
|   if (len > MaxAttrSize)
 | |
|     elog(ERROR, "zpbitin: length of bit() must be less than %d",
 | |
| 	 (MaxAttrSize-VARHDRSZ-VARBITHDRSZ)*BITSPERBYTE);
 | |
| 
 | |
|   result = (char *) palloc(len);
 | |
|   /* set to 0 so that *r is always initialised and strin is zero-padded */
 | |
|   memset(result, 0, len);
 | |
|   VARSIZE(result) = len;
 | |
|   VARBITLEN(result) = atttypmod;
 | |
| 
 | |
|   /* We need to read the bitstring from the end, as we store it least 
 | |
|      significant byte first. s points to the byte before the beginning
 | |
|      of the bitstring */
 | |
|   sp = s+1;
 | |
|   r = (bits8 *) 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 (bc = 0; sp != s+slen+1; sp++, bc++)
 | |
| 	{
 | |
| 	  if (*sp=='1')
 | |
| 	    *r |= x;
 | |
| 	  if (bc==7) {
 | |
| 	    bc = 0;
 | |
| 	    x = BITHIGH;
 | |
| 	    r++;
 | |
| 	  } else 
 | |
| 	    x >>= 1;
 | |
| 	}
 | |
|      }
 | |
|   else 
 | |
|     {
 | |
|       /* Parse the hex representation of the string */
 | |
|       for (bc = 0; sp != s+slen+1; 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 
 | |
| 	    elog(ERROR,"Cannot parse %c as a hex digit",*sp);
 | |
| 	  if (bc) {
 | |
| 	    bc = 0;
 | |
| 	    *r++ |= x;
 | |
| 	  } else {
 | |
| 	    bc++;
 | |
| 	    *r = x<<4;
 | |
| 	  }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   if (bitlen > atttypmod) {
 | |
|     /* Check that this fitted */
 | |
|     r = (bits8 *) (result + len - 1);
 | |
|     ipad = VARBITPAD(result);
 | |
|     /* The bottom ipad bits of the byte pointed to by r need to be zero */
 | |
|     /*    printf("Byte %X  shift %X %d\n",*r,(*r << (8-ipad)) & BITMASK,
 | |
| 	   (*r << (8-ipad)) & BITMASK > 0);
 | |
|     */
 | |
|     if (((*r << (BITSPERBYTE-ipad)) & BITMASK) > 0)
 | |
|       elog(ERROR, "zpbitin: bit string too large for bit(%d) data type",
 | |
| 	   atttypmod);
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* zpbitout -
 | |
|  *    for the time being we print everything as hex strings, as this is likely 
 | |
|  *    to be more compact than bit strings, and consequently much more efficient
 | |
|  *    for long strings
 | |
|  */
 | |
| char *
 | |
| zpbitout(char *s)
 | |
| {
 | |
|   char	   *result, *r;
 | |
|   VarBit   sp;
 | |
|   int	   i, len, bitlen;
 | |
|   
 | |
|   if (s == NULL)
 | |
|     {
 | |
|       result = (char *) palloc(2);
 | |
|       result[0] = '-';
 | |
|       result[1] = '\0';
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       bitlen = VARBITLEN(s);
 | |
|       len = bitlen/4 + (bitlen%4>0 ? 1 : 0);
 | |
|       result = (char *) palloc(len + 4);
 | |
|       sp = (bits8 *) VARBITS(s);
 | |
|       r = result;
 | |
|       *r++ = 'X';
 | |
|       *r++ = '\'';
 | |
|       /* 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+1)
 | |
| 	r--;
 | |
|       *r++ = '\'';
 | |
|       *r = '\0';
 | |
|     }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* zpbitsout -
 | |
|  *    Prints the string a bits
 | |
|  */
 | |
| char *
 | |
| zpbitsout(char *s)
 | |
| {
 | |
|   char	   *result, *r;
 | |
|   VarBit   sp;
 | |
|   bits8    x;
 | |
|   int	   i, k, len;
 | |
|   
 | |
|   if (s == NULL)
 | |
|     {
 | |
|       result = (char *) palloc(2);
 | |
|       result[0] = '-';
 | |
|       result[1] = '\0';
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       len = VARBITLEN(s);
 | |
|       result = (char *) palloc(len + 4);
 | |
|       sp = (bits8 *) VARBITS(s);
 | |
|       r = result;
 | |
|       *r++ = 'B';
 | |
|       *r++ = '\'';
 | |
|       for (i=0; i<len-BITSPERBYTE; i+=BITSPERBYTE, sp++) {
 | |
| 	x = *sp;
 | |
| 	for (k=0; k<BITSPERBYTE; k++) 
 | |
| 	  {
 | |
| 	    *r++ = (x & BITHIGH) ? '1' : '0';
 | |
| 	    x <<= 1;
 | |
| 	  }
 | |
|       }
 | |
|       x = *sp;
 | |
|       for (k=i; k<len; k++)
 | |
| 	{
 | |
| 	  *r++ = (x & BITHIGH) ? '1' : '0';
 | |
| 	  x <<= 1;
 | |
| 	}
 | |
|       *r++ = '\'';
 | |
|       *r = '\0';
 | |
|     }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * varbitin -
 | |
|  *	  converts a string to the internal representation of a bitstring.
 | |
| */
 | |
| char *
 | |
| varbitin(char *s, int dummy,  int32 atttypmod)
 | |
| {
 | |
|   char *result, 
 | |
|     *sp;		/* pointer into the character string  */
 | |
|   bits8 *r;
 | |
|   int len,		/* Length of the whole data structure */
 | |
|     bitlen,		/* Number of bits in the bit string   */
 | |
|     slen;		/* Length of the input string         */
 | |
|   int bit_not_hex;
 | |
|   int i, bc, ipad;
 | |
|   bits8 x, y;
 | |
| 
 | |
| 
 | |
|   if (s == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   /* Check that the first character is a b or an x */
 | |
|   if (s[0]=='b' || s[0]=='B') 
 | |
|       bit_not_hex = 1;
 | |
|   else if (s[0]=='x' || s[0]=='X') 
 | |
|       bit_not_hex = 0;
 | |
|   else 
 | |
|     elog(ERROR, "zpbitin: %s is not a valid bitstring",s);
 | |
| 
 | |
|   slen = strlen(s) - 1;
 | |
|   /* Determine bitlength from input string */
 | |
|   bitlen = slen;
 | |
|   if (!bit_not_hex)
 | |
|     bitlen *= 4;
 | |
|   
 | |
|   /* Sometimes atttypmod is not supplied. If it is supplied we need to make
 | |
|      sure that the bitstring fits. Note that the number of infered bits can
 | |
|      be larger than the number of actual bits needed, but only if we are 
 | |
|      reading a hex string and not by more than 3 bits, as a hex string gives 
 | |
|      and accurate length upto 4 bits */
 | |
|   if (atttypmod > -1)
 | |
|     if (bitlen>atttypmod && bit_not_hex || bitlen>atttypmod+3 && !bit_not_hex)
 | |
| 	  elog(ERROR, "varbitin: bit string of size %d cannot be written into varying bits(%d)",
 | |
| 	       bitlen,atttypmod);
 | |
| 
 | |
| 
 | |
|   len = VARBITDATALEN(bitlen);
 | |
| 
 | |
|   if (len > MaxAttrSize)
 | |
|     elog(ERROR, "varbitin: length of bit() must be less than %d",
 | |
| 	 (MaxAttrSize-VARHDRSZ-VARBITHDRSZ)*BITSPERBYTE);
 | |
| 
 | |
|   result = (char *) palloc(len);
 | |
|   /* set to 0 so that *r is always initialised and strin is zero-padded */
 | |
|   memset(result, 0, len);
 | |
|   VARSIZE(result) = len;
 | |
|   VARBITLEN(result) = bitlen;
 | |
| 
 | |
|   /* We need to read the bitstring from the end, as we store it least 
 | |
|      significant byte first. s points to the byte before the beginning
 | |
|      of the bitstring */
 | |
|   sp = s + 1;
 | |
|   r = (VarBit) VARBITS(result);
 | |
|   if (bit_not_hex) 
 | |
|     {
 | |
|       /* Parse the bit representation of the string */
 | |
|       x = BITHIGH;
 | |
|       for (bc = 0; sp != s+slen+1; sp++, bc++)
 | |
| 	{
 | |
| 	  if (*sp=='1')
 | |
| 	    *r |= x;
 | |
| 	  if (bc==7) {
 | |
| 	    bc = 0;
 | |
| 	    x = BITHIGH;
 | |
| 	    r++;
 | |
| 	  } else 
 | |
| 	    x >>= 1;
 | |
| 	}
 | |
|      }
 | |
|   else 
 | |
|     {
 | |
|       for (bc = 0; sp != s+slen+1; 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 
 | |
| 	    elog(ERROR,"Cannot parse %c as a hex digit",*sp);
 | |
| 	  if (bc) {
 | |
| 	    bc = 0;
 | |
| 	    *r++ |= x;
 | |
| 	  } else {
 | |
| 	    bc++;
 | |
| 	    *r = x<<4;
 | |
| 	  }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   if (bitlen > atttypmod) {
 | |
|     /* Check that this fitted */
 | |
|     r = (bits8 *) (result + len - 1);
 | |
|     ipad = VARBITPAD(result);
 | |
|     /* The bottom ipad bits of the byte pointed to by r need to be zero */
 | |
|     if (((*r << (BITSPERBYTE-ipad)) & BITMASK) > 0)
 | |
|       elog(ERROR, "varbitin: bit string too large for varying bit(%d) data type",
 | |
| 	   atttypmod);
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   the zpbitout routines are fine for varying bits as well 
 | |
| */
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Comparison operators
 | |
|  *
 | |
|  * We only need one set of comparison operators for bitstrings, as the lengths
 | |
|  * are stored in the same way for zero-padded and varying bit strings. 
 | |
|  *
 | |
|  * Note that the standard is not unambiguous about the comparison between 
 | |
|  * zero-padded bit strings and varying bitstrings. If the same value is written
 | |
|  * into a zero padded bitstring as into a varying bitstring, but the zero 
 | |
|  * padded bitstring has greater length, it will be bigger. 
 | |
|  *
 | |
|  * Zeros from the beginning of a bitstring cannot simply be ignored, as they
 | |
|  * may be part of a bit string and may be significant.
 | |
|  */
 | |
| 
 | |
| bool
 | |
| biteq (char *arg1, char *arg2)
 | |
| {
 | |
|   int bitlen1,
 | |
|     bitlen2;
 | |
|   bits8 *p1, *p2;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return (bool) 0;
 | |
|   bitlen1 = VARBITLEN(arg1);
 | |
|   bitlen2 = VARBITLEN(arg2);
 | |
|   if (bitlen1 != bitlen2)
 | |
|     return (bool) 0;
 | |
|   
 | |
|   /* bit strings are always stored in a full number of bytes */
 | |
|   return memcmp((void *)VARBITS(arg1),(void *)VARBITS(arg2),
 | |
| 		VARBITBYTES(arg1)) == 0;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bitne (char *arg1, char *arg2)
 | |
| {
 | |
|   int bitlen1,
 | |
|     bitlen2;
 | |
|   bits8 *p1, *p2;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return (bool) 0;
 | |
|   bitlen1 = VARBITLEN(arg1);
 | |
|   bitlen2 = VARBITLEN(arg2);
 | |
|   if (bitlen1 != bitlen2)
 | |
|     return (bool) 1;
 | |
|   
 | |
|   /* bit strings are always stored in a full number of bytes */
 | |
|   return memcmp((void *)VARBITS(arg1),(void *)VARBITS(arg2),
 | |
| 		VARBITBYTES(arg1)) != 0;
 | |
| }
 | |
| 
 | |
| /* bitcmp
 | |
|  * 
 | |
|  * Compares two bitstrings and returns -1, 0, 1 depending on whether the first
 | |
|  * string is smaller, equal, or bigger than the second. All bits are considered
 | |
|  * and additional zero bits may make one string smaller/larger than the other,
 | |
|  * even if their zero-padded values would be the same.
 | |
|  *   Anything is equal to undefined.
 | |
|  */
 | |
| int 
 | |
| bitcmp (char *arg1, char *arg2)
 | |
| {
 | |
|   int bitlen1, bytelen1,
 | |
|     bitlen2, bytelen2;
 | |
|   bits8 *p1, *p2;
 | |
|   int cmp;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return (bool) 0;
 | |
|   bytelen1 = VARBITBYTES(arg1);  
 | |
|   bytelen2 = VARBITBYTES(arg2);
 | |
|   
 | |
|   cmp = memcmp(VARBITS(arg1),VARBITS(arg2),Min(bytelen1,bytelen2));
 | |
|   if (cmp==0) {
 | |
|     bitlen1 = VARBITLEN(arg1);
 | |
|     bitlen2 = VARBITLEN(arg2);
 | |
|     if (bitlen1 != bitlen2) 
 | |
|       return bitlen1 < bitlen2 ? -1 : 1;
 | |
|   }
 | |
|   return cmp;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bitlt (char *arg1, char *arg2)
 | |
| {
 | |
|   return (bool) (bitcmp(arg1,arg2) == -1);
 | |
| }
 | |
| 
 | |
| bool
 | |
| bitle (char *arg1, char *arg2)
 | |
| {
 | |
|   return (bool) (bitcmp(arg1,arg2) <= 0);
 | |
| }
 | |
| 
 | |
| bool
 | |
| bitge (char *arg1, char *arg2)
 | |
| {
 | |
|   return (bool) (bitcmp(arg1,arg2) >= 0);
 | |
| }
 | |
| 
 | |
| bool
 | |
| bitgt (char *arg1, char *arg2)
 | |
| {
 | |
|   return (bool) (bitcmp(arg1,arg2) == 1);
 | |
| }
 | |
| 
 | |
| /* bitcat
 | |
|  * Concatenation of bit strings
 | |
|  */
 | |
| char *
 | |
| bitcat (char *arg1, char *arg2)
 | |
| {
 | |
|   int bitlen1, bitlen2, bytelen, bit1pad, bit2shift;
 | |
|   char *result;
 | |
|   bits8 *pr, *pa;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return NULL;
 | |
| 
 | |
|   bitlen1 = VARBITLEN(arg1);
 | |
|   bitlen2 = VARBITLEN(arg2);
 | |
| 
 | |
|   bytelen = VARBITDATALEN(bitlen1+bitlen2);
 | |
|   
 | |
|   result = (char *) palloc(bytelen*sizeof(bits8));
 | |
|   VARSIZE(result) = bytelen;
 | |
|   VARBITLEN(result) = bitlen1+bitlen2;
 | |
|   printf("%d %d %d \n",VARBITBYTES(arg1),VARBITLEN(arg1),VARBITPAD(arg1));
 | |
|   /* Copy the first bitstring in */
 | |
|   memcpy(VARBITS(result),VARBITS(arg1),VARBITBYTES(arg1));
 | |
|   /* Copy the second bit string */
 | |
|   bit1pad = VARBITPAD(arg1);
 | |
|   if (bit1pad==0) 
 | |
|     {
 | |
|       memcpy(VARBITS(result)+VARBITBYTES(arg1),VARBITS(arg2),
 | |
| 	     VARBITBYTES(arg2));
 | |
|     }
 | |
|   else if (bitlen2>0)
 | |
|     {
 | |
|       /* We need to shift all the results to fit */
 | |
|       bit2shift = BITSPERBYTE - bit1pad;
 | |
|       pa = (VarBit) VARBITS(arg2);
 | |
|       pr = (VarBit) VARBITS(result)+VARBITBYTES(arg1)-1;
 | |
|       for ( ; pa < VARBITEND(arg2); pa++) {
 | |
| 	*pr = *pr | ((*pa >> bit2shift) & BITMASK);
 | |
| 	pr++;
 | |
| 	if (pr < VARBITEND(result))
 | |
| 	  *pr = (*pa << bit1pad) & BITMASK;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitsubstr
 | |
|  * retrieve a substring from the bit string. 
 | |
|  * Note, s is 1-based.
 | |
|  * SQL draft 6.10 9)
 | |
|  */
 | |
| char * 
 | |
| bitsubstr (char *arg, int32 s, int32 l)
 | |
| {
 | |
|   int bitlen,
 | |
|     rbitlen,
 | |
|     len,
 | |
|     ipad,
 | |
|     ishift,
 | |
|     i;
 | |
|   int e, s1, e1;
 | |
|   char * result;
 | |
|   bits8 mask, *r, *ps;
 | |
| 
 | |
|   if (!PointerIsValid(arg))
 | |
|     return NULL;
 | |
| 
 | |
|   bitlen = VARBITLEN(arg);
 | |
|   e = s+l;
 | |
|   s1 = Max(s,1);
 | |
|   e1 = Min(e,bitlen+1);
 | |
|   if (s1>bitlen || e1<1) 
 | |
|     {
 | |
|       /* Need to return a null string */
 | |
|       len = VARBITDATALEN(0);
 | |
|       result = (char *) palloc(len);
 | |
|       VARBITLEN(result) = 0;
 | |
|       VARSIZE(result) = len;
 | |
|     } 
 | |
|   else 
 | |
|     {
 | |
|       /* OK, we've got a true substring starting at position s1-1 and 
 | |
| 	 ending at position e1-1 */
 | |
|       rbitlen = e1-s1;
 | |
|       len = VARBITDATALEN(rbitlen);
 | |
|       result = (char *) palloc(len);
 | |
|       VARBITLEN(result) = rbitlen;
 | |
|       VARSIZE(result) = len;
 | |
|       /* Are we copying from a byte boundary? */
 | |
|       if ((s1-1)%BITSPERBYTE==0) 
 | |
| 	{
 | |
| 	  /* Yep, we are copying bytes */
 | |
| 	  len -= VARHDRSZ + VARBITHDRSZ;
 | |
| 	  memcpy(VARBITS(result),VARBITS(arg)+(s1-1)/BITSPERBYTE,len);
 | |
| 	} 
 | |
|       else 
 | |
| 	{
 | |
| 	  /* Figure out how much we need to shift the sequence by */
 | |
| 	  ishift = (s1-1)%BITSPERBYTE;
 | |
| 	  r = (VarBit) VARBITS(result);
 | |
| 	  ps = (VarBit) VARBITS(arg) + (s1-1)/BITSPERBYTE;
 | |
| 	  for (i=0; i<len; i++) 
 | |
| 	    {
 | |
| 	      *r = (*ps <<ishift) & BITMASK;
 | |
| 	      if ((++ps) < VARBITEND(arg))
 | |
| 		*r |= *ps >>(BITSPERBYTE-ishift);
 | |
| 	      r++;
 | |
| 	    }
 | |
| 	}
 | |
|       /* Do we need to pad at the end? */
 | |
|       ipad = VARBITPAD(result);
 | |
|       if (ipad > 0) 
 | |
| 	{
 | |
| 	  mask = BITMASK << ipad;
 | |
| 	  *(VARBITS(result) + len - 1) &= mask;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitand
 | |
|  * perform a logical AND on two bit strings. The result is automatically
 | |
|  * truncated to the shorter bit string
 | |
|  */
 | |
| char *
 | |
| bitand (char * arg1, char * arg2)
 | |
| {
 | |
|   int len,
 | |
|     i;
 | |
|   char *result;
 | |
|   bits8 *p1, 
 | |
|     *p2, 
 | |
|     *r;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return (bool) 0;
 | |
| 
 | |
|   len = Min(VARSIZE(arg1),VARSIZE(arg2));
 | |
|   result = (char *) palloc(len);
 | |
|   VARSIZE(result) = len;
 | |
|   VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2));
 | |
| 
 | |
|   p1 = (bits8 *) VARBITS(arg1);
 | |
|   p2 = (bits8 *) VARBITS(arg2);
 | |
|   r = (bits8 *) VARBITS(result);
 | |
|   for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++)
 | |
|     *r++ = *p1++ & *p2++;
 | |
|   
 | |
|   /* Padding is not needed as & of 0 pad is 0 */
 | |
|   
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitor
 | |
|  * perform a logical OR on two bit strings. The result is automatically
 | |
|  * truncated to the shorter bit string.
 | |
|  */
 | |
| char *
 | |
| bitor (char * arg1, char * arg2)
 | |
| {
 | |
|   int len,
 | |
|     i;
 | |
|   char *result;
 | |
|   bits8 *p1, 
 | |
|     *p2, 
 | |
|     *r;
 | |
|   bits8 mask;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return (bool) 0;
 | |
| 
 | |
|   len = Min(VARSIZE(arg1),VARSIZE(arg2));
 | |
|   result = (char *) palloc(len);
 | |
|   VARSIZE(result) = len;
 | |
|   VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2));
 | |
| 
 | |
|   p1 = (bits8 *) VARBITS(arg1);
 | |
|   p2 = (bits8 *) VARBITS(arg2);
 | |
|   r = (bits8 *) VARBITS(result);
 | |
|   for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++)
 | |
|     *r++ = *p1++ | *p2++;
 | |
| 
 | |
|   /* Pad the result */
 | |
|   mask = BITMASK << VARBITPAD(result);
 | |
|   *r &= mask;
 | |
|   
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitxor
 | |
|  * perform a logical XOR on two bit strings. The result is automatically
 | |
|  * truncated to the shorter bit string.
 | |
|  */
 | |
| char *
 | |
| bitxor (char * arg1, char * arg2)
 | |
| {
 | |
|   int len,
 | |
|     i;
 | |
|   char *result;
 | |
|   bits8 *p1, 
 | |
|     *p2, 
 | |
|     *r;
 | |
|   bits8 mask;
 | |
| 
 | |
|   if (!PointerIsValid(arg1) || !PointerIsValid(arg2))
 | |
|     return (bool) 0;
 | |
| 
 | |
|   len = Min(VARSIZE(arg1),VARSIZE(arg2));
 | |
|   result = (char *) palloc(len);
 | |
|   VARSIZE(result) = len;
 | |
|   VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2));
 | |
| 
 | |
|   p1 = (bits8 *) VARBITS(arg1);
 | |
|   p2 = (bits8 *) VARBITS(arg2);
 | |
|   r = (bits8 *) VARBITS(result);
 | |
|   for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++)
 | |
|     {
 | |
|       *r++ = *p1++ ^ *p2++;
 | |
|     }
 | |
| 
 | |
|   /* Pad the result */
 | |
|   mask = BITMASK << VARBITPAD(result);
 | |
|   *r &= mask;
 | |
|   
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitnot
 | |
|  * perform a logical NOT on a bit strings.
 | |
|  */
 | |
| char *
 | |
| bitnot (char * arg)
 | |
| {
 | |
|   int len;
 | |
|   char *result;
 | |
|   bits8 *p, 
 | |
|     *r;
 | |
|   bits8 mask;
 | |
| 
 | |
|   if (!PointerIsValid(arg))
 | |
|     return (bool) 0;
 | |
| 
 | |
|   result = (char *) palloc(VARSIZE(arg));
 | |
|   VARSIZE(result) = VARSIZE(arg);
 | |
|   VARBITLEN(result) = VARBITLEN(arg);
 | |
| 
 | |
|   p = (bits8 *) VARBITS(arg);
 | |
|   r = (bits8 *) VARBITS(result);
 | |
|   for ( ; p < VARBITEND(arg); p++, r++)
 | |
|     *r = ~*p;
 | |
| 
 | |
|   /* Pad the result */
 | |
|   mask = BITMASK << VARBITPAD(result);
 | |
|   *r &= mask;
 | |
|   
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitshiftleft
 | |
|  * do a left shift (i.e. to the beginning of the string) of the bit string
 | |
|  */
 | |
| char *
 | |
| bitshiftleft (char * arg, int shft)
 | |
| {
 | |
|   int byte_shift, ishift, len;
 | |
|   char *result;
 | |
|   bits8 *p, 
 | |
|     *r;
 | |
| 
 | |
|   if (!PointerIsValid(arg))
 | |
|     return (bool) 0;
 | |
| 
 | |
|   /* Negative shift is a shift to the right */
 | |
|   if (shft < 0) 
 | |
|     return bitshiftright(arg, -shft);
 | |
| 
 | |
|   result = (char *) palloc(VARSIZE(arg));
 | |
|   VARSIZE(result) = VARSIZE(arg);
 | |
|   VARBITLEN(result) = VARBITLEN(arg);
 | |
|   r = (bits8 *) VARBITS(result);
 | |
| 
 | |
|   byte_shift = shft/BITSPERBYTE;
 | |
|   ishift = shft % BITSPERBYTE;
 | |
|   p = ((bits8 *) 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 >>(BITSPERBYTE-ishift);
 | |
|     }
 | |
|     for ( ; r < VARBITEND(result) ; r++ ) 
 | |
|       *r = (bits8) 0;
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* bitshiftright
 | |
|  * do a right shift (i.e. to the beginning of the string) of the bit string
 | |
|  */
 | |
| char *
 | |
| bitshiftright (char * arg, int shft)
 | |
| {
 | |
|   int byte_shift, ishift, len;
 | |
|   char *result;
 | |
|   bits8 *p, 
 | |
|     *r;
 | |
| 
 | |
|   if (!PointerIsValid(arg))
 | |
|     return (bool) 0;
 | |
| 
 | |
|   /* Negative shift is a shift to the left */
 | |
|   if (shft < 0) 
 | |
|     return bitshiftleft(arg, -shft);
 | |
| 
 | |
|   result = (char *) palloc(VARSIZE(arg));
 | |
|   VARSIZE(result) = VARSIZE(arg);
 | |
|   VARBITLEN(result) = VARBITLEN(arg);
 | |
|   r = (bits8 *) VARBITS(result);
 | |
| 
 | |
|   byte_shift = shft/BITSPERBYTE;
 | |
|   ishift = shft % BITSPERBYTE;
 | |
|   p = (bits8 *) VARBITS(arg);
 | |
| 
 | |
|   /* Set the first part of the result to 0 */
 | |
|   memset(r, 0, byte_shift);
 | |
|   
 | |
|   if (ishift == 0) 
 | |
|     {
 | |
|       /* Special case: we can do a memcpy */
 | |
|       len = VARBITBYTES(arg) - byte_shift;
 | |
|       memcpy(r+byte_shift, p, len);
 | |
|     } 
 | |
|   else 
 | |
|     {
 | |
|       r += byte_shift;
 | |
|       *r = 0;    /* Initialise first byte */
 | |
|       for ( ; r < VARBITEND(result); p++) {
 | |
| 	*r |= *p >> ishift;
 | |
| 	if ((++r) < VARBITEND(result))
 | |
| 	  *r = (*p <<(BITSPERBYTE-ishift)) & BITMASK;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   return result;
 | |
| }
 |