Attached are the C-routines that implement a BIT and BIT VARYING type.
Adriaan Joubert
This commit is contained in:
parent
47e51683e6
commit
1f747c6722
10
contrib/bit/Makefile
Normal file
10
contrib/bit/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CFLAGS = -g
|
||||||
|
|
||||||
|
varbit: vartest.o varbit.o
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
varbit.o: varbit.c varbit.h
|
||||||
|
vartest.o: vartest.c varbit.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o varbit
|
77
contrib/bit/README
Normal file
77
contrib/bit/README
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
A set of C routines to implement an SQL-compliant bitstring type.
|
||||||
|
|
||||||
|
The file varbit.c contains the c-functions to implement both BIT and
|
||||||
|
BIT VARYING. Both types are implemented in essentially the same way,
|
||||||
|
except that BIT is zero padded to a specified length. I've tried to
|
||||||
|
make this code as independent as possible of the byte length, but it
|
||||||
|
is quite possible that there may be problems on machines that don't
|
||||||
|
have 8 bits/byte (are there still any around?).
|
||||||
|
|
||||||
|
In the input routines I have assumed that the parser eats the quotes
|
||||||
|
in B'...' or X'...'.
|
||||||
|
|
||||||
|
The SQL standard only defines comparison, SUBSTR and concatenation
|
||||||
|
operators, and these have been implemented. In addition all logical
|
||||||
|
operators have been implemented, i.e. ~,|,&,^,<< and >>. This is
|
||||||
|
useful if one wants to build bit masks. If the two strings are not of
|
||||||
|
the same length the longer string is truncated (truncation was the
|
||||||
|
only real option, as padding with zeros could give unintuitive results
|
||||||
|
for ^) and the result has the length of the shorter string. If there
|
||||||
|
is a requirement for any other functions, let me know, and I will have
|
||||||
|
a look.
|
||||||
|
|
||||||
|
My knowledge of postgres is not up to integrating a type, so I'm hoping
|
||||||
|
that somebody can integrate this type for me, or give me some hints as
|
||||||
|
to what needs to be done. These routines were developed outside the
|
||||||
|
postgres source tree, with a hacked version of postgres.h. The header
|
||||||
|
files probably need some ammending.
|
||||||
|
|
||||||
|
The included files are
|
||||||
|
|
||||||
|
varbit.h -- bit string header type
|
||||||
|
varbit.c -- the routines
|
||||||
|
vartest.c -- a few calls to the routines to
|
||||||
|
|
||||||
|
The following routines are available.
|
||||||
|
|
||||||
|
char * zpbitin(char *s, int dummy, int32 atttypmod);
|
||||||
|
Read in a zero padded bit string of the form X'...' or B'...'
|
||||||
|
|
||||||
|
char * zpbitout(char *s);
|
||||||
|
Print a zero padded bit string in hex X'...'
|
||||||
|
|
||||||
|
char * zpbitsout(char *s);
|
||||||
|
Print a zero padded bit string in binary B'...'
|
||||||
|
|
||||||
|
char * varbitin(char *s, int dummy, int32 atttypmod);
|
||||||
|
Read in a varying length bit string of the form X'...' or B'...'
|
||||||
|
|
||||||
|
[There is no need for separate output functions for varying bit, as
|
||||||
|
zpbitout will print them out correctly]
|
||||||
|
|
||||||
|
char * bitcat (char *arg1, char *arg2);
|
||||||
|
Bit concatenation.
|
||||||
|
|
||||||
|
char * bitsubstr (char *arg, int32 s, int32 l);
|
||||||
|
Substring of a bit string.
|
||||||
|
|
||||||
|
bool biteq (char *arg1, char *arg2);
|
||||||
|
bool bitne (char *arg1, char *arg2);
|
||||||
|
bool bitge (char *arg1, char *arg2);
|
||||||
|
bool bitgt (char *arg1, char *arg2);
|
||||||
|
bool bitle (char *arg1, char *arg2);
|
||||||
|
bool bitlt (char *arg1, char *arg2);
|
||||||
|
int bitcmp (char *arg1, char *arg2);
|
||||||
|
Comparison operators
|
||||||
|
|
||||||
|
char * bitand (char * arg1, char * arg2);
|
||||||
|
char * bitor (char * arg1, char * arg2);
|
||||||
|
char * bitxor (char * arg1, char * arg2);
|
||||||
|
char * bitnot (char * arg);
|
||||||
|
char * bitshiftright (char * arg, int shft);
|
||||||
|
char * bitshiftleft (char * arg, int shft);
|
||||||
|
Bit operations.
|
||||||
|
|
||||||
|
If anything else needs to be done, please let me know.
|
||||||
|
|
||||||
|
Adriaan (adriaan@albourne.com)
|
74
contrib/bit/postgres.h
Normal file
74
contrib/bit/postgres.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#ifndef POSTGRES_H
|
||||||
|
#define POSTGRES_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef char bool;
|
||||||
|
typedef signed char int8;
|
||||||
|
typedef signed short int16;
|
||||||
|
typedef signed int int32;
|
||||||
|
|
||||||
|
/*#define NULL ((void *) 0)*/
|
||||||
|
#define Min(x, y) ((x) < (y) ? (x) : (y))
|
||||||
|
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
#define PointerIsValid(pointer) (bool)((void*)(pointer) != NULL)
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned int Oid;
|
||||||
|
typedef int16 int2;
|
||||||
|
typedef int32 int4;
|
||||||
|
typedef float float4;
|
||||||
|
typedef double float8;
|
||||||
|
typedef unsigned char uint8; /* == 8 bits */
|
||||||
|
typedef unsigned short uint16; /* == 16 bits */
|
||||||
|
typedef unsigned int uint32; /* == 32 bits */
|
||||||
|
typedef uint8 bits8; /* >= 8 bits */
|
||||||
|
typedef uint16 bits16; /* >= 16 bits */
|
||||||
|
typedef uint32 bits32; /* >= 32 bits */
|
||||||
|
|
||||||
|
|
||||||
|
typedef int4 aclitem;
|
||||||
|
|
||||||
|
#define InvalidOid 0
|
||||||
|
#define OidIsValid(objectId) ((bool) (objectId != InvalidOid))
|
||||||
|
|
||||||
|
/* unfortunately, both regproc and RegProcedure are used */
|
||||||
|
typedef Oid regproc;
|
||||||
|
typedef Oid RegProcedure;
|
||||||
|
|
||||||
|
typedef char *((*func_ptr) ());
|
||||||
|
|
||||||
|
|
||||||
|
#define RegProcedureIsValid(p) OidIsValid(p)
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------
|
||||||
|
* Section 2: variable length and array types
|
||||||
|
* ----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/* ----------------
|
||||||
|
* struct varlena
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
struct varlena
|
||||||
|
{
|
||||||
|
int32 vl_len;
|
||||||
|
char vl_dat[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VARSIZE(PTR) (((struct varlena *)(PTR))->vl_len)
|
||||||
|
#define VARDATA(PTR) (((struct varlena *)(PTR))->vl_dat)
|
||||||
|
#define VARHDRSZ sizeof(int32)
|
||||||
|
|
||||||
|
typedef struct varlena bytea;
|
||||||
|
typedef struct varlena text;
|
||||||
|
|
||||||
|
typedef int2 int28[8];
|
||||||
|
typedef Oid oid8[8];
|
||||||
|
|
||||||
|
#define ERROR stderr
|
||||||
|
#define elog fprintf
|
||||||
|
|
||||||
|
#define MaxAttrSize 10000
|
||||||
|
|
||||||
|
#define palloc malloc
|
||||||
|
#endif
|
832
contrib/bit/varbit.c
Normal file
832
contrib/bit/varbit.c
Normal file
@ -0,0 +1,832 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
48
contrib/bit/varbit.h
Normal file
48
contrib/bit/varbit.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "postgres.h"
|
||||||
|
|
||||||
|
typedef bits8 *VarBit;
|
||||||
|
typedef uint32 BitIndex;
|
||||||
|
|
||||||
|
#define HEXDIG(z) (z)<10 ? ((z)+'0') : ((z)-10+'A')
|
||||||
|
|
||||||
|
|
||||||
|
#define BITSPERBYTE 8
|
||||||
|
#define VARBITHDRSZ sizeof(int32)
|
||||||
|
/* Number of bits in this bit string */
|
||||||
|
#define VARBITLEN(PTR) (((struct varlena *)VARDATA(PTR))->vl_len)
|
||||||
|
/* Pointer tp the first byte containing bit string data */
|
||||||
|
#define VARBITS(PTR) (((struct varlena *)VARDATA(PTR))->vl_dat)
|
||||||
|
/* Number of bytes in the data section of a bit string */
|
||||||
|
#define VARBITBYTES(PTR) (VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ)
|
||||||
|
/* Padding of the bit string at the end */
|
||||||
|
#define VARBITPAD(PTR) (VARBITBYTES(PTR)*BITSPERBYTE - VARBITLEN(PTR))
|
||||||
|
/* Number of bytes needed to store a bit string of a given length */
|
||||||
|
#define VARBITDATALEN(BITLEN) (BITLEN/BITSPERBYTE + \
|
||||||
|
(BITLEN%BITSPERBYTE > 0 ? 1 : 0) + \
|
||||||
|
VARHDRSZ + VARBITHDRSZ)
|
||||||
|
/* pointer beyond the end of the bit string (like end() in STL containers) */
|
||||||
|
#define VARBITEND(PTR) ((bits8 *) (PTR + VARSIZE(PTR)))
|
||||||
|
/* Mask that will cover exactly one byte, i.e. BITSPERBYTE bits */
|
||||||
|
#define BITMASK 0xFF
|
||||||
|
#define BITHIGH 0x80
|
||||||
|
|
||||||
|
|
||||||
|
char * zpbitin(char *s, int dummy, int32 atttypmod);
|
||||||
|
char * zpbitout(char *s);
|
||||||
|
char * zpbitsout(char *s);
|
||||||
|
char * varbitin(char *s, int dummy, int32 atttypmod);
|
||||||
|
bool biteq (char *arg1, char *arg2);
|
||||||
|
bool bitne (char *arg1, char *arg2);
|
||||||
|
bool bitge (char *arg1, char *arg2);
|
||||||
|
bool bitgt (char *arg1, char *arg2);
|
||||||
|
bool bitle (char *arg1, char *arg2);
|
||||||
|
bool bitlt (char *arg1, char *arg2);
|
||||||
|
int bitcmp (char *arg1, char *arg2);
|
||||||
|
char * bitand (char * arg1, char * arg2);
|
||||||
|
char * bitor (char * arg1, char * arg2);
|
||||||
|
char * bitxor (char * arg1, char * arg2);
|
||||||
|
char * bitnot (char * arg);
|
||||||
|
char * bitshiftright (char * arg, int shft);
|
||||||
|
char * bitshiftleft (char * arg, int shft);
|
||||||
|
char * bitcat (char *arg1, char *arg2);
|
||||||
|
char * bitsubstr (char *arg, int32 s, int32 l);
|
172
contrib/bit/vartest.c
Normal file
172
contrib/bit/vartest.c
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#include "postgres.h"
|
||||||
|
#include "varbit.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
const int numb = 8;
|
||||||
|
/*
|
||||||
|
const char *b[] = { "B0010", "B11011011", "B0001", "X3F12", "X27", "B",
|
||||||
|
"X11", "B100111"};
|
||||||
|
int atttypmod[] = {-1, -1, -1,-1,-1,-1,-1,-1 };
|
||||||
|
*/
|
||||||
|
const char *b[] = { "B0010", "B11011011", "B10001", "X3D12", "X27", "B",
|
||||||
|
"X11", "B100111"};
|
||||||
|
int atttypmod[] = { 7, 9, 6, 18, 11, 6, -1, -1 };
|
||||||
|
|
||||||
|
|
||||||
|
void print_details (unsigned char *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
printf ("Length in bytes : %d\n",VARSIZE(s));
|
||||||
|
printf ("Length of bitstring: %d\n",VARBITLEN(s));
|
||||||
|
for (i=8; i<VARSIZE(s); i++)
|
||||||
|
printf ("%X%X ",s[i]>>4,s[i]&0xF);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char *s[numb];
|
||||||
|
|
||||||
|
for (i=0; i<numb; i++) {
|
||||||
|
printf ("Input: %s\n",b[i]);
|
||||||
|
s[i] = zpbitin(b[i], 0, atttypmod[i]);
|
||||||
|
//print_details(s[i]);
|
||||||
|
printf ("%s = %s\n",zpbitout(s[i]),zpbitsout(s[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\nCOMPARISONS:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s <=> %s = %d\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
bitcmp(s[i],s[j]));
|
||||||
|
|
||||||
|
printf ("\nCONCATENATION:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s || %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitcat(s[i],s[j])));
|
||||||
|
|
||||||
|
printf("\nSUBSTR:\n");
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,8,
|
||||||
|
zpbitsout(bitsubstr(s[3],1,8)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),9,8,
|
||||||
|
zpbitsout(bitsubstr(s[3],9,8)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,9,
|
||||||
|
zpbitsout(bitsubstr(s[3],1,9)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,5,
|
||||||
|
zpbitsout(bitsubstr(s[3],3,5)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,9,
|
||||||
|
zpbitsout(bitsubstr(s[3],3,9)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,17,
|
||||||
|
zpbitsout(bitsubstr(s[3],3,17)));
|
||||||
|
printf ("\nLOGICAL AND:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s & %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitand(s[i],s[j])));
|
||||||
|
|
||||||
|
printf ("\nLOGICAL OR:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s | %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitor(s[i],s[j])));
|
||||||
|
|
||||||
|
printf ("\nLOGICAL XOR:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s ^ %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitxor(s[i],s[j])));
|
||||||
|
|
||||||
|
printf ("\nLOGICAL NOT:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
printf("~%s = %s\n",zpbitsout(s[i]),zpbitsout(bitnot(s[i])));
|
||||||
|
|
||||||
|
|
||||||
|
printf ("\nSHIFT LEFT:\n");
|
||||||
|
for (i=0; i<numb; i++) {
|
||||||
|
printf("%s\n",zpbitsout(s[i]));
|
||||||
|
for (j=0; j<=VARBITLEN(s[i]); j++)
|
||||||
|
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftleft(s[i],j)));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\nSHIFT RIGHT:\n");
|
||||||
|
for (i=0; i<numb; i++) {
|
||||||
|
printf("%s\n",zpbitsout(s[i]));
|
||||||
|
for (j=0; j<=VARBITLEN(s[i]); j++)
|
||||||
|
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftright(s[i],j)));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\n\n ********** VARYING **********\n");
|
||||||
|
for (i=0; i<numb; i++) {
|
||||||
|
printf ("Input: %s\n",b[i]);
|
||||||
|
s[i] = varbitin(b[i], 0, atttypmod[i]);
|
||||||
|
/*print_details(s);*/
|
||||||
|
printf ("%s\n",zpbitout(s[i]));
|
||||||
|
printf ("%s\n",zpbitsout(s[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\nCOMPARISONS:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s <=> %s = %d\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
bitcmp(s[i],s[j]));
|
||||||
|
|
||||||
|
printf ("\nCONCATENATION:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s || %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitcat(s[i],s[j])));
|
||||||
|
|
||||||
|
printf("\nSUBSTR:\n");
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,8,
|
||||||
|
zpbitsout(bitsubstr(s[3],1,8)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),9,8,
|
||||||
|
zpbitsout(bitsubstr(s[3],9,8)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,9,
|
||||||
|
zpbitsout(bitsubstr(s[3],1,9)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,5,
|
||||||
|
zpbitsout(bitsubstr(s[3],3,5)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,9,
|
||||||
|
zpbitsout(bitsubstr(s[3],3,9)));
|
||||||
|
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,17,
|
||||||
|
zpbitsout(bitsubstr(s[3],3,17)));
|
||||||
|
printf ("\nLOGICAL AND:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s & %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitand(s[i],s[j])));
|
||||||
|
|
||||||
|
printf ("\nLOGICAL OR:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s | %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitor(s[i],s[j])));
|
||||||
|
|
||||||
|
printf ("\nLOGICAL XOR:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
for (j=i+1; j<numb; j++)
|
||||||
|
printf("%s ^ %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]),
|
||||||
|
zpbitsout(bitxor(s[i],s[j])));
|
||||||
|
|
||||||
|
printf ("\nLOGICAL NOT:\n");
|
||||||
|
for (i=0; i<numb; i++)
|
||||||
|
printf("~%s = %s\n",zpbitsout(s[i]),zpbitsout(bitnot(s[i])));
|
||||||
|
|
||||||
|
|
||||||
|
printf ("\nSHIFT LEFT:\n");
|
||||||
|
for (i=0; i<numb; i++) {
|
||||||
|
printf("%s\n",zpbitsout(s[i]));
|
||||||
|
for (j=0; j<=VARBITLEN(s[i]); j++)
|
||||||
|
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftleft(s[i],j)));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\nSHIFT RIGHT:\n");
|
||||||
|
for (i=0; i<numb; i++) {
|
||||||
|
printf("%s\n",zpbitsout(s[i]));
|
||||||
|
for (j=0; j<=VARBITLEN(s[i]); j++)
|
||||||
|
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftright(s[i],j)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user