📄 varbit.c
字号:
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); VARATT_SIZEP(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);}/* bitxor * perform a logical XOR on two bit strings. */Datumbitxor(PG_FUNCTION_ARGS){ 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); VARATT_SIZEP(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);}/* bitnot * perform a logical NOT on a bit string. */Datumbitnot(PG_FUNCTION_ARGS){ VarBit *arg = PG_GETARG_VARBIT_P(0); VarBit *result; bits8 *p, *r; bits8 mask; result = (VarBit *) palloc(VARSIZE(arg)); VARATT_SIZEP(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);}/* bitshiftleft * do a left shift (i.e. towards the beginning of the string) */Datumbitshiftleft(PG_FUNCTION_ARGS){ 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)); VARATT_SIZEP(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);}/* bitshiftright * do a right shift (i.e. towards the end of the string) */Datumbitshiftright(PG_FUNCTION_ARGS){ 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)); VARATT_SIZEP(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);}/* * This is not defined in any standard. We retain the natural ordering of * bits here, as it just seems more intuitive. */Datumbitfromint4(PG_FUNCTION_ARGS){ 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); VARATT_SIZEP(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) { *r++ = (bits8) ((a >> (srcbitsleft - 8)) & 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);}Datumbittoint4(PG_FUNCTION_ARGS){ 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);}Datumbitfromint8(PG_FUNCTION_ARGS){ 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); VARATT_SIZEP(result) = rlen; VARBITLEN(result) = typmod; r = VARBITS(result); destbitsleft = typmod;#ifndef INT64_IS_BUSTED srcbitsleft = 64;#else srcbitsleft = 32; /* don't try to shift more than 32 */#endif /* 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) { *r++ = (bits8) ((a >> (srcbitsleft - 8)) & 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);}Datumbittoint8(PG_FUNCTION_ARGS){ 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);}/* Determines the position of S2 in the bitstring S1 (1-based string). * If S2 does not appear in S1 this function returns 0. * If S2 is of length 0 this function returns 1. * Compatible in usage with POSITION() functions for other data types. */Datumbitposition(PG_FUNCTION_ARGS){ 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -