Commit 1f747c67 authored by Bruce Momjian's avatar Bruce Momjian

Attached are the C-routines that implement a BIT and BIT VARYING type.

Adriaan Joubert
parent 47e51683
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
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)
#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
This diff is collapsed.
#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);
#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)));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment