Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions

varbit.c File Reference

#include "postgres.h"
#include "access/htup_details.h"
#include "libpq/pqformat.h"
#include "nodes/nodeFuncs.h"
#include "utils/array.h"
#include "utils/varbit.h"
Include dependency graph for varbit.c:

Go to the source code of this file.

Defines

#define HEXDIG(z)   ((z)<10 ? ((z)+'0') : ((z)-10+'A'))

Functions

static VarBitbit_catenate (VarBit *arg1, VarBit *arg2)
static VarBitbitsubstring (VarBit *arg, int32 s, int32 l, bool length_not_specified)
static VarBitbit_overlay (VarBit *t1, VarBit *t2, int sp, int sl)
static int32 anybit_typmodin (ArrayType *ta, const char *typename)
static char * anybit_typmodout (int32 typmod)
Datum bit_in (PG_FUNCTION_ARGS)
Datum bit_out (PG_FUNCTION_ARGS)
Datum bit_recv (PG_FUNCTION_ARGS)
Datum bit_send (PG_FUNCTION_ARGS)
Datum bit (PG_FUNCTION_ARGS)
Datum bittypmodin (PG_FUNCTION_ARGS)
Datum bittypmodout (PG_FUNCTION_ARGS)
Datum varbit_in (PG_FUNCTION_ARGS)
Datum varbit_out (PG_FUNCTION_ARGS)
Datum varbit_recv (PG_FUNCTION_ARGS)
Datum varbit_send (PG_FUNCTION_ARGS)
Datum varbit_transform (PG_FUNCTION_ARGS)
Datum varbit (PG_FUNCTION_ARGS)
Datum varbittypmodin (PG_FUNCTION_ARGS)
Datum varbittypmodout (PG_FUNCTION_ARGS)
static int32 bit_cmp (VarBit *arg1, VarBit *arg2)
Datum biteq (PG_FUNCTION_ARGS)
Datum bitne (PG_FUNCTION_ARGS)
Datum bitlt (PG_FUNCTION_ARGS)
Datum bitle (PG_FUNCTION_ARGS)
Datum bitgt (PG_FUNCTION_ARGS)
Datum bitge (PG_FUNCTION_ARGS)
Datum bitcmp (PG_FUNCTION_ARGS)
Datum bitcat (PG_FUNCTION_ARGS)
Datum bitsubstr (PG_FUNCTION_ARGS)
Datum bitsubstr_no_len (PG_FUNCTION_ARGS)
Datum bitoverlay (PG_FUNCTION_ARGS)
Datum bitoverlay_no_len (PG_FUNCTION_ARGS)
Datum bitlength (PG_FUNCTION_ARGS)
Datum bitoctetlength (PG_FUNCTION_ARGS)
Datum bit_and (PG_FUNCTION_ARGS)
Datum bit_or (PG_FUNCTION_ARGS)
Datum bitxor (PG_FUNCTION_ARGS)
Datum bitnot (PG_FUNCTION_ARGS)
Datum bitshiftleft (PG_FUNCTION_ARGS)
Datum bitshiftright (PG_FUNCTION_ARGS)
Datum bitfromint4 (PG_FUNCTION_ARGS)
Datum bittoint4 (PG_FUNCTION_ARGS)
Datum bitfromint8 (PG_FUNCTION_ARGS)
Datum bittoint8 (PG_FUNCTION_ARGS)
Datum bitposition (PG_FUNCTION_ARGS)
Datum bitsetbit (PG_FUNCTION_ARGS)
Datum bitgetbit (PG_FUNCTION_ARGS)

Define Documentation

#define HEXDIG (   z  )     ((z)<10 ? ((z)+'0') : ((z)-10+'A'))

Definition at line 25 of file varbit.c.

Referenced by bit_out().


Function Documentation

static int32 anybit_typmodin ( ArrayType ta,
const char *  typename 
) [static]

Definition at line 37 of file varbit.c.

References ArrayGetIntegerTypmods(), BITS_PER_BYTE, ereport, errcode(), errmsg(), ERROR, and MaxAttrSize.

Referenced by bittypmodin(), and varbittypmodin().

{
    int32       typmod;
    int32      *tl;
    int         n;

    tl = ArrayGetIntegerTypmods(ta, &n);

    /*
     * we're not too tense about good error message here because grammar
     * shouldn't allow wrong number of modifiers for BIT
     */
    if (n != 1)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("invalid type modifier")));

    if (*tl < 1)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("length for type %s must be at least 1",
                        typename)));
    if (*tl > (MaxAttrSize * BITS_PER_BYTE))
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("length for type %s cannot exceed %d",
                        typename, MaxAttrSize * BITS_PER_BYTE)));

    typmod = *tl;

    return typmod;
}

static char* anybit_typmodout ( int32  typmod  )  [static]

Definition at line 74 of file varbit.c.

References palloc(), and snprintf().

Referenced by bittypmodout(), and varbittypmodout().

{
    char       *res = (char *) palloc(64);

    if (typmod >= 0)
        snprintf(res, 64, "(%d)", typmod);
    else
        *res = '\0';

    return res;
}

Datum bit ( PG_FUNCTION_ARGS   ) 

Definition at line 350 of file varbit.c.

References arg, BITMASK, ereport, errcode(), errmsg(), ERROR, Min, palloc0(), PG_GETARG_BOOL, PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITPAD, VARBITS, and VARBITTOTALLEN.

{
    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);
    SET_VARSIZE(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);
}

Datum bit_and ( PG_FUNCTION_ARGS   ) 

Definition at line 1180 of file varbit.c.

References ereport, errcode(), errmsg(), ERROR, i, palloc(), PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITS, and VARSIZE.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    VarBit     *result;
    int         len,
                bitlen1,
                bitlen2,
                i;
    bits8      *p1,
               *p2,
               *r;

    bitlen1 = VARBITLEN(arg1);
    bitlen2 = VARBITLEN(arg2);
    if (bitlen1 != bitlen2)
        ereport(ERROR,
                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
                 errmsg("cannot AND bit strings of different sizes")));

    len = VARSIZE(arg1);
    result = (VarBit *) palloc(len);
    SET_VARSIZE(result, len);
    VARBITLEN(result) = bitlen1;

    p1 = VARBITS(arg1);
    p2 = VARBITS(arg2);
    r = VARBITS(result);
    for (i = 0; i < VARBITBYTES(arg1); i++)
        *r++ = *p1++ & *p2++;

    /* Padding is not needed as & of 0 pad is 0 */

    PG_RETURN_VARBIT_P(result);
}

static VarBit * bit_catenate ( VarBit arg1,
VarBit arg2 
) [static]

Definition at line 933 of file varbit.c.

References BITMASK, BITS_PER_BYTE, palloc(), SET_VARSIZE, VARBITBYTES, VARBITEND, VARBITLEN, VARBITPAD, VARBITS, and VARBITTOTALLEN.

Referenced by bit_overlay(), and bitcat().

{
    VarBit     *result;
    int         bitlen1,
                bitlen2,
                bytelen,
                bit1pad,
                bit2shift;
    bits8      *pr,
               *pa;

    bitlen1 = VARBITLEN(arg1);
    bitlen2 = VARBITLEN(arg2);

    bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);

    result = (VarBit *) palloc(bytelen);
    SET_VARSIZE(result, bytelen);
    VARBITLEN(result) = bitlen1 + bitlen2;

    /* 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 bits to fit */
        bit2shift = BITS_PER_BYTE - bit1pad;
        pr = VARBITS(result) + VARBITBYTES(arg1) - 1;
        for (pa = VARBITS(arg2); pa < VARBITEND(arg2); pa++)
        {
            *pr |= ((*pa >> bit2shift) & BITMASK);
            pr++;
            if (pr < VARBITEND(result))
                *pr = (*pa << bit1pad) & BITMASK;
        }
    }

    return result;
}

static int32 bit_cmp ( VarBit arg1,
VarBit arg2 
) [static]

Definition at line 774 of file varbit.c.

References memcmp(), Min, VARBITBYTES, VARBITLEN, and VARBITS.

Referenced by bitcmp(), biteq(), bitge(), bitgt(), bitle(), bitlt(), and bitne().

{
    int         bitlen1,
                bytelen1,
                bitlen2,
                bytelen2;
    int32       cmp;

    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)
            cmp = (bitlen1 < bitlen2) ? -1 : 1;
    }
    return cmp;
}

Datum bit_in ( PG_FUNCTION_ARGS   ) 

Definition at line 112 of file varbit.c.

References ereport, errcode(), errmsg(), ERROR, palloc0(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITLEN, VARBITS, and VARBITTOTALLEN.

Referenced by leftmostvalue_bit(), and make_const().

{
    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);
    SET_VARSIZE(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 = HIGHBIT;
        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 = HIGHBIT;
                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);
}

Datum bit_or ( PG_FUNCTION_ARGS   ) 

Definition at line 1221 of file varbit.c.

References BITMASK, ereport, errcode(), errmsg(), ERROR, i, palloc(), PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITPAD, VARBITS, and VARSIZE.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    VarBit     *result;
    int         len,
                bitlen1,
                bitlen2,
                i;
    bits8      *p1,
               *p2,
               *r;
    bits8       mask;

    bitlen1 = VARBITLEN(arg1);
    bitlen2 = VARBITLEN(arg2);
    if (bitlen1 != bitlen2)
        ereport(ERROR,
                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
                 errmsg("cannot OR bit strings of different sizes")));
    len = VARSIZE(arg1);
    result = (VarBit *) palloc(len);
    SET_VARSIZE(result, len);
    VARBITLEN(result) = bitlen1;

    p1 = VARBITS(arg1);
    p2 = VARBITS(arg2);
    r = VARBITS(result);
    for (i = 0; i < VARBITBYTES(arg1); i++)
        *r++ = *p1++ | *p2++;

    /* Pad the result */
    mask = BITMASK << VARBITPAD(result);
    if (mask)
    {
        r--;
        *r &= mask;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum bit_out ( PG_FUNCTION_ARGS   ) 

Definition at line 235 of file varbit.c.

References HEXDIG, i, palloc(), PG_GETARG_VARBIT_P, PG_RETURN_CSTRING, varbit_out(), VARBITLEN, and VARBITS.

{
#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
}

static VarBit * bit_overlay ( VarBit t1,
VarBit t2,
int  sp,
int  sl 
) [static]

Definition at line 1125 of file varbit.c.

References bit_catenate(), bitsubstring(), ereport, errcode(), errmsg(), ERROR, s1, and s2.

Referenced by bitoverlay(), and bitoverlay_no_len().

{
    VarBit     *result;
    VarBit     *s1;
    VarBit     *s2;
    int         sp_pl_sl;

    /*
     * Check for possible integer-overflow cases.  For negative sp, throw a
     * "substring length" error because that's what should be expected
     * according to the spec's definition of OVERLAY().
     */
    if (sp <= 0)
        ereport(ERROR,
                (errcode(ERRCODE_SUBSTRING_ERROR),
                 errmsg("negative substring length not allowed")));
    sp_pl_sl = sp + sl;
    if (sp_pl_sl <= sl)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("integer out of range")));

    s1 = bitsubstring(t1, 1, sp - 1, false);
    s2 = bitsubstring(t1, sp_pl_sl, -1, true);
    result = bit_catenate(s1, t2);
    result = bit_catenate(result, s2);

    return result;
}

Datum bit_recv ( PG_FUNCTION_ARGS   ) 

Definition at line 283 of file varbit.c.

References BITMASK, buf, ereport, errcode(), errmsg(), ERROR, palloc(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_VARBIT_P, pq_copymsgbytes(), pq_getmsgint(), SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITPAD, VARBITS, and VARBITTOTALLEN.

{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       atttypmod = PG_GETARG_INT32(2);
    VarBit     *result;
    int         len,
                bitlen;
    int         ipad;
    bits8       mask;

    bitlen = pq_getmsgint(buf, sizeof(int32));
    if (bitlen < 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                 errmsg("invalid length in external bit string")));

    /*
     * Sometimes atttypmod is not supplied. If it is supplied we need to make
     * sure that the bitstring fits.
     */
    if (atttypmod > 0 && 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(bitlen);
    result = (VarBit *) palloc(len);
    SET_VARSIZE(result, len);
    VARBITLEN(result) = bitlen;

    pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));

    /* Make sure last byte is zero-padded if needed */
    ipad = VARBITPAD(result);
    if (ipad > 0)
    {
        mask = BITMASK << ipad;
        *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum bit_send ( PG_FUNCTION_ARGS   ) 

Definition at line 335 of file varbit.c.

References varbit_send().

{
    /* Exactly the same as varbit_send, so share code */
    return varbit_send(fcinfo);
}

Datum bitcat ( PG_FUNCTION_ARGS   ) 

Definition at line 924 of file varbit.c.

References bit_catenate(), PG_GETARG_VARBIT_P, and PG_RETURN_VARBIT_P.

Datum bitcmp ( PG_FUNCTION_ARGS   ) 

Definition at line 905 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, and PG_RETURN_INT32.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    int32       result;

    result = bit_cmp(arg1, arg2);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_INT32(result);
}

Datum biteq ( PG_FUNCTION_ARGS   ) 

Definition at line 797 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, PG_RETURN_BOOL, and VARBITLEN.

Referenced by gbt_biteq().

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    bool        result;
    int         bitlen1,
                bitlen2;

    bitlen1 = VARBITLEN(arg1);
    bitlen2 = VARBITLEN(arg2);

    /* fast path for different-length inputs */
    if (bitlen1 != bitlen2)
        result = false;
    else
        result = (bit_cmp(arg1, arg2) == 0);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_BOOL(result);
}

Datum bitfromint4 ( PG_FUNCTION_ARGS   ) 

Definition at line 1472 of file varbit.c.

References BITMASK, Min, palloc(), PG_GETARG_INT32, PG_RETURN_VARBIT_P, SET_VARSIZE, val, VARBITLEN, VARBITS, and VARBITTOTALLEN.

{
    int32       a = PG_GETARG_INT32(0);
    int32       typmod = PG_GETARG_INT32(1);
    VarBit     *result;
    bits8      *r;
    int         rlen;
    int         destbitsleft,
                srcbitsleft;

    if (typmod <= 0)
        typmod = 1;             /* default bit length */

    rlen = VARBITTOTALLEN(typmod);
    result = (VarBit *) palloc(rlen);
    SET_VARSIZE(result, rlen);
    VARBITLEN(result) = typmod;

    r = VARBITS(result);
    destbitsleft = typmod;
    srcbitsleft = 32;
    /* drop any input bits that don't fit */
    srcbitsleft = Min(srcbitsleft, destbitsleft);
    /* sign-fill any excess bytes in output */
    while (destbitsleft >= srcbitsleft + 8)
    {
        *r++ = (bits8) ((a < 0) ? BITMASK : 0);
        destbitsleft -= 8;
    }
    /* store first fractional byte */
    if (destbitsleft > srcbitsleft)
    {
        int         val = (int) (a >> (destbitsleft - 8));

        /* Force sign-fill in case the compiler implements >> as zero-fill */
        if (a < 0)
            val |= (-1) << (srcbitsleft + 8 - destbitsleft);
        *r++ = (bits8) (val & BITMASK);
        destbitsleft -= 8;
    }
    /* Now srcbitsleft and destbitsleft are the same, need not track both */
    /* store whole bytes */
    while (destbitsleft >= 8)
    {
        *r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
        destbitsleft -= 8;
    }
    /* store last fractional byte */
    if (destbitsleft > 0)
        *r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);

    PG_RETURN_VARBIT_P(result);
}

Datum bitfromint8 ( PG_FUNCTION_ARGS   ) 

Definition at line 1552 of file varbit.c.

References BITMASK, Min, palloc(), PG_GETARG_INT32, PG_GETARG_INT64, PG_RETURN_VARBIT_P, SET_VARSIZE, val, VARBITLEN, VARBITS, and VARBITTOTALLEN.

{
    int64       a = PG_GETARG_INT64(0);
    int32       typmod = PG_GETARG_INT32(1);
    VarBit     *result;
    bits8      *r;
    int         rlen;
    int         destbitsleft,
                srcbitsleft;

    if (typmod <= 0)
        typmod = 1;             /* default bit length */

    rlen = VARBITTOTALLEN(typmod);
    result = (VarBit *) palloc(rlen);
    SET_VARSIZE(result, rlen);
    VARBITLEN(result) = typmod;

    r = VARBITS(result);
    destbitsleft = typmod;
    srcbitsleft = 64;
    /* drop any input bits that don't fit */
    srcbitsleft = Min(srcbitsleft, destbitsleft);
    /* sign-fill any excess bytes in output */
    while (destbitsleft >= srcbitsleft + 8)
    {
        *r++ = (bits8) ((a < 0) ? BITMASK : 0);
        destbitsleft -= 8;
    }
    /* store first fractional byte */
    if (destbitsleft > srcbitsleft)
    {
        int         val = (int) (a >> (destbitsleft - 8));

        /* Force sign-fill in case the compiler implements >> as zero-fill */
        if (a < 0)
            val |= (-1) << (srcbitsleft + 8 - destbitsleft);
        *r++ = (bits8) (val & BITMASK);
        destbitsleft -= 8;
    }
    /* Now srcbitsleft and destbitsleft are the same, need not track both */
    /* store whole bytes */
    while (destbitsleft >= 8)
    {
        *r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
        destbitsleft -= 8;
    }
    /* store last fractional byte */
    if (destbitsleft > 0)
        *r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);

    PG_RETURN_VARBIT_P(result);
}

Datum bitge ( PG_FUNCTION_ARGS   ) 

Definition at line 890 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, and PG_RETURN_BOOL.

Referenced by gbt_bitge().

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    bool        result;

    result = (bit_cmp(arg1, arg2) >= 0);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_BOOL(result);
}

Datum bitgetbit ( PG_FUNCTION_ARGS   ) 

Definition at line 1810 of file varbit.c.

References BITS_PER_BYTE, ereport, errcode(), errmsg(), ERROR, PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_INT32, VARBITLEN, and VARBITS.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    int32       n = PG_GETARG_INT32(1);
    int         bitlen;
    bits8      *p;
    int         byteNo,
                bitNo;

    bitlen = VARBITLEN(arg1);
    if (n < 0 || n >= bitlen)
        ereport(ERROR,
                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                 errmsg("bit index %d out of valid range (0..%d)",
                        n, bitlen - 1)));

    p = VARBITS(arg1);

    byteNo = n / BITS_PER_BYTE;
    bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE);

    if (p[byteNo] & (1 << bitNo))
        PG_RETURN_INT32(1);
    else
        PG_RETURN_INT32(0);
}

Datum bitgt ( PG_FUNCTION_ARGS   ) 

Definition at line 875 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, and PG_RETURN_BOOL.

Referenced by gbt_bitgt().

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    bool        result;

    result = (bit_cmp(arg1, arg2) > 0);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_BOOL(result);
}

Datum bitle ( PG_FUNCTION_ARGS   ) 

Definition at line 860 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, and PG_RETURN_BOOL.

Referenced by gbt_bitle().

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    bool        result;

    result = (bit_cmp(arg1, arg2) <= 0);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_BOOL(result);
}

Datum bitlength ( PG_FUNCTION_ARGS   ) 

Definition at line 1160 of file varbit.c.

References arg, PG_GETARG_VARBIT_P, PG_RETURN_INT32, and VARBITLEN.

Datum bitlt ( PG_FUNCTION_ARGS   ) 

Definition at line 845 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, and PG_RETURN_BOOL.

Referenced by gbt_bitlt().

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    bool        result;

    result = (bit_cmp(arg1, arg2) < 0);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_BOOL(result);
}

Datum bitne ( PG_FUNCTION_ARGS   ) 

Definition at line 821 of file varbit.c.

References bit_cmp(), PG_FREE_IF_COPY, PG_GETARG_VARBIT_P, PG_RETURN_BOOL, and VARBITLEN.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    bool        result;
    int         bitlen1,
                bitlen2;

    bitlen1 = VARBITLEN(arg1);
    bitlen2 = VARBITLEN(arg2);

    /* fast path for different-length inputs */
    if (bitlen1 != bitlen2)
        result = true;
    else
        result = (bit_cmp(arg1, arg2) != 0);

    PG_FREE_IF_COPY(arg1, 0);
    PG_FREE_IF_COPY(arg2, 1);

    PG_RETURN_BOOL(result);
}

Datum bitnot ( PG_FUNCTION_ARGS   ) 

Definition at line 1316 of file varbit.c.

References arg, BITMASK, palloc(), PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITEND, VARBITLEN, VARBITPAD, VARBITS, and VARSIZE.

{
    VarBit     *arg = PG_GETARG_VARBIT_P(0);
    VarBit     *result;
    bits8      *p,
               *r;
    bits8       mask;

    result = (VarBit *) palloc(VARSIZE(arg));
    SET_VARSIZE(result, VARSIZE(arg));
    VARBITLEN(result) = VARBITLEN(arg);

    p = VARBITS(arg);
    r = VARBITS(result);
    for (; p < VARBITEND(arg); p++)
        *r++ = ~*p;

    /* Pad the result */
    mask = BITMASK << VARBITPAD(result);
    if (mask)
    {
        r--;
        *r &= mask;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum bitoctetlength ( PG_FUNCTION_ARGS   ) 

Definition at line 1168 of file varbit.c.

References arg, PG_GETARG_VARBIT_P, PG_RETURN_INT32, and VARBITBYTES.

Datum bitoverlay ( PG_FUNCTION_ARGS   ) 

Definition at line 1102 of file varbit.c.

References bit_overlay(), PG_GETARG_INT32, PG_GETARG_VARBIT_P, and PG_RETURN_VARBIT_P.

{
    VarBit     *t1 = PG_GETARG_VARBIT_P(0);
    VarBit     *t2 = PG_GETARG_VARBIT_P(1);
    int         sp = PG_GETARG_INT32(2);        /* substring start position */
    int         sl = PG_GETARG_INT32(3);        /* substring length */

    PG_RETURN_VARBIT_P(bit_overlay(t1, t2, sp, sl));
}

Datum bitoverlay_no_len ( PG_FUNCTION_ARGS   ) 

Definition at line 1113 of file varbit.c.

References bit_overlay(), PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, and VARBITLEN.

{
    VarBit     *t1 = PG_GETARG_VARBIT_P(0);
    VarBit     *t2 = PG_GETARG_VARBIT_P(1);
    int         sp = PG_GETARG_INT32(2);        /* substring start position */
    int         sl;

    sl = VARBITLEN(t2);         /* defaults to length(t2) */
    PG_RETURN_VARBIT_P(bit_overlay(t1, t2, sp, sl));
}

Datum bitposition ( PG_FUNCTION_ARGS   ) 

Definition at line 1639 of file varbit.c.

References BITMASK, DEBUG4, elog, i, PG_GETARG_VARBIT_P, PG_RETURN_INT32, VARBITBYTES, VARBITEND, VARBITLEN, VARBITPAD, and VARBITS.

{
    VarBit     *str = PG_GETARG_VARBIT_P(0);
    VarBit     *substr = PG_GETARG_VARBIT_P(1);
    int         substr_length,
                str_length,
                i,
                is;
    bits8      *s,              /* pointer into substring */
               *p;              /* pointer into str */
    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 */
                str_mask;       /* pad mask for last string byte */
    bool        is_match;

    /* Get the substring length */
    substr_length = VARBITLEN(substr);
    str_length = VARBITLEN(str);

    /* String has zero length or substring longer than string, return 0 */
    if ((str_length == 0) || (substr_length > str_length))
        PG_RETURN_INT32(0);

    /* zero-length substring means return 1 */
    if (substr_length == 0)
        PG_RETURN_INT32(1);

    /* Initialise the padding masks */
    end_mask = BITMASK << VARBITPAD(substr);
    str_mask = BITMASK << VARBITPAD(str);
    for (i = 0; i < VARBITBYTES(str) - VARBITBYTES(substr) + 1; i++)
    {
        for (is = 0; is < BITS_PER_BYTE; is++)
        {
            is_match = true;
            p = VARBITS(str) + 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(str) - 1)
                    {
                        /* Check that there is enough of str left */
                        if (mask1 & ~str_mask)
                        {
                            is_match = false;
                            break;
                        }
                        mask1 &= str_mask;
                    }
                }
                is_match = ((cmp ^ *p) & mask1) == 0;
                if (!is_match)
                    break;
                /* Move on to the next byte */
                p++;
                if (p == VARBITEND(str))
                {
                    mask2 = end_mask << (BITS_PER_BYTE - is);
                    is_match = mask2 == 0;
#if 0
                    elog(DEBUG4, "S. %d %d em=%2x sm=%2x r=%d",
                         i, is, end_mask, mask2, is_match);
#endif
                    break;
                }
                cmp = *s << (BITS_PER_BYTE - is);
                if (s == VARBITEND(substr) - 1)
                {
                    mask2 &= end_mask << (BITS_PER_BYTE - is);
                    if (p == VARBITEND(str) - 1)
                    {
                        if (mask2 & ~str_mask)
                        {
                            is_match = false;
                            break;
                        }
                        mask2 &= str_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);
}

Datum bitsetbit ( PG_FUNCTION_ARGS   ) 

Definition at line 1748 of file varbit.c.

References BITS_PER_BYTE, ereport, errcode(), errmsg(), ERROR, palloc(), PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITS, and VARSIZE.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    int32       n = PG_GETARG_INT32(1);
    int32       newBit = PG_GETARG_INT32(2);
    VarBit     *result;
    int         len,
                bitlen;
    bits8      *r,
               *p;
    int         byteNo,
                bitNo;

    bitlen = VARBITLEN(arg1);
    if (n < 0 || n >= bitlen)
        ereport(ERROR,
                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                 errmsg("bit index %d out of valid range (0..%d)",
                        n, bitlen - 1)));

    /*
     * sanity check!
     */
    if (newBit != 0 && newBit != 1)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("new bit must be 0 or 1")));

    len = VARSIZE(arg1);
    result = (VarBit *) palloc(len);
    SET_VARSIZE(result, len);
    VARBITLEN(result) = bitlen;

    p = VARBITS(arg1);
    r = VARBITS(result);

    memcpy(r, p, VARBITBYTES(arg1));

    byteNo = n / BITS_PER_BYTE;
    bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE);

    /*
     * Update the byte.
     */
    if (newBit == 0)
        r[byteNo] &= (~(1 << bitNo));
    else
        r[byteNo] |= (1 << bitNo);

    PG_RETURN_VARBIT_P(result);
}

Datum bitshiftleft ( PG_FUNCTION_ARGS   ) 

Definition at line 1349 of file varbit.c.

References arg, BITS_PER_BYTE, bitshiftright(), DirectFunctionCall2, Int32GetDatum, MemSet, palloc(), PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_DATUM, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITEND, VARBITLEN, VarBitPGetDatum, VARBITS, and VARSIZE.

Referenced by bitshiftright().

{
    VarBit     *arg = PG_GETARG_VARBIT_P(0);
    int32       shft = PG_GETARG_INT32(1);
    VarBit     *result;
    int         byte_shift,
                ishift,
                len;
    bits8      *p,
               *r;

    /* Negative shift is a shift to the right */
    if (shft < 0)
        PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
                                            VarBitPGetDatum(arg),
                                            Int32GetDatum(-shft)));

    result = (VarBit *) palloc(VARSIZE(arg));
    SET_VARSIZE(result, VARSIZE(arg));
    VARBITLEN(result) = VARBITLEN(arg);
    r = VARBITS(result);

    /* If we shifted all the bits out, return an all-zero string */
    if (shft >= VARBITLEN(arg))
    {
        MemSet(r, 0, VARBITBYTES(arg));
        PG_RETURN_VARBIT_P(result);
    }

    byte_shift = shft / BITS_PER_BYTE;
    ishift = shft % BITS_PER_BYTE;
    p = 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 >> (BITS_PER_BYTE - ishift);
        }
        for (; r < VARBITEND(result); r++)
            *r = 0;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum bitshiftright ( PG_FUNCTION_ARGS   ) 

Definition at line 1409 of file varbit.c.

References arg, BITMASK, BITS_PER_BYTE, bitshiftleft(), DirectFunctionCall2, Int32GetDatum, MemSet, palloc(), PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_DATUM, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITEND, VARBITLEN, VarBitPGetDatum, VARBITS, and VARSIZE.

Referenced by bitshiftleft().

{
    VarBit     *arg = PG_GETARG_VARBIT_P(0);
    int32       shft = PG_GETARG_INT32(1);
    VarBit     *result;
    int         byte_shift,
                ishift,
                len;
    bits8      *p,
               *r;

    /* 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));
    SET_VARSIZE(result, VARSIZE(arg));
    VARBITLEN(result) = VARBITLEN(arg);
    r = VARBITS(result);

    /* If we shifted all the bits out, return an all-zero string */
    if (shft >= VARBITLEN(arg))
    {
        MemSet(r, 0, VARBITBYTES(arg));
        PG_RETURN_VARBIT_P(result);
    }

    byte_shift = shft / BITS_PER_BYTE;
    ishift = shft % BITS_PER_BYTE;
    p = VARBITS(arg);

    /* Set the first part of the result to 0 */
    MemSet(r, 0, byte_shift);
    r += byte_shift;

    if (ishift == 0)
    {
        /* Special case: we can do a memcpy */
        len = VARBITBYTES(arg) - byte_shift;
        memcpy(r, p, len);
    }
    else
    {
        if (r < VARBITEND(result))
            *r = 0;             /* initialize first byte */
        for (; r < VARBITEND(result); p++)
        {
            *r |= *p >> ishift;
            if ((++r) < VARBITEND(result))
                *r = (*p << (BITS_PER_BYTE - ishift)) & BITMASK;
        }
    }

    PG_RETURN_VARBIT_P(result);
}

Datum bitsubstr ( PG_FUNCTION_ARGS   ) 
Datum bitsubstr_no_len ( PG_FUNCTION_ARGS   ) 
static VarBit * bitsubstring ( VarBit arg,
int32  s,
int32  l,
bool  length_not_specified 
) [static]

Definition at line 1004 of file varbit.c.

References BITMASK, BITS_PER_BYTE, ereport, errcode(), errmsg(), ERROR, i, Max, Min, palloc(), s1, SET_VARSIZE, VARBITEND, VARBITLEN, VARBITPAD, VARBITS, VARBITTOTALLEN, and VARHDRSZ.

Referenced by bit_overlay(), bitsubstr(), and bitsubstr_no_len().

{
    VarBit     *result;
    int         bitlen,
                rbitlen,
                len,
                ipad = 0,
                ishift,
                i;
    int         e,
                s1,
                e1;
    bits8       mask,
               *r,
               *ps;

    bitlen = VARBITLEN(arg);
    s1 = Max(s, 1);
    /* If we do not have an upper bound, use end of string */
    if (length_not_specified)
    {
        e1 = bitlen + 1;
    }
    else
    {
        e = s + l;

        /*
         * A negative value for L is the only way for the end position to be
         * before the start. SQL99 says to throw an error.
         */
        if (e < s)
            ereport(ERROR,
                    (errcode(ERRCODE_SUBSTRING_ERROR),
                     errmsg("negative substring length not allowed")));
        e1 = Min(e, bitlen + 1);
    }
    if (s1 > bitlen || e1 <= s1)
    {
        /* Need to return a zero-length bitstring */
        len = VARBITTOTALLEN(0);
        result = (VarBit *) palloc(len);
        SET_VARSIZE(result, len);
        VARBITLEN(result) = 0;
    }
    else
    {
        /*
         * OK, we've got a true substring starting at position s1-1 and ending
         * at position e1-1
         */
        rbitlen = e1 - s1;
        len = VARBITTOTALLEN(rbitlen);
        result = (VarBit *) palloc(len);
        SET_VARSIZE(result, len);
        VARBITLEN(result) = rbitlen;
        len -= VARHDRSZ + VARBITHDRSZ;
        /* Are we copying from a byte boundary? */
        if ((s1 - 1) % BITS_PER_BYTE == 0)
        {
            /* Yep, we are copying bytes */
            memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE,
                   len);
        }
        else
        {
            /* Figure out how much we need to shift the sequence by */
            ishift = (s1 - 1) % BITS_PER_BYTE;
            r = VARBITS(result);
            ps = VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE;
            for (i = 0; i < len; i++)
            {
                *r = (*ps << ishift) & BITMASK;
                if ((++ps) < VARBITEND(arg))
                    *r |= *ps >> (BITS_PER_BYTE - 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;
}

Datum bittoint4 ( PG_FUNCTION_ARGS   ) 

Definition at line 1527 of file varbit.c.

References arg, BITS_PER_BYTE, ereport, errcode(), errmsg(), ERROR, PG_GETARG_VARBIT_P, PG_RETURN_INT32, VARBITEND, VARBITLEN, VARBITPAD, and VARBITS.

{
    VarBit     *arg = PG_GETARG_VARBIT_P(0);
    uint32      result;
    bits8      *r;

    /* Check that the bit string is not too long */
    if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("integer out of range")));

    result = 0;
    for (r = VARBITS(arg); r < VARBITEND(arg); r++)
    {
        result <<= BITS_PER_BYTE;
        result |= *r;
    }
    /* Now shift the result to take account of the padding at the end */
    result >>= VARBITPAD(arg);

    PG_RETURN_INT32(result);
}

Datum bittoint8 ( PG_FUNCTION_ARGS   ) 

Definition at line 1607 of file varbit.c.

References arg, BITS_PER_BYTE, ereport, errcode(), errmsg(), ERROR, PG_GETARG_VARBIT_P, PG_RETURN_INT64, VARBITEND, VARBITLEN, VARBITPAD, and VARBITS.

{
    VarBit     *arg = PG_GETARG_VARBIT_P(0);
    uint64      result;
    bits8      *r;

    /* Check that the bit string is not too long */
    if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
        ereport(ERROR,
                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                 errmsg("bigint out of range")));

    result = 0;
    for (r = VARBITS(arg); r < VARBITEND(arg); r++)
    {
        result <<= BITS_PER_BYTE;
        result |= *r;
    }
    /* Now shift the result to take account of the padding at the end */
    result >>= VARBITPAD(arg);

    PG_RETURN_INT64(result);
}

Datum bittypmodin ( PG_FUNCTION_ARGS   ) 

Definition at line 395 of file varbit.c.

References anybit_typmodin(), PG_GETARG_ARRAYTYPE_P, and PG_RETURN_INT32.

Datum bittypmodout ( PG_FUNCTION_ARGS   ) 

Definition at line 403 of file varbit.c.

References anybit_typmodout(), PG_GETARG_INT32, and PG_RETURN_CSTRING.

Datum bitxor ( PG_FUNCTION_ARGS   ) 

Definition at line 1268 of file varbit.c.

References BITMASK, ereport, errcode(), errmsg(), ERROR, i, palloc(), PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITPAD, VARBITS, and VARSIZE.

{
    VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
    VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
    VarBit     *result;
    int         len,
                bitlen1,
                bitlen2,
                i;
    bits8      *p1,
               *p2,
               *r;
    bits8       mask;

    bitlen1 = VARBITLEN(arg1);
    bitlen2 = VARBITLEN(arg2);
    if (bitlen1 != bitlen2)
        ereport(ERROR,
                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
                 errmsg("cannot XOR bit strings of different sizes")));

    len = VARSIZE(arg1);
    result = (VarBit *) palloc(len);
    SET_VARSIZE(result, len);
    VARBITLEN(result) = bitlen1;

    p1 = VARBITS(arg1);
    p2 = VARBITS(arg2);
    r = VARBITS(result);
    for (i = 0; i < VARBITBYTES(arg1); i++)
        *r++ = *p1++ ^ *p2++;

    /* Pad the result */
    mask = BITMASK << VARBITPAD(result);
    if (mask)
    {
        r--;
        *r &= mask;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum varbit ( PG_FUNCTION_ARGS   ) 

Definition at line 691 of file varbit.c.

References arg, BITMASK, ereport, errcode(), errmsg(), ERROR, palloc(), PG_GETARG_BOOL, PG_GETARG_INT32, PG_GETARG_VARBIT_P, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITPAD, VARBITS, and VARBITTOTALLEN.

{
    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_RIGHT_TRUNCATION),
                 errmsg("bit string too long for type bit varying(%d)",
                        len)));

    rlen = VARBITTOTALLEN(len);
    result = (VarBit *) palloc(rlen);
    SET_VARSIZE(result, rlen);
    VARBITLEN(result) = len;

    memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));

    /* Make sure last byte is zero-padded if needed */
    ipad = VARBITPAD(result);
    if (ipad > 0)
    {
        mask = BITMASK << ipad;
        *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum varbit_in ( PG_FUNCTION_ARGS   ) 

Definition at line 418 of file varbit.c.

References ereport, errcode(), errmsg(), ERROR, Min, palloc0(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_VARBIT_P, SET_VARSIZE, VARBITLEN, VARBITS, and VARBITTOTALLEN.

Referenced by leftmostvalue_varbit().

{
    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_RIGHT_TRUNCATION),
                 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);
    SET_VARSIZE(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 = HIGHBIT;
        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 = HIGHBIT;
                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);
}

Datum varbit_out ( PG_FUNCTION_ARGS   ) 

Definition at line 540 of file varbit.c.

References i, IS_HIGHBIT_SET, palloc(), PG_GETARG_VARBIT_P, PG_RETURN_CSTRING, VARBITLEN, and VARBITS.

Referenced by bit_out().

{
    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++)
    {
        /* print full bytes */
        x = *sp;
        for (k = 0; k < BITS_PER_BYTE; k++)
        {
            *r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
            x <<= 1;
        }
    }
    if (i < len)
    {
        /* print the last partial byte */
        x = *sp;
        for (k = i; k < len; k++)
        {
            *r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
            x <<= 1;
        }
    }
    *r = '\0';

    PG_RETURN_CSTRING(result);
}

Datum varbit_recv ( PG_FUNCTION_ARGS   ) 

Definition at line 586 of file varbit.c.

References BITMASK, buf, ereport, errcode(), errmsg(), ERROR, palloc(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_VARBIT_P, pq_copymsgbytes(), pq_getmsgint(), SET_VARSIZE, VARBITBYTES, VARBITLEN, VARBITPAD, VARBITS, and VARBITTOTALLEN.

{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       atttypmod = PG_GETARG_INT32(2);
    VarBit     *result;
    int         len,
                bitlen;
    int         ipad;
    bits8       mask;

    bitlen = pq_getmsgint(buf, sizeof(int32));
    if (bitlen < 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                 errmsg("invalid length in external bit string")));

    /*
     * Sometimes atttypmod is not supplied. If it is supplied we need to make
     * sure that the bitstring fits.
     */
    if (atttypmod > 0 && bitlen > atttypmod)
        ereport(ERROR,
                (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
                 errmsg("bit string too long for type bit varying(%d)",
                        atttypmod)));

    len = VARBITTOTALLEN(bitlen);
    result = (VarBit *) palloc(len);
    SET_VARSIZE(result, len);
    VARBITLEN(result) = bitlen;

    pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));

    /* Make sure last byte is zero-padded if needed */
    ipad = VARBITPAD(result);
    if (ipad > 0)
    {
        mask = BITMASK << ipad;
        *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
    }

    PG_RETURN_VARBIT_P(result);
}

Datum varbit_send ( PG_FUNCTION_ARGS   ) 
Datum varbit_transform ( PG_FUNCTION_ARGS   ) 

Definition at line 656 of file varbit.c.

References FuncExpr::args, Assert, DatumGetInt32, exprTypmod(), IsA, linitial, list_length(), lsecond, PG_GETARG_POINTER, PG_RETURN_POINTER, and relabel_to_typmod().

{
    FuncExpr   *expr = (FuncExpr *) PG_GETARG_POINTER(0);
    Node       *ret = NULL;
    Node       *typmod;

    Assert(IsA(expr, FuncExpr));
    Assert(list_length(expr->args) >= 2);

    typmod = (Node *) lsecond(expr->args);

    if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull)
    {
        Node       *source = (Node *) linitial(expr->args);
        int32       new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
        int32       old_max = exprTypmod(source);
        int32       new_max = new_typmod;

        /* Note: varbit() treats typmod 0 as invalid, so we do too */
        if (new_max <= 0 || (old_max > 0 && old_max <= new_max))
            ret = relabel_to_typmod(source, new_typmod);
    }

    PG_RETURN_POINTER(ret);
}

Datum varbittypmodin ( PG_FUNCTION_ARGS   ) 

Definition at line 730 of file varbit.c.

References anybit_typmodin(), PG_GETARG_ARRAYTYPE_P, and PG_RETURN_INT32.

Datum varbittypmodout ( PG_FUNCTION_ARGS   ) 

Definition at line 738 of file varbit.c.

References anybit_typmodout(), PG_GETARG_INT32, and PG_RETURN_CSTRING.