Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * varbit.c
4 : : * Functions for the SQL datatypes BIT() and BIT VARYING().
5 : : *
6 : : * The data structure contains the following elements:
7 : : * header -- length of the whole data structure (incl header)
8 : : * in bytes (as with all varying length datatypes)
9 : : * data section -- private data section for the bits data structures
10 : : * bitlength -- length of the bit string in bits
11 : : * bitdata -- bit string, most significant byte first
12 : : *
13 : : * The length of the bitdata vector should always be exactly as many
14 : : * bytes as are needed for the given bitlength. If the bitlength is
15 : : * not a multiple of 8, the extra low-order padding bits of the last
16 : : * byte must be zeroes.
17 : : *
18 : : * attypmod is defined as the length of the bit string in bits, or for
19 : : * varying bits the maximum length.
20 : : *
21 : : * Code originally contributed by Adriaan Joubert.
22 : : *
23 : : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
24 : : * Portions Copyright (c) 1994, Regents of the University of California
25 : : *
26 : : * IDENTIFICATION
27 : : * src/backend/utils/adt/varbit.c
28 : : *
29 : : *-------------------------------------------------------------------------
30 : : */
31 : :
32 : : #include "postgres.h"
33 : :
34 : : #include "access/htup_details.h"
35 : : #include "common/int.h"
36 : : #include "libpq/pqformat.h"
37 : : #include "nodes/nodeFuncs.h"
38 : : #include "nodes/supportnodes.h"
39 : : #include "port/pg_bitutils.h"
40 : : #include "utils/array.h"
41 : : #include "utils/fmgrprotos.h"
42 : : #include "utils/varbit.h"
43 : :
44 : : #define HEXDIG(z) ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
45 : :
46 : : /* Mask off any bits that should be zero in the last byte of a bitstring */
47 : : #define VARBIT_PAD(vb) \
48 : : do { \
49 : : int32 pad_ = VARBITPAD(vb); \
50 : : Assert(pad_ >= 0 && pad_ < BITS_PER_BYTE); \
51 : : if (pad_ > 0) \
52 : : *(VARBITS(vb) + VARBITBYTES(vb) - 1) &= BITMASK << pad_; \
53 : : } while (0)
54 : :
55 : : /*
56 : : * Many functions work byte-by-byte, so they have a pointer handy to the
57 : : * last-plus-one byte, which saves a cycle or two.
58 : : */
59 : : #define VARBIT_PAD_LAST(vb, ptr) \
60 : : do { \
61 : : int32 pad_ = VARBITPAD(vb); \
62 : : Assert(pad_ >= 0 && pad_ < BITS_PER_BYTE); \
63 : : if (pad_ > 0) \
64 : : *((ptr) - 1) &= BITMASK << pad_; \
65 : : } while (0)
66 : :
67 : : /* Assert proper padding of a bitstring */
68 : : #ifdef USE_ASSERT_CHECKING
69 : : #define VARBIT_CORRECTLY_PADDED(vb) \
70 : : do { \
71 : : int32 pad_ = VARBITPAD(vb); \
72 : : Assert(pad_ >= 0 && pad_ < BITS_PER_BYTE); \
73 : : Assert(pad_ == 0 || \
74 : : (*(VARBITS(vb) + VARBITBYTES(vb) - 1) & ~(BITMASK << pad_)) == 0); \
75 : : } while (0)
76 : : #else
77 : : #define VARBIT_CORRECTLY_PADDED(vb) ((void) 0)
78 : : #endif
79 : :
80 : : static VarBit *bit_catenate(VarBit *arg1, VarBit *arg2);
81 : : static VarBit *bitsubstring(VarBit *arg, int32 s, int32 l,
82 : : bool length_not_specified);
83 : : static VarBit *bit_overlay(VarBit *t1, VarBit *t2, int sp, int sl);
84 : :
85 : :
86 : : /*
87 : : * common code for bittypmodin and varbittypmodin
88 : : */
89 : : static int32
6315 tgl@sss.pgh.pa.us 90 :CBC 1062 : anybit_typmodin(ArrayType *ta, const char *typename)
91 : : {
92 : : int32 typmod;
93 : : int32 *tl;
94 : : int n;
95 : :
6148 96 : 1062 : tl = ArrayGetIntegerTypmods(ta, &n);
97 : :
98 : : /*
99 : : * we're not too tense about good error message here because grammar
100 : : * shouldn't allow wrong number of modifiers for BIT
101 : : */
6315 102 [ - + ]: 1062 : if (n != 1)
6315 tgl@sss.pgh.pa.us 103 [ # # ]:UBC 0 : ereport(ERROR,
104 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
105 : : errmsg("invalid type modifier")));
106 : :
6315 tgl@sss.pgh.pa.us 107 [ - + ]:CBC 1062 : if (*tl < 1)
6315 tgl@sss.pgh.pa.us 108 [ # # ]:UBC 0 : ereport(ERROR,
109 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
110 : : errmsg("length for type %s must be at least 1",
111 : : typename)));
6315 tgl@sss.pgh.pa.us 112 [ - + ]:CBC 1062 : if (*tl > (MaxAttrSize * BITS_PER_BYTE))
6315 tgl@sss.pgh.pa.us 113 [ # # ]:UBC 0 : ereport(ERROR,
114 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
115 : : errmsg("length for type %s cannot exceed %d",
116 : : typename, MaxAttrSize * BITS_PER_BYTE)));
117 : :
6315 tgl@sss.pgh.pa.us 118 :CBC 1062 : typmod = *tl;
119 : :
120 : 1062 : return typmod;
121 : : }
122 : :
123 : : /*
124 : : * common code for bittypmodout and varbittypmodout
125 : : */
126 : : static char *
127 : 179 : anybit_typmodout(int32 typmod)
128 : : {
5995 bruce@momjian.us 129 : 179 : char *res = (char *) palloc(64);
130 : :
6315 tgl@sss.pgh.pa.us 131 [ + - ]: 179 : if (typmod >= 0)
132 : 179 : snprintf(res, 64, "(%d)", typmod);
133 : : else
6315 tgl@sss.pgh.pa.us 134 :UBC 0 : *res = '\0';
135 : :
6315 tgl@sss.pgh.pa.us 136 :CBC 179 : return res;
137 : : }
138 : :
139 : :
140 : : /*
141 : : * bit_in -
142 : : * converts a char string to the internal representation of a bitstring.
143 : : * The length is determined by the number of bits required plus
144 : : * VARHDRSZ bytes or from atttypmod.
145 : : */
146 : : Datum
8363 peter_e@gmx.net 147 : 2890 : bit_in(PG_FUNCTION_ARGS)
148 : : {
8548 149 : 2890 : char *input_string = PG_GETARG_CSTRING(0);
150 : : #ifdef NOT_USED
151 : : Oid typelem = PG_GETARG_OID(1);
152 : : #endif
8637 tgl@sss.pgh.pa.us 153 : 2890 : int32 atttypmod = PG_GETARG_INT32(2);
487 154 : 2890 : Node *escontext = fcinfo->context;
155 : : VarBit *result; /* The resulting bit string */
156 : : char *sp; /* pointer into the character string */
157 : : bits8 *r; /* pointer into the result */
158 : : int len, /* Length of the whole data structure */
159 : : bitlen, /* Number of bits in the bit string */
160 : : slen; /* Length of the input string */
161 : : bool bit_not_hex; /* false = hex string true = bit string */
162 : : int bc;
8768 bruce@momjian.us 163 : 2890 : bits8 x = 0;
164 : :
165 : : /* Check that the first character is a b or an x */
8548 peter_e@gmx.net 166 [ + + + + ]: 2890 : if (input_string[0] == 'b' || input_string[0] == 'B')
167 : : {
8637 tgl@sss.pgh.pa.us 168 : 385 : bit_not_hex = true;
8548 peter_e@gmx.net 169 : 385 : sp = input_string + 1;
170 : : }
171 [ + + + + ]: 2505 : else if (input_string[0] == 'x' || input_string[0] == 'X')
172 : : {
8637 tgl@sss.pgh.pa.us 173 : 1738 : bit_not_hex = false;
8548 peter_e@gmx.net 174 : 1738 : sp = input_string + 1;
175 : : }
176 : : else
177 : : {
178 : : /*
179 : : * Otherwise it's binary. This allows things like cast('1001' as bit)
180 : : * to work transparently.
181 : : */
182 : 767 : bit_not_hex = true;
183 : 767 : sp = input_string;
184 : : }
185 : :
186 : : /*
187 : : * Determine bitlength from input string. MaxAllocSize ensures a regular
188 : : * input is small enough, but we must check hex input.
189 : : */
190 : 2890 : slen = strlen(sp);
8637 tgl@sss.pgh.pa.us 191 [ + + ]: 2890 : if (bit_not_hex)
192 : 1152 : bitlen = slen;
193 : : else
194 : : {
3709 noah@leadboat.com 195 [ - + ]: 1738 : if (slen > VARBITMAXLEN / 4)
487 tgl@sss.pgh.pa.us 196 [ # # ]:UBC 0 : ereturn(escontext, (Datum) 0,
197 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
198 : : errmsg("bit string length exceeds the maximum allowed (%d)",
199 : : VARBITMAXLEN)));
8637 tgl@sss.pgh.pa.us 200 :CBC 1738 : bitlen = slen * 4;
201 : : }
202 : :
203 : : /*
204 : : * Sometimes atttypmod is not supplied. If it is supplied we need to make
205 : : * sure that the bitstring fits.
206 : : */
207 [ + + ]: 2890 : if (atttypmod <= 0)
8768 bruce@momjian.us 208 : 2203 : atttypmod = bitlen;
8363 peter_e@gmx.net 209 [ + + ]: 687 : else if (bitlen != atttypmod)
487 tgl@sss.pgh.pa.us 210 [ + + ]: 6 : ereturn(escontext, (Datum) 0,
211 : : (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
212 : : errmsg("bit string length %d does not match type bit(%d)",
213 : : bitlen, atttypmod)));
214 : :
8637 215 : 2884 : len = VARBITTOTALLEN(atttypmod);
216 : : /* set to 0 so that *r is always initialised and string is zero-padded */
7823 bruce@momjian.us 217 : 2884 : result = (VarBit *) palloc0(len);
6256 tgl@sss.pgh.pa.us 218 : 2884 : SET_VARSIZE(result, len);
8768 bruce@momjian.us 219 : 2884 : VARBITLEN(result) = atttypmod;
220 : :
221 : 2884 : r = VARBITS(result);
222 [ + + ]: 2884 : if (bit_not_hex)
223 : : {
224 : : /* Parse the bit representation of the string */
225 : : /* We know it fits, as bitlen was compared to atttypmod */
6685 226 : 1146 : x = HIGHBIT;
8637 tgl@sss.pgh.pa.us 227 [ + + ]: 32543 : for (; *sp; sp++)
228 : : {
8768 bruce@momjian.us 229 [ + + ]: 31409 : if (*sp == '1')
230 : 15901 : *r |= x;
8637 tgl@sss.pgh.pa.us 231 [ + + ]: 15508 : else if (*sp != '0')
487 232 [ + + ]: 12 : ereturn(escontext, (Datum) 0,
233 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
234 : : errmsg("\"%.*s\" is not a valid binary digit",
235 : : pg_mblen(sp), sp)));
236 : :
8637 237 : 31397 : x >>= 1;
238 [ + + ]: 31397 : if (x == 0)
239 : : {
6685 bruce@momjian.us 240 : 3684 : x = HIGHBIT;
8768 241 : 3684 : r++;
242 : : }
243 : : }
244 : : }
245 : : else
246 : : {
247 : : /* Parse the hex representation of the string */
8637 tgl@sss.pgh.pa.us 248 [ + + ]: 20578 : for (bc = 0; *sp; sp++)
249 : : {
8768 bruce@momjian.us 250 [ + + + + ]: 18852 : if (*sp >= '0' && *sp <= '9')
251 : 12824 : x = (bits8) (*sp - '0');
252 [ + + + + ]: 6028 : else if (*sp >= 'A' && *sp <= 'F')
253 : 299 : x = (bits8) (*sp - 'A') + 10;
254 [ + + + - ]: 5729 : else if (*sp >= 'a' && *sp <= 'f')
255 : 5717 : x = (bits8) (*sp - 'a') + 10;
256 : : else
487 tgl@sss.pgh.pa.us 257 [ + + ]: 12 : ereturn(escontext, (Datum) 0,
258 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
259 : : errmsg("\"%.*s\" is not a valid hexadecimal digit",
260 : : pg_mblen(sp), sp)));
261 : :
8768 bruce@momjian.us 262 [ + + ]: 18840 : if (bc)
263 : : {
264 : 9364 : *r++ |= x;
8637 tgl@sss.pgh.pa.us 265 : 9364 : bc = 0;
266 : : }
267 : : else
268 : : {
8768 bruce@momjian.us 269 : 9476 : *r = x << 4;
8637 tgl@sss.pgh.pa.us 270 : 9476 : bc = 1;
271 : : }
272 : : }
273 : : }
274 : :
275 : 2860 : PG_RETURN_VARBIT_P(result);
276 : : }
277 : :
278 : :
279 : : Datum
8363 peter_e@gmx.net 280 : 2119 : bit_out(PG_FUNCTION_ARGS)
281 : : {
282 : : #if 1
283 : : /* same as varbit output */
8550 284 : 2119 : return varbit_out(fcinfo);
285 : : #else
286 : :
287 : : /*
288 : : * This is how one would print a hex string, in case someone wants to
289 : : * write a formatting function.
290 : : */
291 : : VarBit *s = PG_GETARG_VARBIT_P(0);
292 : : char *result,
293 : : *r;
294 : : bits8 *sp;
295 : : int i,
296 : : len,
297 : : bitlen;
298 : :
299 : : /* Assertion to help catch any bit functions that don't pad correctly */
300 : : VARBIT_CORRECTLY_PADDED(s);
301 : :
302 : : bitlen = VARBITLEN(s);
303 : : len = (bitlen + 3) / 4;
304 : : result = (char *) palloc(len + 2);
305 : : sp = VARBITS(s);
306 : : r = result;
307 : : *r++ = 'X';
308 : : /* we cheat by knowing that we store full bytes zero padded */
309 : : for (i = 0; i < len; i += 2, sp++)
310 : : {
311 : : *r++ = HEXDIG((*sp) >> 4);
312 : : *r++ = HEXDIG((*sp) & 0xF);
313 : : }
314 : :
315 : : /*
316 : : * Go back one step if we printed a hex number that was not part of the
317 : : * bitstring anymore
318 : : */
319 : : if (i > len)
320 : : r--;
321 : : *r = '\0';
322 : :
323 : : PG_RETURN_CSTRING(result);
324 : : #endif
325 : : }
326 : :
327 : : /*
328 : : * bit_recv - converts external binary format to bit
329 : : */
330 : : Datum
7643 tgl@sss.pgh.pa.us 331 :UBC 0 : bit_recv(PG_FUNCTION_ARGS)
332 : : {
6853 333 : 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
334 : :
335 : : #ifdef NOT_USED
336 : : Oid typelem = PG_GETARG_OID(1);
337 : : #endif
338 : 0 : int32 atttypmod = PG_GETARG_INT32(2);
339 : : VarBit *result;
340 : : int len,
341 : : bitlen;
342 : :
343 : 0 : bitlen = pq_getmsgint(buf, sizeof(int32));
2739 344 [ # # # # ]: 0 : if (bitlen < 0 || bitlen > VARBITMAXLEN)
6853 345 [ # # ]: 0 : ereport(ERROR,
346 : : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
347 : : errmsg("invalid length in external bit string")));
348 : :
349 : : /*
350 : : * Sometimes atttypmod is not supplied. If it is supplied we need to make
351 : : * sure that the bitstring fits.
352 : : */
353 [ # # # # ]: 0 : if (atttypmod > 0 && bitlen != atttypmod)
354 [ # # ]: 0 : ereport(ERROR,
355 : : (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
356 : : errmsg("bit string length %d does not match type bit(%d)",
357 : : bitlen, atttypmod)));
358 : :
359 : 0 : len = VARBITTOTALLEN(bitlen);
360 : 0 : result = (VarBit *) palloc(len);
6256 361 : 0 : SET_VARSIZE(result, len);
6853 362 : 0 : VARBITLEN(result) = bitlen;
363 : :
364 : 0 : pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
365 : :
366 : : /* Make sure last byte is correctly zero-padded */
1666 367 [ # # # # : 0 : VARBIT_PAD(result);
# # ]
368 : :
6853 369 : 0 : PG_RETURN_VARBIT_P(result);
370 : : }
371 : :
372 : : /*
373 : : * bit_send - converts bit to binary format
374 : : */
375 : : Datum
7643 376 : 0 : bit_send(PG_FUNCTION_ARGS)
377 : : {
378 : : /* Exactly the same as varbit_send, so share code */
379 : 0 : return varbit_send(fcinfo);
380 : : }
381 : :
382 : : /*
383 : : * bit()
384 : : * Converts a bit() type to a specific internal length.
385 : : * len is the bitlength specified in the column definition.
386 : : *
387 : : * If doing implicit cast, raise error when source data is wrong length.
388 : : * If doing explicit cast, silently truncate or zero-pad to specified length.
389 : : */
390 : : Datum
8363 peter_e@gmx.net 391 :CBC 502 : bit(PG_FUNCTION_ARGS)
392 : : {
8637 tgl@sss.pgh.pa.us 393 : 502 : VarBit *arg = PG_GETARG_VARBIT_P(0);
394 : 502 : int32 len = PG_GETARG_INT32(1);
7879 395 : 502 : bool isExplicit = PG_GETARG_BOOL(2);
396 : : VarBit *result;
397 : : int rlen;
398 : :
399 : : /* No work if typmod is invalid or supplied data matches it already */
2739 400 [ + - + - : 502 : if (len <= 0 || len > VARBITMAXLEN || len == VARBITLEN(arg))
+ + ]
8637 401 : 199 : PG_RETURN_VARBIT_P(arg);
402 : :
7879 403 [ + + ]: 303 : if (!isExplicit)
7567 404 [ + - ]: 6 : ereport(ERROR,
405 : : (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
406 : : errmsg("bit string length %d does not match type bit(%d)",
407 : : VARBITLEN(arg), len)));
408 : :
7879 409 : 297 : rlen = VARBITTOTALLEN(len);
410 : : /* set to 0 so that string is zero-padded */
7823 bruce@momjian.us 411 : 297 : result = (VarBit *) palloc0(rlen);
6256 tgl@sss.pgh.pa.us 412 : 297 : SET_VARSIZE(result, rlen);
7879 413 : 297 : VARBITLEN(result) = len;
414 : :
415 : 297 : memcpy(VARBITS(result), VARBITS(arg),
416 : 297 : Min(VARBITBYTES(result), VARBITBYTES(arg)));
417 : :
418 : : /*
419 : : * Make sure last byte is zero-padded if needed. This is useless but safe
420 : : * if source data was shorter than target length (we assume the last byte
421 : : * of the source data was itself correctly zero-padded).
422 : : */
1666 423 [ + - - + : 297 : VARBIT_PAD(result);
+ - ]
424 : :
7879 425 : 297 : PG_RETURN_VARBIT_P(result);
426 : : }
427 : :
428 : : Datum
6315 429 : 940 : bittypmodin(PG_FUNCTION_ARGS)
430 : : {
5995 bruce@momjian.us 431 : 940 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
432 : :
6315 tgl@sss.pgh.pa.us 433 : 940 : PG_RETURN_INT32(anybit_typmodin(ta, "bit"));
434 : : }
435 : :
436 : : Datum
437 : 113 : bittypmodout(PG_FUNCTION_ARGS)
438 : : {
5995 bruce@momjian.us 439 : 113 : int32 typmod = PG_GETARG_INT32(0);
440 : :
6315 tgl@sss.pgh.pa.us 441 : 113 : PG_RETURN_CSTRING(anybit_typmodout(typmod));
442 : : }
443 : :
444 : :
445 : : /*
446 : : * varbit_in -
447 : : * converts a string to the internal representation of a bitstring.
448 : : * This is the same as bit_in except that atttypmod is taken as
449 : : * the maximum length, not the exact length to force the bitstring to.
450 : : */
451 : : Datum
8637 452 : 917 : varbit_in(PG_FUNCTION_ARGS)
453 : : {
8548 peter_e@gmx.net 454 : 917 : char *input_string = PG_GETARG_CSTRING(0);
455 : : #ifdef NOT_USED
456 : : Oid typelem = PG_GETARG_OID(1);
457 : : #endif
8637 tgl@sss.pgh.pa.us 458 : 917 : int32 atttypmod = PG_GETARG_INT32(2);
487 459 : 917 : Node *escontext = fcinfo->context;
460 : : VarBit *result; /* The resulting bit string */
461 : : char *sp; /* pointer into the character string */
462 : : bits8 *r; /* pointer into the result */
463 : : int len, /* Length of the whole data structure */
464 : : bitlen, /* Number of bits in the bit string */
465 : : slen; /* Length of the input string */
466 : : bool bit_not_hex; /* false = hex string true = bit string */
467 : : int bc;
8768 bruce@momjian.us 468 : 917 : bits8 x = 0;
469 : :
470 : : /* Check that the first character is a b or an x */
8548 peter_e@gmx.net 471 [ + - - + ]: 917 : if (input_string[0] == 'b' || input_string[0] == 'B')
472 : : {
8637 tgl@sss.pgh.pa.us 473 :UBC 0 : bit_not_hex = true;
8548 peter_e@gmx.net 474 : 0 : sp = input_string + 1;
475 : : }
8548 peter_e@gmx.net 476 [ + + + + ]:CBC 917 : else if (input_string[0] == 'x' || input_string[0] == 'X')
477 : : {
8637 tgl@sss.pgh.pa.us 478 : 66 : bit_not_hex = false;
8548 peter_e@gmx.net 479 : 66 : sp = input_string + 1;
480 : : }
481 : : else
482 : : {
483 : 851 : bit_not_hex = true;
484 : 851 : sp = input_string;
485 : : }
486 : :
487 : : /*
488 : : * Determine bitlength from input string. MaxAllocSize ensures a regular
489 : : * input is small enough, but we must check hex input.
490 : : */
491 : 917 : slen = strlen(sp);
8637 tgl@sss.pgh.pa.us 492 [ + + ]: 917 : if (bit_not_hex)
493 : 851 : bitlen = slen;
494 : : else
495 : : {
3709 noah@leadboat.com 496 [ - + ]: 66 : if (slen > VARBITMAXLEN / 4)
487 tgl@sss.pgh.pa.us 497 [ # # ]:UBC 0 : ereturn(escontext, (Datum) 0,
498 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
499 : : errmsg("bit string length exceeds the maximum allowed (%d)",
500 : : VARBITMAXLEN)));
8637 tgl@sss.pgh.pa.us 501 :CBC 66 : bitlen = slen * 4;
502 : : }
503 : :
504 : : /*
505 : : * Sometimes atttypmod is not supplied. If it is supplied we need to make
506 : : * sure that the bitstring fits.
507 : : */
508 [ + + ]: 917 : if (atttypmod <= 0)
509 : 857 : atttypmod = bitlen;
8363 peter_e@gmx.net 510 [ - + ]: 60 : else if (bitlen > atttypmod)
487 tgl@sss.pgh.pa.us 511 [ # # ]:UBC 0 : ereturn(escontext, (Datum) 0,
512 : : (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
513 : : errmsg("bit string too long for type bit varying(%d)",
514 : : atttypmod)));
515 : :
8637 tgl@sss.pgh.pa.us 516 :CBC 917 : len = VARBITTOTALLEN(bitlen);
517 : : /* set to 0 so that *r is always initialised and string is zero-padded */
7823 bruce@momjian.us 518 : 917 : result = (VarBit *) palloc0(len);
6256 tgl@sss.pgh.pa.us 519 : 917 : SET_VARSIZE(result, len);
8637 520 : 917 : VARBITLEN(result) = Min(bitlen, atttypmod);
521 : :
8768 bruce@momjian.us 522 : 917 : r = VARBITS(result);
523 [ + + ]: 917 : if (bit_not_hex)
524 : : {
525 : : /* Parse the bit representation of the string */
526 : : /* We know it fits, as bitlen was compared to atttypmod */
6685 527 : 851 : x = HIGHBIT;
8637 tgl@sss.pgh.pa.us 528 [ + + ]: 33393 : for (; *sp; sp++)
529 : : {
8768 bruce@momjian.us 530 [ + + ]: 32548 : if (*sp == '1')
531 : 16227 : *r |= x;
8637 tgl@sss.pgh.pa.us 532 [ + + ]: 16321 : else if (*sp != '0')
487 533 [ + + ]: 6 : ereturn(escontext, (Datum) 0,
534 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
535 : : errmsg("\"%.*s\" is not a valid binary digit",
536 : : pg_mblen(sp), sp)));
537 : :
8637 538 : 32542 : x >>= 1;
539 [ + + ]: 32542 : if (x == 0)
540 : : {
6685 bruce@momjian.us 541 : 3750 : x = HIGHBIT;
8768 542 : 3750 : r++;
543 : : }
544 : : }
545 : : }
546 : : else
547 : : {
548 : : /* Parse the hex representation of the string */
8637 tgl@sss.pgh.pa.us 549 [ + + ]: 276 : for (bc = 0; *sp; sp++)
550 : : {
8768 bruce@momjian.us 551 [ + - + + ]: 216 : if (*sp >= '0' && *sp <= '9')
552 : 159 : x = (bits8) (*sp - '0');
553 [ + - + + ]: 57 : else if (*sp >= 'A' && *sp <= 'F')
554 : 51 : x = (bits8) (*sp - 'A') + 10;
555 [ - + - - ]: 6 : else if (*sp >= 'a' && *sp <= 'f')
8768 bruce@momjian.us 556 :UBC 0 : x = (bits8) (*sp - 'a') + 10;
557 : : else
487 tgl@sss.pgh.pa.us 558 [ + + ]:CBC 6 : ereturn(escontext, (Datum) 0,
559 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
560 : : errmsg("\"%.*s\" is not a valid hexadecimal digit",
561 : : pg_mblen(sp), sp)));
562 : :
8768 bruce@momjian.us 563 [ + + ]: 210 : if (bc)
564 : : {
565 : 102 : *r++ |= x;
8637 tgl@sss.pgh.pa.us 566 : 102 : bc = 0;
567 : : }
568 : : else
569 : : {
8768 bruce@momjian.us 570 : 108 : *r = x << 4;
8637 tgl@sss.pgh.pa.us 571 : 108 : bc = 1;
572 : : }
573 : : }
574 : : }
575 : :
576 : 905 : PG_RETURN_VARBIT_P(result);
577 : : }
578 : :
579 : : /*
580 : : * varbit_out -
581 : : * Prints the string as bits to preserve length accurately
582 : : *
583 : : * XXX varbit_recv() and hex input to varbit_in() can load a value that this
584 : : * cannot emit. Consider using hex output for such values.
585 : : */
586 : : Datum
587 : 3104 : varbit_out(PG_FUNCTION_ARGS)
588 : : {
589 : 3104 : VarBit *s = PG_GETARG_VARBIT_P(0);
590 : : char *result,
591 : : *r;
592 : : bits8 *sp;
593 : : bits8 x;
594 : : int i,
595 : : k,
596 : : len;
597 : :
598 : : /* Assertion to help catch any bit functions that don't pad correctly */
1666 599 [ + - - + : 3104 : VARBIT_CORRECTLY_PADDED(s);
+ + - + ]
600 : :
8637 601 : 3104 : len = VARBITLEN(s);
8548 peter_e@gmx.net 602 : 3104 : result = (char *) palloc(len + 1);
8637 tgl@sss.pgh.pa.us 603 : 3104 : sp = VARBITS(s);
604 : 3104 : r = result;
6081 605 [ + + ]: 7265 : for (i = 0; i <= len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++)
606 : : {
607 : : /* print full bytes */
8637 608 : 4161 : x = *sp;
8632 609 [ + + ]: 37449 : for (k = 0; k < BITS_PER_BYTE; k++)
610 : : {
6685 bruce@momjian.us 611 [ + + ]: 33288 : *r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
8637 tgl@sss.pgh.pa.us 612 : 33288 : x <<= 1;
613 : : }
614 : : }
6081 615 [ + + ]: 3104 : if (i < len)
616 : : {
617 : : /* print the last partial byte */
618 : 1487 : x = *sp;
619 [ + + ]: 7210 : for (k = i; k < len; k++)
620 : : {
621 [ + + ]: 5723 : *r++ = IS_HIGHBIT_SET(x) ? '1' : '0';
622 : 5723 : x <<= 1;
623 : : }
624 : : }
8637 625 : 3104 : *r = '\0';
626 : :
627 : 3104 : PG_RETURN_CSTRING(result);
628 : : }
629 : :
630 : : /*
631 : : * varbit_recv - converts external binary format to varbit
632 : : *
633 : : * External format is the bitlen as an int32, then the byte array.
634 : : */
635 : : Datum
7643 tgl@sss.pgh.pa.us 636 :UBC 0 : varbit_recv(PG_FUNCTION_ARGS)
637 : : {
638 : 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
639 : :
640 : : #ifdef NOT_USED
641 : : Oid typelem = PG_GETARG_OID(1);
642 : : #endif
6853 643 : 0 : int32 atttypmod = PG_GETARG_INT32(2);
644 : : VarBit *result;
645 : : int len,
646 : : bitlen;
647 : :
7643 648 : 0 : bitlen = pq_getmsgint(buf, sizeof(int32));
2739 649 [ # # # # ]: 0 : if (bitlen < 0 || bitlen > VARBITMAXLEN)
7567 650 [ # # ]: 0 : ereport(ERROR,
651 : : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
652 : : errmsg("invalid length in external bit string")));
653 : :
654 : : /*
655 : : * Sometimes atttypmod is not supplied. If it is supplied we need to make
656 : : * sure that the bitstring fits.
657 : : */
6853 658 [ # # # # ]: 0 : if (atttypmod > 0 && bitlen > atttypmod)
659 [ # # ]: 0 : ereport(ERROR,
660 : : (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
661 : : errmsg("bit string too long for type bit varying(%d)",
662 : : atttypmod)));
663 : :
7643 664 : 0 : len = VARBITTOTALLEN(bitlen);
665 : 0 : result = (VarBit *) palloc(len);
6256 666 : 0 : SET_VARSIZE(result, len);
7643 667 : 0 : VARBITLEN(result) = bitlen;
668 : :
669 : 0 : pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
670 : :
671 : : /* Make sure last byte is correctly zero-padded */
1666 672 [ # # # # : 0 : VARBIT_PAD(result);
# # ]
673 : :
7643 674 : 0 : PG_RETURN_VARBIT_P(result);
675 : : }
676 : :
677 : : /*
678 : : * varbit_send - converts varbit to binary format
679 : : */
680 : : Datum
681 : 0 : varbit_send(PG_FUNCTION_ARGS)
682 : : {
683 : 0 : VarBit *s = PG_GETARG_VARBIT_P(0);
684 : : StringInfoData buf;
685 : :
686 : 0 : pq_begintypsend(&buf);
2377 andres@anarazel.de 687 : 0 : pq_sendint32(&buf, VARBITLEN(s));
425 peter@eisentraut.org 688 : 0 : pq_sendbytes(&buf, VARBITS(s), VARBITBYTES(s));
7643 tgl@sss.pgh.pa.us 689 : 0 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
690 : : }
691 : :
692 : : /*
693 : : * varbit_support()
694 : : *
695 : : * Planner support function for the varbit() length coercion function.
696 : : *
697 : : * Currently, the only interesting thing we can do is flatten calls that set
698 : : * the new maximum length >= the previous maximum length. We can ignore the
699 : : * isExplicit argument, since that only affects truncation cases.
700 : : */
701 : : Datum
1891 tgl@sss.pgh.pa.us 702 :CBC 60 : varbit_support(PG_FUNCTION_ARGS)
703 : : {
704 : 60 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
4450 rhaas@postgresql.org 705 : 60 : Node *ret = NULL;
706 : :
1891 tgl@sss.pgh.pa.us 707 [ + + ]: 60 : if (IsA(rawreq, SupportRequestSimplify))
708 : : {
709 : 30 : SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
710 : 30 : FuncExpr *expr = req->fcall;
711 : : Node *typmod;
712 : :
713 [ - + ]: 30 : Assert(list_length(expr->args) >= 2);
714 : :
715 : 30 : typmod = (Node *) lsecond(expr->args);
716 : :
1429 717 [ + - + - ]: 30 : if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
718 : : {
1891 719 : 30 : Node *source = (Node *) linitial(expr->args);
720 : 30 : int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
721 : 30 : int32 old_max = exprTypmod(source);
722 : 30 : int32 new_max = new_typmod;
723 : :
724 : : /* Note: varbit() treats typmod 0 as invalid, so we do too */
725 [ + - - + : 30 : if (new_max <= 0 || (old_max > 0 && old_max <= new_max))
- - ]
1891 tgl@sss.pgh.pa.us 726 :UBC 0 : ret = relabel_to_typmod(source, new_typmod);
727 : : }
728 : : }
729 : :
4450 rhaas@postgresql.org 730 :CBC 60 : PG_RETURN_POINTER(ret);
731 : : }
732 : :
733 : : /*
734 : : * varbit()
735 : : * Converts a varbit() type to a specific internal length.
736 : : * len is the maximum bitlength specified in the column definition.
737 : : *
738 : : * If doing implicit cast, raise error when source data is too long.
739 : : * If doing explicit cast, silently truncate to max length.
740 : : */
741 : : Datum
8637 tgl@sss.pgh.pa.us 742 : 489 : varbit(PG_FUNCTION_ARGS)
743 : : {
744 : 489 : VarBit *arg = PG_GETARG_VARBIT_P(0);
745 : 489 : int32 len = PG_GETARG_INT32(1);
7879 746 : 489 : bool isExplicit = PG_GETARG_BOOL(2);
747 : : VarBit *result;
748 : : int rlen;
749 : :
750 : : /* No work if typmod is invalid or supplied data matches it already */
8637 751 [ + - + + ]: 489 : if (len <= 0 || len >= VARBITLEN(arg))
752 : 486 : PG_RETURN_VARBIT_P(arg);
753 : :
7879 754 [ + - ]: 3 : if (!isExplicit)
7567 755 [ + - ]: 3 : ereport(ERROR,
756 : : (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
757 : : errmsg("bit string too long for type bit varying(%d)",
758 : : len)));
759 : :
8637 tgl@sss.pgh.pa.us 760 :UBC 0 : rlen = VARBITTOTALLEN(len);
761 : 0 : result = (VarBit *) palloc(rlen);
6256 762 : 0 : SET_VARSIZE(result, rlen);
8637 763 : 0 : VARBITLEN(result) = len;
764 : :
765 : 0 : memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));
766 : :
767 : : /* Make sure last byte is correctly zero-padded */
1666 768 [ # # # # : 0 : VARBIT_PAD(result);
# # ]
769 : :
7879 770 : 0 : PG_RETURN_VARBIT_P(result);
771 : : }
772 : :
773 : : Datum
6315 tgl@sss.pgh.pa.us 774 :CBC 122 : varbittypmodin(PG_FUNCTION_ARGS)
775 : : {
5995 bruce@momjian.us 776 : 122 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
777 : :
6315 tgl@sss.pgh.pa.us 778 : 122 : PG_RETURN_INT32(anybit_typmodin(ta, "varbit"));
779 : : }
780 : :
781 : : Datum
782 : 66 : varbittypmodout(PG_FUNCTION_ARGS)
783 : : {
5995 bruce@momjian.us 784 : 66 : int32 typmod = PG_GETARG_INT32(0);
785 : :
6315 tgl@sss.pgh.pa.us 786 : 66 : PG_RETURN_CSTRING(anybit_typmodout(typmod));
787 : : }
788 : :
789 : :
790 : : /*
791 : : * Comparison operators
792 : : *
793 : : * We only need one set of comparison operators for bitstrings, as the lengths
794 : : * are stored in the same way for zero-padded and varying bit strings.
795 : : *
796 : : * Note that the standard is not unambiguous about the comparison between
797 : : * zero-padded bit strings and varying bitstrings. If the same value is written
798 : : * into a zero padded bitstring as into a varying bitstring, but the zero
799 : : * padded bitstring has greater length, it will be bigger.
800 : : *
801 : : * Zeros from the beginning of a bitstring cannot simply be ignored, as they
802 : : * may be part of a bit string and may be significant.
803 : : *
804 : : * Note: btree indexes need these routines not to leak memory; therefore,
805 : : * be careful to free working copies of toasted datums. Most places don't
806 : : * need to be so careful.
807 : : */
808 : :
809 : : /*
810 : : * bit_cmp
811 : : *
812 : : * Compares two bitstrings and returns <0, 0, >0 depending on whether the first
813 : : * string is smaller, equal, or bigger than the second. All bits are considered
814 : : * and additional zero bits may make one string smaller/larger than the other,
815 : : * even if their zero-padded values would be the same.
816 : : */
817 : : static int32
8382 818 : 21353 : bit_cmp(VarBit *arg1, VarBit *arg2)
819 : : {
820 : : int bitlen1,
821 : : bytelen1,
822 : : bitlen2,
823 : : bytelen2;
824 : : int32 cmp;
825 : :
826 : 21353 : bytelen1 = VARBITBYTES(arg1);
827 : 21353 : bytelen2 = VARBITBYTES(arg2);
828 : :
829 : 21353 : cmp = memcmp(VARBITS(arg1), VARBITS(arg2), Min(bytelen1, bytelen2));
830 [ + + ]: 21353 : if (cmp == 0)
831 : : {
832 : 3104 : bitlen1 = VARBITLEN(arg1);
833 : 3104 : bitlen2 = VARBITLEN(arg2);
834 [ + + ]: 3104 : if (bitlen1 != bitlen2)
835 [ + + ]: 21 : cmp = (bitlen1 < bitlen2) ? -1 : 1;
836 : : }
837 : 21353 : return cmp;
838 : : }
839 : :
840 : : Datum
8637 841 : 2656 : biteq(PG_FUNCTION_ARGS)
842 : : {
843 : 2656 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
844 : 2656 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
845 : : bool result;
846 : : int bitlen1,
847 : : bitlen2;
848 : :
8768 bruce@momjian.us 849 : 2656 : bitlen1 = VARBITLEN(arg1);
850 : 2656 : bitlen2 = VARBITLEN(arg2);
851 : :
852 : : /* fast path for different-length inputs */
853 [ + + ]: 2656 : if (bitlen1 != bitlen2)
8637 tgl@sss.pgh.pa.us 854 : 751 : result = false;
855 : : else
8382 856 : 1905 : result = (bit_cmp(arg1, arg2) == 0);
857 : :
8637 858 [ + + ]: 2656 : PG_FREE_IF_COPY(arg1, 0);
859 [ + + ]: 2656 : PG_FREE_IF_COPY(arg2, 1);
860 : :
861 : 2656 : PG_RETURN_BOOL(result);
862 : : }
863 : :
864 : : Datum
865 : 484 : bitne(PG_FUNCTION_ARGS)
866 : : {
867 : 484 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
868 : 484 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
869 : : bool result;
870 : : int bitlen1,
871 : : bitlen2;
872 : :
8768 bruce@momjian.us 873 : 484 : bitlen1 = VARBITLEN(arg1);
874 : 484 : bitlen2 = VARBITLEN(arg2);
875 : :
876 : : /* fast path for different-length inputs */
877 [ - + ]: 484 : if (bitlen1 != bitlen2)
8637 tgl@sss.pgh.pa.us 878 :UBC 0 : result = true;
879 : : else
8382 tgl@sss.pgh.pa.us 880 :CBC 484 : result = (bit_cmp(arg1, arg2) != 0);
881 : :
8637 882 [ + + ]: 484 : PG_FREE_IF_COPY(arg1, 0);
883 [ + + ]: 484 : PG_FREE_IF_COPY(arg2, 1);
884 : :
885 : 484 : PG_RETURN_BOOL(result);
886 : : }
887 : :
888 : : Datum
889 : 4940 : bitlt(PG_FUNCTION_ARGS)
890 : : {
891 : 4940 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
892 : 4940 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
893 : : bool result;
894 : :
895 : 4940 : result = (bit_cmp(arg1, arg2) < 0);
896 : :
897 [ + + ]: 4940 : PG_FREE_IF_COPY(arg1, 0);
898 [ + + ]: 4940 : PG_FREE_IF_COPY(arg2, 1);
899 : :
900 : 4940 : PG_RETURN_BOOL(result);
901 : : }
902 : :
903 : : Datum
904 : 4278 : bitle(PG_FUNCTION_ARGS)
905 : : {
906 : 4278 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
907 : 4278 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
908 : : bool result;
909 : :
910 : 4278 : result = (bit_cmp(arg1, arg2) <= 0);
911 : :
912 [ + + ]: 4278 : PG_FREE_IF_COPY(arg1, 0);
913 [ + + ]: 4278 : PG_FREE_IF_COPY(arg2, 1);
914 : :
915 : 4278 : PG_RETURN_BOOL(result);
916 : : }
917 : :
918 : : Datum
919 : 5200 : bitgt(PG_FUNCTION_ARGS)
920 : : {
921 : 5200 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
922 : 5200 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
923 : : bool result;
924 : :
925 : 5200 : result = (bit_cmp(arg1, arg2) > 0);
926 : :
927 [ + + ]: 5200 : PG_FREE_IF_COPY(arg1, 0);
928 [ + + ]: 5200 : PG_FREE_IF_COPY(arg2, 1);
929 : :
930 : 5200 : PG_RETURN_BOOL(result);
931 : : }
932 : :
933 : : Datum
934 : 4168 : bitge(PG_FUNCTION_ARGS)
935 : : {
936 : 4168 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
937 : 4168 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
938 : : bool result;
939 : :
940 : 4168 : result = (bit_cmp(arg1, arg2) >= 0);
941 : :
942 [ + + ]: 4168 : PG_FREE_IF_COPY(arg1, 0);
943 [ + + ]: 4168 : PG_FREE_IF_COPY(arg2, 1);
944 : :
945 : 4168 : PG_RETURN_BOOL(result);
946 : : }
947 : :
948 : : Datum
949 : 378 : bitcmp(PG_FUNCTION_ARGS)
950 : : {
951 : 378 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
952 : 378 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
953 : : int32 result;
954 : :
955 : 378 : result = bit_cmp(arg1, arg2);
956 : :
957 [ + + ]: 378 : PG_FREE_IF_COPY(arg1, 0);
958 [ + + ]: 378 : PG_FREE_IF_COPY(arg2, 1);
959 : :
960 : 378 : PG_RETURN_INT32(result);
961 : : }
962 : :
963 : : /*
964 : : * bitcat
965 : : * Concatenation of bit strings
966 : : */
967 : : Datum
968 : 81 : bitcat(PG_FUNCTION_ARGS)
969 : : {
970 : 81 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
971 : 81 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
972 : :
5193 973 : 81 : PG_RETURN_VARBIT_P(bit_catenate(arg1, arg2));
974 : : }
975 : :
976 : : static VarBit *
977 : 105 : bit_catenate(VarBit *arg1, VarBit *arg2)
978 : : {
979 : : VarBit *result;
980 : : int bitlen1,
981 : : bitlen2,
982 : : bytelen,
983 : : bit1pad,
984 : : bit2shift;
985 : : bits8 *pr,
986 : : *pa;
987 : :
8768 bruce@momjian.us 988 : 105 : bitlen1 = VARBITLEN(arg1);
989 : 105 : bitlen2 = VARBITLEN(arg2);
990 : :
3709 noah@leadboat.com 991 [ - + ]: 105 : if (bitlen1 > VARBITMAXLEN - bitlen2)
3709 noah@leadboat.com 992 [ # # ]:UBC 0 : ereport(ERROR,
993 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
994 : : errmsg("bit string length exceeds the maximum allowed (%d)",
995 : : VARBITMAXLEN)));
8637 tgl@sss.pgh.pa.us 996 :CBC 105 : bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);
997 : :
998 : 105 : result = (VarBit *) palloc(bytelen);
6256 999 : 105 : SET_VARSIZE(result, bytelen);
8768 bruce@momjian.us 1000 : 105 : VARBITLEN(result) = bitlen1 + bitlen2;
1001 : :
1002 : : /* Copy the first bitstring in */
1003 : 105 : memcpy(VARBITS(result), VARBITS(arg1), VARBITBYTES(arg1));
1004 : :
1005 : : /* Copy the second bit string */
1006 : 105 : bit1pad = VARBITPAD(arg1);
1007 [ + + ]: 105 : if (bit1pad == 0)
1008 : : {
1009 : 18 : memcpy(VARBITS(result) + VARBITBYTES(arg1), VARBITS(arg2),
1010 : 18 : VARBITBYTES(arg2));
1011 : : }
1012 [ + + ]: 87 : else if (bitlen2 > 0)
1013 : : {
1014 : : /* We need to shift all the bits to fit */
8632 tgl@sss.pgh.pa.us 1015 : 81 : bit2shift = BITS_PER_BYTE - bit1pad;
8768 bruce@momjian.us 1016 : 81 : pr = VARBITS(result) + VARBITBYTES(arg1) - 1;
8637 tgl@sss.pgh.pa.us 1017 [ + + ]: 189 : for (pa = VARBITS(arg2); pa < VARBITEND(arg2); pa++)
1018 : : {
8768 bruce@momjian.us 1019 : 108 : *pr |= ((*pa >> bit2shift) & BITMASK);
1020 : 108 : pr++;
1021 [ + + ]: 108 : if (pr < VARBITEND(result))
1022 : 69 : *pr = (*pa << bit1pad) & BITMASK;
1023 : : }
1024 : : }
1025 : :
1026 : : /* The pad bits should be already zero at this point */
1027 : :
5193 tgl@sss.pgh.pa.us 1028 : 105 : return result;
1029 : : }
1030 : :
1031 : : /*
1032 : : * bitsubstr
1033 : : * retrieve a substring from the bit string.
1034 : : * Note, s is 1-based.
1035 : : * SQL draft 6.10 9)
1036 : : */
1037 : : Datum
8637 1038 : 60 : bitsubstr(PG_FUNCTION_ARGS)
1039 : : {
5211 1040 : 60 : PG_RETURN_VARBIT_P(bitsubstring(PG_GETARG_VARBIT_P(0),
1041 : : PG_GETARG_INT32(1),
1042 : : PG_GETARG_INT32(2),
1043 : : false));
1044 : : }
1045 : :
1046 : : Datum
1047 : 21 : bitsubstr_no_len(PG_FUNCTION_ARGS)
1048 : : {
1049 : 21 : PG_RETURN_VARBIT_P(bitsubstring(PG_GETARG_VARBIT_P(0),
1050 : : PG_GETARG_INT32(1),
1051 : : -1, true));
1052 : : }
1053 : :
1054 : : static VarBit *
1055 : 105 : bitsubstring(VarBit *arg, int32 s, int32 l, bool length_not_specified)
1056 : : {
1057 : : VarBit *result;
1058 : : int bitlen,
1059 : : rbitlen,
1060 : : len,
1061 : : ishift,
1062 : : i;
1063 : : int32 e,
1064 : : s1,
1065 : : e1;
1066 : : bits8 *r,
1067 : : *ps;
1068 : :
8768 bruce@momjian.us 1069 : 105 : bitlen = VARBITLEN(arg);
1070 : 105 : s1 = Max(s, 1);
1071 : : /* If we do not have an upper bound, use end of string */
5211 tgl@sss.pgh.pa.us 1072 [ + + ]: 105 : if (length_not_specified)
1073 : : {
1074 : 33 : e1 = bitlen + 1;
1075 : : }
1196 1076 [ + + ]: 72 : else if (l < 0)
1077 : : {
1078 : : /* SQL99 says to throw an error for E < S, i.e., negative length */
1079 [ + - ]: 6 : ereport(ERROR,
1080 : : (errcode(ERRCODE_SUBSTRING_ERROR),
1081 : : errmsg("negative substring length not allowed")));
1082 : : e1 = -1; /* silence stupider compilers */
1083 : : }
1084 [ + + ]: 66 : else if (pg_add_s32_overflow(s, l, &e))
1085 : : {
1086 : : /*
1087 : : * L could be large enough for S + L to overflow, in which case the
1088 : : * substring must run to end of string.
1089 : : */
1090 : 6 : e1 = bitlen + 1;
1091 : : }
1092 : : else
1093 : : {
5211 1094 : 60 : e1 = Min(e, bitlen + 1);
1095 : : }
1096 [ + + - + ]: 99 : if (s1 > bitlen || e1 <= s1)
1097 : : {
1098 : : /* Need to return a zero-length bitstring */
8637 1099 : 27 : len = VARBITTOTALLEN(0);
1100 : 27 : result = (VarBit *) palloc(len);
6256 1101 : 27 : SET_VARSIZE(result, len);
8637 1102 : 27 : VARBITLEN(result) = 0;
1103 : : }
1104 : : else
1105 : : {
1106 : : /*
1107 : : * OK, we've got a true substring starting at position s1-1 and ending
1108 : : * at position e1-1
1109 : : */
8768 bruce@momjian.us 1110 : 72 : rbitlen = e1 - s1;
8637 tgl@sss.pgh.pa.us 1111 : 72 : len = VARBITTOTALLEN(rbitlen);
1112 : 72 : result = (VarBit *) palloc(len);
6256 1113 : 72 : SET_VARSIZE(result, len);
8637 1114 : 72 : VARBITLEN(result) = rbitlen;
8768 bruce@momjian.us 1115 : 72 : len -= VARHDRSZ + VARBITHDRSZ;
1116 : : /* Are we copying from a byte boundary? */
8632 tgl@sss.pgh.pa.us 1117 [ + + ]: 72 : if ((s1 - 1) % BITS_PER_BYTE == 0)
1118 : : {
1119 : : /* Yep, we are copying bytes */
1120 : 21 : memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE,
1121 : : len);
1122 : : }
1123 : : else
1124 : : {
1125 : : /* Figure out how much we need to shift the sequence by */
1126 : 51 : ishift = (s1 - 1) % BITS_PER_BYTE;
8768 bruce@momjian.us 1127 : 51 : r = VARBITS(result);
8632 tgl@sss.pgh.pa.us 1128 : 51 : ps = VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE;
8768 bruce@momjian.us 1129 [ + + ]: 102 : for (i = 0; i < len; i++)
1130 : : {
1131 : 51 : *r = (*ps << ishift) & BITMASK;
1132 [ + + ]: 51 : if ((++ps) < VARBITEND(arg))
8632 tgl@sss.pgh.pa.us 1133 : 39 : *r |= *ps >> (BITS_PER_BYTE - ishift);
8768 bruce@momjian.us 1134 : 51 : r++;
1135 : : }
1136 : : }
1137 : :
1138 : : /* Make sure last byte is correctly zero-padded */
1666 tgl@sss.pgh.pa.us 1139 [ + - - + : 72 : VARBIT_PAD(result);
+ + ]
1140 : : }
1141 : :
5211 1142 : 99 : return result;
1143 : : }
1144 : :
1145 : : /*
1146 : : * bitoverlay
1147 : : * Replace specified substring of first string with second
1148 : : *
1149 : : * The SQL standard defines OVERLAY() in terms of substring and concatenation.
1150 : : * This code is a direct implementation of what the standard says.
1151 : : */
1152 : : Datum
5193 1153 : 3 : bitoverlay(PG_FUNCTION_ARGS)
1154 : : {
1155 : 3 : VarBit *t1 = PG_GETARG_VARBIT_P(0);
1156 : 3 : VarBit *t2 = PG_GETARG_VARBIT_P(1);
2489 1157 : 3 : int sp = PG_GETARG_INT32(2); /* substring start position */
1158 : 3 : int sl = PG_GETARG_INT32(3); /* substring length */
1159 : :
5193 1160 : 3 : PG_RETURN_VARBIT_P(bit_overlay(t1, t2, sp, sl));
1161 : : }
1162 : :
1163 : : Datum
1164 : 9 : bitoverlay_no_len(PG_FUNCTION_ARGS)
1165 : : {
1166 : 9 : VarBit *t1 = PG_GETARG_VARBIT_P(0);
1167 : 9 : VarBit *t2 = PG_GETARG_VARBIT_P(1);
2489 1168 : 9 : int sp = PG_GETARG_INT32(2); /* substring start position */
1169 : : int sl;
1170 : :
5161 bruce@momjian.us 1171 : 9 : sl = VARBITLEN(t2); /* defaults to length(t2) */
5193 tgl@sss.pgh.pa.us 1172 : 9 : PG_RETURN_VARBIT_P(bit_overlay(t1, t2, sp, sl));
1173 : : }
1174 : :
1175 : : static VarBit *
1176 : 12 : bit_overlay(VarBit *t1, VarBit *t2, int sp, int sl)
1177 : : {
1178 : : VarBit *result;
1179 : : VarBit *s1;
1180 : : VarBit *s2;
1181 : : int sp_pl_sl;
1182 : :
1183 : : /*
1184 : : * Check for possible integer-overflow cases. For negative sp, throw a
1185 : : * "substring length" error because that's what should be expected
1186 : : * according to the spec's definition of OVERLAY().
1187 : : */
1188 [ - + ]: 12 : if (sp <= 0)
5193 tgl@sss.pgh.pa.us 1189 [ # # ]:UBC 0 : ereport(ERROR,
1190 : : (errcode(ERRCODE_SUBSTRING_ERROR),
1191 : : errmsg("negative substring length not allowed")));
2315 andres@anarazel.de 1192 [ - + ]:CBC 12 : if (pg_add_s32_overflow(sp, sl, &sp_pl_sl))
5193 tgl@sss.pgh.pa.us 1193 [ # # ]:UBC 0 : ereport(ERROR,
1194 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1195 : : errmsg("integer out of range")));
1196 : :
5161 bruce@momjian.us 1197 :CBC 12 : s1 = bitsubstring(t1, 1, sp - 1, false);
5193 tgl@sss.pgh.pa.us 1198 : 12 : s2 = bitsubstring(t1, sp_pl_sl, -1, true);
1199 : 12 : result = bit_catenate(s1, t2);
1200 : 12 : result = bit_catenate(result, s2);
1201 : :
1202 : 12 : return result;
1203 : : }
1204 : :
1205 : : /*
1206 : : * bit_count
1207 : : *
1208 : : * Returns the number of bits set in a bit string.
1209 : : */
1210 : : Datum
1118 peter@eisentraut.org 1211 : 18 : bit_bit_count(PG_FUNCTION_ARGS)
1212 : : {
1213 : 18 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1214 : :
1215 : 18 : PG_RETURN_INT64(pg_popcount((char *) VARBITS(arg), VARBITBYTES(arg)));
1216 : : }
1217 : :
1218 : : /*
1219 : : * bitlength, bitoctetlength
1220 : : * Return the length of a bit string
1221 : : */
1222 : : Datum
8637 tgl@sss.pgh.pa.us 1223 : 21 : bitlength(PG_FUNCTION_ARGS)
1224 : : {
1225 : 21 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1226 : :
1227 : 21 : PG_RETURN_INT32(VARBITLEN(arg));
1228 : : }
1229 : :
1230 : : Datum
8637 tgl@sss.pgh.pa.us 1231 :UBC 0 : bitoctetlength(PG_FUNCTION_ARGS)
1232 : : {
1233 : 0 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1234 : :
1235 : 0 : PG_RETURN_INT32(VARBITBYTES(arg));
1236 : : }
1237 : :
1238 : : /*
1239 : : * bit_and
1240 : : * perform a logical AND on two bit strings.
1241 : : */
1242 : : Datum
4857 tgl@sss.pgh.pa.us 1243 :CBC 82 : bit_and(PG_FUNCTION_ARGS)
1244 : : {
8637 1245 : 82 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
1246 : 82 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
1247 : : VarBit *result;
1248 : : int len,
1249 : : bitlen1,
1250 : : bitlen2,
1251 : : i;
1252 : : bits8 *p1,
1253 : : *p2,
1254 : : *r;
1255 : :
1256 : 82 : bitlen1 = VARBITLEN(arg1);
1257 : 82 : bitlen2 = VARBITLEN(arg2);
1258 [ + + ]: 82 : if (bitlen1 != bitlen2)
7567 1259 [ + - ]: 3 : ereport(ERROR,
1260 : : (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
1261 : : errmsg("cannot AND bit strings of different sizes")));
1262 : :
8637 1263 : 79 : len = VARSIZE(arg1);
1264 : 79 : result = (VarBit *) palloc(len);
6256 1265 : 79 : SET_VARSIZE(result, len);
8637 1266 : 79 : VARBITLEN(result) = bitlen1;
1267 : :
1268 : 79 : p1 = VARBITS(arg1);
1269 : 79 : p2 = VARBITS(arg2);
1270 : 79 : r = VARBITS(result);
1271 [ + + ]: 239 : for (i = 0; i < VARBITBYTES(arg1); i++)
8768 bruce@momjian.us 1272 : 160 : *r++ = *p1++ & *p2++;
1273 : :
1274 : : /* Padding is not needed as & of 0 pads is 0 */
1275 : :
8637 tgl@sss.pgh.pa.us 1276 : 79 : PG_RETURN_VARBIT_P(result);
1277 : : }
1278 : :
1279 : : /*
1280 : : * bit_or
1281 : : * perform a logical OR on two bit strings.
1282 : : */
1283 : : Datum
4857 1284 : 84 : bit_or(PG_FUNCTION_ARGS)
1285 : : {
8637 1286 : 84 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
1287 : 84 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
1288 : : VarBit *result;
1289 : : int len,
1290 : : bitlen1,
1291 : : bitlen2,
1292 : : i;
1293 : : bits8 *p1,
1294 : : *p2,
1295 : : *r;
1296 : :
1297 : 84 : bitlen1 = VARBITLEN(arg1);
1298 : 84 : bitlen2 = VARBITLEN(arg2);
1299 [ + + ]: 84 : if (bitlen1 != bitlen2)
7567 1300 [ + - ]: 3 : ereport(ERROR,
1301 : : (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
1302 : : errmsg("cannot OR bit strings of different sizes")));
8637 1303 : 81 : len = VARSIZE(arg1);
1304 : 81 : result = (VarBit *) palloc(len);
6256 1305 : 81 : SET_VARSIZE(result, len);
8637 1306 : 81 : VARBITLEN(result) = bitlen1;
1307 : :
1308 : 81 : p1 = VARBITS(arg1);
1309 : 81 : p2 = VARBITS(arg2);
1310 : 81 : r = VARBITS(result);
1311 [ + + ]: 237 : for (i = 0; i < VARBITBYTES(arg1); i++)
8768 bruce@momjian.us 1312 : 156 : *r++ = *p1++ | *p2++;
1313 : :
1314 : : /* Padding is not needed as | of 0 pads is 0 */
1315 : :
8637 tgl@sss.pgh.pa.us 1316 : 81 : PG_RETURN_VARBIT_P(result);
1317 : : }
1318 : :
1319 : : /*
1320 : : * bitxor
1321 : : * perform a logical XOR on two bit strings.
1322 : : */
1323 : : Datum
1324 : 69 : bitxor(PG_FUNCTION_ARGS)
1325 : : {
1326 : 69 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
1327 : 69 : VarBit *arg2 = PG_GETARG_VARBIT_P(1);
1328 : : VarBit *result;
1329 : : int len,
1330 : : bitlen1,
1331 : : bitlen2,
1332 : : i;
1333 : : bits8 *p1,
1334 : : *p2,
1335 : : *r;
1336 : :
1337 : 69 : bitlen1 = VARBITLEN(arg1);
1338 : 69 : bitlen2 = VARBITLEN(arg2);
1339 [ + + ]: 69 : if (bitlen1 != bitlen2)
7567 1340 [ + - ]: 3 : ereport(ERROR,
1341 : : (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
1342 : : errmsg("cannot XOR bit strings of different sizes")));
1343 : :
8637 1344 : 66 : len = VARSIZE(arg1);
1345 : 66 : result = (VarBit *) palloc(len);
6256 1346 : 66 : SET_VARSIZE(result, len);
8637 1347 : 66 : VARBITLEN(result) = bitlen1;
1348 : :
1349 : 66 : p1 = VARBITS(arg1);
1350 : 66 : p2 = VARBITS(arg2);
1351 : 66 : r = VARBITS(result);
1352 [ + + ]: 177 : for (i = 0; i < VARBITBYTES(arg1); i++)
8768 bruce@momjian.us 1353 : 111 : *r++ = *p1++ ^ *p2++;
1354 : :
1355 : : /* Padding is not needed as ^ of 0 pads is 0 */
1356 : :
8637 tgl@sss.pgh.pa.us 1357 : 66 : PG_RETURN_VARBIT_P(result);
1358 : : }
1359 : :
1360 : : /*
1361 : : * bitnot
1362 : : * perform a logical NOT on a bit string.
1363 : : */
1364 : : Datum
1365 : 60 : bitnot(PG_FUNCTION_ARGS)
1366 : : {
1367 : 60 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1368 : : VarBit *result;
1369 : : bits8 *p,
1370 : : *r;
1371 : :
1372 : 60 : result = (VarBit *) palloc(VARSIZE(arg));
6256 1373 : 60 : SET_VARSIZE(result, VARSIZE(arg));
8768 bruce@momjian.us 1374 : 60 : VARBITLEN(result) = VARBITLEN(arg);
1375 : :
8637 tgl@sss.pgh.pa.us 1376 : 60 : p = VARBITS(arg);
1377 : 60 : r = VARBITS(result);
1378 [ + + ]: 165 : for (; p < VARBITEND(arg); p++)
8424 bruce@momjian.us 1379 : 105 : *r++ = ~*p;
1380 : :
1381 : : /* Must zero-pad the result, because extra bits are surely 1's here */
1666 tgl@sss.pgh.pa.us 1382 [ + - - + : 60 : VARBIT_PAD_LAST(result, r);
- + ]
1383 : :
8637 1384 : 60 : PG_RETURN_VARBIT_P(result);
1385 : : }
1386 : :
1387 : : /*
1388 : : * bitshiftleft
1389 : : * do a left shift (i.e. towards the beginning of the string)
1390 : : */
1391 : : Datum
1392 : 348 : bitshiftleft(PG_FUNCTION_ARGS)
1393 : : {
1394 : 348 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1395 : 348 : int32 shft = PG_GETARG_INT32(1);
1396 : : VarBit *result;
1397 : : int byte_shift,
1398 : : ishift,
1399 : : len;
1400 : : bits8 *p,
1401 : : *r;
1402 : :
1403 : : /* Negative shift is a shift to the right */
8768 bruce@momjian.us 1404 [ - + ]: 348 : if (shft < 0)
1405 : : {
1406 : : /* Prevent integer overflow in negation */
2739 tgl@sss.pgh.pa.us 1407 [ # # ]:UBC 0 : if (shft < -VARBITMAXLEN)
1408 : 0 : shft = -VARBITMAXLEN;
8637 1409 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
1410 : : VarBitPGetDatum(arg),
1411 : : Int32GetDatum(-shft)));
1412 : : }
1413 : :
8637 tgl@sss.pgh.pa.us 1414 :CBC 348 : result = (VarBit *) palloc(VARSIZE(arg));
6256 1415 : 348 : SET_VARSIZE(result, VARSIZE(arg));
8768 bruce@momjian.us 1416 : 348 : VARBITLEN(result) = VARBITLEN(arg);
8637 tgl@sss.pgh.pa.us 1417 : 348 : r = VARBITS(result);
1418 : :
1419 : : /* If we shifted all the bits out, return an all-zero string */
1420 [ + + ]: 348 : if (shft >= VARBITLEN(arg))
1421 : : {
7879 1422 [ + - - + : 12 : MemSet(r, 0, VARBITBYTES(arg));
- - - - -
- ]
8637 1423 : 12 : PG_RETURN_VARBIT_P(result);
1424 : : }
1425 : :
8632 1426 : 336 : byte_shift = shft / BITS_PER_BYTE;
1427 : 336 : ishift = shft % BITS_PER_BYTE;
8637 1428 : 336 : p = VARBITS(arg) + byte_shift;
1429 : :
8768 bruce@momjian.us 1430 [ + + ]: 336 : if (ishift == 0)
1431 : : {
1432 : : /* Special case: we can do a memcpy */
1433 : 132 : len = VARBITBYTES(arg) - byte_shift;
1434 : 132 : memcpy(r, p, len);
7879 tgl@sss.pgh.pa.us 1435 [ - + - - : 132 : MemSet(r + len, 0, byte_shift);
- - - - -
- ]
1436 : : }
1437 : : else
1438 : : {
8768 bruce@momjian.us 1439 [ + + ]: 597 : for (; p < VARBITEND(arg); r++)
1440 : : {
1441 : 393 : *r = *p << ishift;
1442 [ + + ]: 393 : if ((++p) < VARBITEND(arg))
8632 tgl@sss.pgh.pa.us 1443 : 189 : *r |= *p >> (BITS_PER_BYTE - ishift);
1444 : : }
8768 bruce@momjian.us 1445 [ - + ]: 204 : for (; r < VARBITEND(result); r++)
8637 tgl@sss.pgh.pa.us 1446 :UBC 0 : *r = 0;
1447 : : }
1448 : :
1449 : : /* The pad bits should be already zero at this point */
1450 : :
8637 tgl@sss.pgh.pa.us 1451 :CBC 336 : PG_RETURN_VARBIT_P(result);
1452 : : }
1453 : :
1454 : : /*
1455 : : * bitshiftright
1456 : : * do a right shift (i.e. towards the end of the string)
1457 : : */
1458 : : Datum
1459 : 438 : bitshiftright(PG_FUNCTION_ARGS)
1460 : : {
1461 : 438 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1462 : 438 : int32 shft = PG_GETARG_INT32(1);
1463 : : VarBit *result;
1464 : : int byte_shift,
1465 : : ishift,
1466 : : len;
1467 : : bits8 *p,
1468 : : *r;
1469 : :
1470 : : /* Negative shift is a shift to the left */
8768 bruce@momjian.us 1471 [ - + ]: 438 : if (shft < 0)
1472 : : {
1473 : : /* Prevent integer overflow in negation */
2739 tgl@sss.pgh.pa.us 1474 [ # # ]:UBC 0 : if (shft < -VARBITMAXLEN)
1475 : 0 : shft = -VARBITMAXLEN;
8637 1476 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
1477 : : VarBitPGetDatum(arg),
1478 : : Int32GetDatum(-shft)));
1479 : : }
1480 : :
8637 tgl@sss.pgh.pa.us 1481 :CBC 438 : result = (VarBit *) palloc(VARSIZE(arg));
6256 1482 : 438 : SET_VARSIZE(result, VARSIZE(arg));
8768 bruce@momjian.us 1483 : 438 : VARBITLEN(result) = VARBITLEN(arg);
8637 tgl@sss.pgh.pa.us 1484 : 438 : r = VARBITS(result);
1485 : :
1486 : : /* If we shifted all the bits out, return an all-zero string */
1487 [ + + ]: 438 : if (shft >= VARBITLEN(arg))
1488 : : {
7879 1489 [ + - - + : 12 : MemSet(r, 0, VARBITBYTES(arg));
- - - - -
- ]
8637 1490 : 12 : PG_RETURN_VARBIT_P(result);
1491 : : }
1492 : :
8632 1493 : 426 : byte_shift = shft / BITS_PER_BYTE;
1494 : 426 : ishift = shft % BITS_PER_BYTE;
8637 1495 : 426 : p = VARBITS(arg);
1496 : :
1497 : : /* Set the first part of the result to 0 */
7879 1498 [ + - + + : 426 : MemSet(r, 0, byte_shift);
+ - + - -
+ ]
8637 1499 : 426 : r += byte_shift;
1500 : :
8768 bruce@momjian.us 1501 [ + + ]: 426 : if (ishift == 0)
1502 : : {
1503 : : /* Special case: we can do a memcpy */
1504 : 180 : len = VARBITBYTES(arg) - byte_shift;
8637 tgl@sss.pgh.pa.us 1505 : 180 : memcpy(r, p, len);
1654 1506 : 180 : r += len;
1507 : : }
1508 : : else
1509 : : {
8637 1510 [ + - ]: 246 : if (r < VARBITEND(result))
1511 : 246 : *r = 0; /* initialize first byte */
8768 bruce@momjian.us 1512 [ + + ]: 714 : for (; r < VARBITEND(result); p++)
1513 : : {
1514 : 468 : *r |= *p >> ishift;
1515 [ + + ]: 468 : if ((++r) < VARBITEND(result))
8632 tgl@sss.pgh.pa.us 1516 : 222 : *r = (*p << (BITS_PER_BYTE - ishift)) & BITMASK;
1517 : : }
1518 : : }
1519 : :
1520 : : /* We may have shifted 1's into the pad bits, so fix that */
1654 1521 [ + - - + : 426 : VARBIT_PAD_LAST(result, r);
+ + ]
1522 : :
8637 1523 : 426 : PG_RETURN_VARBIT_P(result);
1524 : : }
1525 : :
1526 : : /*
1527 : : * This is not defined in any standard. We retain the natural ordering of
1528 : : * bits here, as it just seems more intuitive.
1529 : : */
1530 : : Datum
1531 : 1505 : bitfromint4(PG_FUNCTION_ARGS)
1532 : : {
1533 : 1505 : int32 a = PG_GETARG_INT32(0);
7242 1534 : 1505 : int32 typmod = PG_GETARG_INT32(1);
1535 : : VarBit *result;
1536 : : bits8 *r;
1537 : : int rlen;
1538 : : int destbitsleft,
1539 : : srcbitsleft;
1540 : :
2739 1541 [ + - - + ]: 1505 : if (typmod <= 0 || typmod > VARBITMAXLEN)
7242 tgl@sss.pgh.pa.us 1542 :UBC 0 : typmod = 1; /* default bit length */
1543 : :
7242 tgl@sss.pgh.pa.us 1544 :CBC 1505 : rlen = VARBITTOTALLEN(typmod);
1545 : 1505 : result = (VarBit *) palloc(rlen);
6256 1546 : 1505 : SET_VARSIZE(result, rlen);
7242 1547 : 1505 : VARBITLEN(result) = typmod;
1548 : :
8637 1549 : 1505 : r = VARBITS(result);
7242 1550 : 1505 : destbitsleft = typmod;
1551 : 1505 : srcbitsleft = 32;
1552 : : /* drop any input bits that don't fit */
1553 : 1505 : srcbitsleft = Min(srcbitsleft, destbitsleft);
1554 : : /* sign-fill any excess bytes in output */
1555 [ - + ]: 1505 : while (destbitsleft >= srcbitsleft + 8)
1556 : : {
7242 tgl@sss.pgh.pa.us 1557 [ # # ]:UBC 0 : *r++ = (bits8) ((a < 0) ? BITMASK : 0);
1558 : 0 : destbitsleft -= 8;
1559 : : }
1560 : : /* store first fractional byte */
7242 tgl@sss.pgh.pa.us 1561 [ - + ]:CBC 1505 : if (destbitsleft > srcbitsleft)
1562 : : {
2128 tgl@sss.pgh.pa.us 1563 :UBC 0 : unsigned int val = (unsigned int) (a >> (destbitsleft - 8));
1564 : :
1565 : : /* Force sign-fill in case the compiler implements >> as zero-fill */
5237 1566 [ # # ]: 0 : if (a < 0)
2128 1567 : 0 : val |= ((unsigned int) -1) << (srcbitsleft + 8 - destbitsleft);
5237 1568 : 0 : *r++ = (bits8) (val & BITMASK);
7242 1569 : 0 : destbitsleft -= 8;
1570 : : }
1571 : : /* Now srcbitsleft and destbitsleft are the same, need not track both */
1572 : : /* store whole bytes */
7242 tgl@sss.pgh.pa.us 1573 [ + + ]:CBC 5875 : while (destbitsleft >= 8)
1574 : : {
1575 : 4370 : *r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
1576 : 4370 : destbitsleft -= 8;
1577 : : }
1578 : : /* store last fractional byte */
1579 [ + + ]: 1505 : if (destbitsleft > 0)
1580 : 330 : *r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);
1581 : :
8637 1582 : 1505 : PG_RETURN_VARBIT_P(result);
1583 : : }
1584 : :
1585 : : Datum
1586 : 943 : bittoint4(PG_FUNCTION_ARGS)
1587 : : {
1588 : 943 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1589 : : uint32 result;
1590 : : bits8 *r;
1591 : :
1592 : : /* Check that the bit string is not too long */
7242 1593 [ - + ]: 943 : if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
7567 tgl@sss.pgh.pa.us 1594 [ # # ]:UBC 0 : ereport(ERROR,
1595 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1596 : : errmsg("integer out of range")));
1597 : :
8637 tgl@sss.pgh.pa.us 1598 :CBC 943 : result = 0;
1599 [ + + ]: 4610 : for (r = VARBITS(arg); r < VARBITEND(arg); r++)
1600 : : {
8632 1601 : 3667 : result <<= BITS_PER_BYTE;
8637 1602 : 3667 : result |= *r;
1603 : : }
1604 : : /* Now shift the result to take account of the padding at the end */
1605 : 943 : result >>= VARBITPAD(arg);
1606 : :
1607 : 943 : PG_RETURN_INT32(result);
1608 : : }
1609 : :
1610 : : Datum
7924 lockhart@fourpalms.o 1611 : 848 : bitfromint8(PG_FUNCTION_ARGS)
1612 : : {
1613 : 848 : int64 a = PG_GETARG_INT64(0);
7242 tgl@sss.pgh.pa.us 1614 : 848 : int32 typmod = PG_GETARG_INT32(1);
1615 : : VarBit *result;
1616 : : bits8 *r;
1617 : : int rlen;
1618 : : int destbitsleft,
1619 : : srcbitsleft;
1620 : :
2739 1621 [ + - - + ]: 848 : if (typmod <= 0 || typmod > VARBITMAXLEN)
7242 tgl@sss.pgh.pa.us 1622 :UBC 0 : typmod = 1; /* default bit length */
1623 : :
7242 tgl@sss.pgh.pa.us 1624 :CBC 848 : rlen = VARBITTOTALLEN(typmod);
1625 : 848 : result = (VarBit *) palloc(rlen);
6256 1626 : 848 : SET_VARSIZE(result, rlen);
7242 1627 : 848 : VARBITLEN(result) = typmod;
1628 : :
1629 : 848 : r = VARBITS(result);
1630 : 848 : destbitsleft = typmod;
1631 : 848 : srcbitsleft = 64;
1632 : : /* drop any input bits that don't fit */
1633 : 848 : srcbitsleft = Min(srcbitsleft, destbitsleft);
1634 : : /* sign-fill any excess bytes in output */
1635 [ - + ]: 848 : while (destbitsleft >= srcbitsleft + 8)
1636 : : {
7242 tgl@sss.pgh.pa.us 1637 [ # # ]:UBC 0 : *r++ = (bits8) ((a < 0) ? BITMASK : 0);
1638 : 0 : destbitsleft -= 8;
1639 : : }
1640 : : /* store first fractional byte */
7242 tgl@sss.pgh.pa.us 1641 [ - + ]:CBC 848 : if (destbitsleft > srcbitsleft)
1642 : : {
2128 tgl@sss.pgh.pa.us 1643 :UBC 0 : unsigned int val = (unsigned int) (a >> (destbitsleft - 8));
1644 : :
1645 : : /* Force sign-fill in case the compiler implements >> as zero-fill */
5237 1646 [ # # ]: 0 : if (a < 0)
2128 1647 : 0 : val |= ((unsigned int) -1) << (srcbitsleft + 8 - destbitsleft);
5237 1648 : 0 : *r++ = (bits8) (val & BITMASK);
7242 1649 : 0 : destbitsleft -= 8;
1650 : : }
1651 : : /* Now srcbitsleft and destbitsleft are the same, need not track both */
1652 : : /* store whole bytes */
7242 tgl@sss.pgh.pa.us 1653 [ + + ]:CBC 4240 : while (destbitsleft >= 8)
1654 : : {
1655 : 3392 : *r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
1656 : 3392 : destbitsleft -= 8;
1657 : : }
1658 : : /* store last fractional byte */
1659 [ - + ]: 848 : if (destbitsleft > 0)
7242 tgl@sss.pgh.pa.us 1660 :UBC 0 : *r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);
1661 : :
7242 tgl@sss.pgh.pa.us 1662 :CBC 848 : PG_RETURN_VARBIT_P(result);
1663 : : }
1664 : :
1665 : : Datum
7924 lockhart@fourpalms.o 1666 : 685 : bittoint8(PG_FUNCTION_ARGS)
1667 : : {
1668 : 685 : VarBit *arg = PG_GETARG_VARBIT_P(0);
1669 : : uint64 result;
1670 : : bits8 *r;
1671 : :
1672 : : /* Check that the bit string is not too long */
1673 [ - + ]: 685 : if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
7567 tgl@sss.pgh.pa.us 1674 [ # # ]:UBC 0 : ereport(ERROR,
1675 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1676 : : errmsg("bigint out of range")));
1677 : :
7924 lockhart@fourpalms.o 1678 :CBC 685 : result = 0;
1679 [ + + ]: 6165 : for (r = VARBITS(arg); r < VARBITEND(arg); r++)
1680 : : {
1681 : 5480 : result <<= BITS_PER_BYTE;
1682 : 5480 : result |= *r;
1683 : : }
1684 : : /* Now shift the result to take account of the padding at the end */
1685 : 685 : result >>= VARBITPAD(arg);
1686 : :
1687 : 685 : PG_RETURN_INT64(result);
1688 : : }
1689 : :
1690 : :
1691 : : /*
1692 : : * Determines the position of S2 in the bitstring S1 (1-based string).
1693 : : * If S2 does not appear in S1 this function returns 0.
1694 : : * If S2 is of length 0 this function returns 1.
1695 : : * Compatible in usage with POSITION() functions for other data types.
1696 : : */
1697 : : Datum
8566 peter_e@gmx.net 1698 : 306 : bitposition(PG_FUNCTION_ARGS)
1699 : : {
7924 lockhart@fourpalms.o 1700 : 306 : VarBit *str = PG_GETARG_VARBIT_P(0);
8424 bruce@momjian.us 1701 : 306 : VarBit *substr = PG_GETARG_VARBIT_P(1);
1702 : : int substr_length,
1703 : : str_length,
1704 : : i,
1705 : : is;
1706 : : bits8 *s, /* pointer into substring */
1707 : : *p; /* pointer into str */
1708 : : bits8 cmp, /* shifted substring byte to compare */
1709 : : mask1, /* mask for substring byte shifted right */
1710 : : mask2, /* mask for substring byte shifted left */
1711 : : end_mask, /* pad mask for last substring byte */
1712 : : str_mask; /* pad mask for last string byte */
1713 : : bool is_match;
1714 : :
1715 : : /* Get the substring length */
8566 peter_e@gmx.net 1716 : 306 : substr_length = VARBITLEN(substr);
7924 lockhart@fourpalms.o 1717 : 306 : str_length = VARBITLEN(str);
1718 : :
1719 : : /* String has zero length or substring longer than string, return 0 */
1720 [ + + + + ]: 306 : if ((str_length == 0) || (substr_length > str_length))
8424 bruce@momjian.us 1721 : 12 : PG_RETURN_INT32(0);
1722 : :
1723 : : /* zero-length substring means return 1 */
8566 peter_e@gmx.net 1724 [ + + ]: 294 : if (substr_length == 0)
1725 : 3 : PG_RETURN_INT32(1);
1726 : :
1727 : : /* Initialise the padding masks */
1728 : 291 : end_mask = BITMASK << VARBITPAD(substr);
7924 lockhart@fourpalms.o 1729 : 291 : str_mask = BITMASK << VARBITPAD(str);
1730 [ + + ]: 468 : for (i = 0; i < VARBITBYTES(str) - VARBITBYTES(substr) + 1; i++)
1731 : : {
8424 bruce@momjian.us 1732 [ + + ]: 2568 : for (is = 0; is < BITS_PER_BYTE; is++)
1733 : : {
8566 peter_e@gmx.net 1734 : 2391 : is_match = true;
7924 lockhart@fourpalms.o 1735 : 2391 : p = VARBITS(str) + i;
8566 peter_e@gmx.net 1736 : 2391 : mask1 = BITMASK >> is;
1737 : 2391 : mask2 = ~mask1;
8424 bruce@momjian.us 1738 : 2391 : for (s = VARBITS(substr);
1739 [ + + + + ]: 2670 : is_match && s < VARBITEND(substr); s++)
1740 : : {
8566 peter_e@gmx.net 1741 : 2496 : cmp = *s >> is;
8424 bruce@momjian.us 1742 [ + + ]: 2496 : if (s == VARBITEND(substr) - 1)
1743 : : {
8566 peter_e@gmx.net 1744 : 1887 : mask1 &= end_mask >> is;
7924 lockhart@fourpalms.o 1745 [ + + ]: 1887 : if (p == VARBITEND(str) - 1)
1746 : : {
1747 : : /* Check that there is enough of str left */
1748 [ + + ]: 495 : if (mask1 & ~str_mask)
1749 : : {
8566 peter_e@gmx.net 1750 : 30 : is_match = false;
1751 : 30 : break;
1752 : : }
7924 lockhart@fourpalms.o 1753 : 465 : mask1 &= str_mask;
1754 : : }
1755 : : }
8566 peter_e@gmx.net 1756 : 2466 : is_match = ((cmp ^ *p) & mask1) == 0;
1757 [ + + ]: 2466 : if (!is_match)
1758 : 2025 : break;
1759 : : /* Move on to the next byte */
1760 : 441 : p++;
7924 lockhart@fourpalms.o 1761 [ + + ]: 441 : if (p == VARBITEND(str))
1762 : : {
8566 peter_e@gmx.net 1763 : 162 : mask2 = end_mask << (BITS_PER_BYTE - is);
1764 : 162 : is_match = mask2 == 0;
1765 : : #if 0
1766 : : elog(DEBUG4, "S. %d %d em=%2x sm=%2x r=%d",
1767 : : i, is, end_mask, mask2, is_match);
1768 : : #endif
1769 : 162 : break;
1770 : : }
1771 : 279 : cmp = *s << (BITS_PER_BYTE - is);
8424 bruce@momjian.us 1772 [ + + ]: 279 : if (s == VARBITEND(substr) - 1)
1773 : : {
8566 peter_e@gmx.net 1774 : 117 : mask2 &= end_mask << (BITS_PER_BYTE - is);
7924 lockhart@fourpalms.o 1775 [ + + ]: 117 : if (p == VARBITEND(str) - 1)
1776 : : {
1777 [ - + ]: 114 : if (mask2 & ~str_mask)
1778 : : {
8566 peter_e@gmx.net 1779 :UBC 0 : is_match = false;
1780 : 0 : break;
1781 : : }
7924 lockhart@fourpalms.o 1782 :CBC 114 : mask2 &= str_mask;
1783 : : }
1784 : : }
8566 peter_e@gmx.net 1785 : 279 : is_match = ((cmp ^ *p) & mask2) == 0;
1786 : : }
1787 : : /* Have we found a match? */
1788 [ + + ]: 2391 : if (is_match)
8424 bruce@momjian.us 1789 : 243 : PG_RETURN_INT32(i * BITS_PER_BYTE + is + 1);
1790 : : }
1791 : : }
8566 peter_e@gmx.net 1792 : 48 : PG_RETURN_INT32(0);
1793 : : }
1794 : :
1795 : :
1796 : : /*
1797 : : * bitsetbit
1798 : : *
1799 : : * Given an instance of type 'bit' creates a new one with
1800 : : * the Nth bit set to the given value.
1801 : : *
1802 : : * The bit location is specified left-to-right in a zero-based fashion
1803 : : * consistent with the other get_bit and set_bit functions, but
1804 : : * inconsistent with the standard substring, position, overlay functions
1805 : : */
1806 : : Datum
5193 tgl@sss.pgh.pa.us 1807 : 6 : bitsetbit(PG_FUNCTION_ARGS)
1808 : : {
1809 : 6 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
1810 : 6 : int32 n = PG_GETARG_INT32(1);
1811 : 6 : int32 newBit = PG_GETARG_INT32(2);
1812 : : VarBit *result;
1813 : : int len,
1814 : : bitlen;
1815 : : bits8 *r,
1816 : : *p;
1817 : : int byteNo,
1818 : : bitNo;
1819 : :
1820 : 6 : bitlen = VARBITLEN(arg1);
1821 [ + - + + ]: 6 : if (n < 0 || n >= bitlen)
1822 [ + - ]: 3 : ereport(ERROR,
1823 : : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1824 : : errmsg("bit index %d out of valid range (0..%d)",
1825 : : n, bitlen - 1)));
1826 : :
1827 : : /*
1828 : : * sanity check!
1829 : : */
1830 [ + - - + ]: 3 : if (newBit != 0 && newBit != 1)
5193 tgl@sss.pgh.pa.us 1831 [ # # ]:UBC 0 : ereport(ERROR,
1832 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1833 : : errmsg("new bit must be 0 or 1")));
1834 : :
5193 tgl@sss.pgh.pa.us 1835 :CBC 3 : len = VARSIZE(arg1);
1836 : 3 : result = (VarBit *) palloc(len);
1837 : 3 : SET_VARSIZE(result, len);
1838 : 3 : VARBITLEN(result) = bitlen;
1839 : :
1840 : 3 : p = VARBITS(arg1);
1841 : 3 : r = VARBITS(result);
1842 : :
1843 : 3 : memcpy(r, p, VARBITBYTES(arg1));
1844 : :
1845 : 3 : byteNo = n / BITS_PER_BYTE;
1846 : 3 : bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE);
1847 : :
1848 : : /*
1849 : : * Update the byte.
1850 : : */
1851 [ - + ]: 3 : if (newBit == 0)
5193 tgl@sss.pgh.pa.us 1852 :UBC 0 : r[byteNo] &= (~(1 << bitNo));
1853 : : else
5193 tgl@sss.pgh.pa.us 1854 :CBC 3 : r[byteNo] |= (1 << bitNo);
1855 : :
1856 : 3 : PG_RETURN_VARBIT_P(result);
1857 : : }
1858 : :
1859 : : /*
1860 : : * bitgetbit
1861 : : *
1862 : : * returns the value of the Nth bit of a bit array (0 or 1).
1863 : : *
1864 : : * The bit location is specified left-to-right in a zero-based fashion
1865 : : * consistent with the other get_bit and set_bit functions, but
1866 : : * inconsistent with the standard substring, position, overlay functions
1867 : : */
1868 : : Datum
1869 : 3 : bitgetbit(PG_FUNCTION_ARGS)
1870 : : {
1871 : 3 : VarBit *arg1 = PG_GETARG_VARBIT_P(0);
1872 : 3 : int32 n = PG_GETARG_INT32(1);
1873 : : int bitlen;
1874 : : bits8 *p;
1875 : : int byteNo,
1876 : : bitNo;
1877 : :
1878 : 3 : bitlen = VARBITLEN(arg1);
1879 [ + - - + ]: 3 : if (n < 0 || n >= bitlen)
5193 tgl@sss.pgh.pa.us 1880 [ # # ]:UBC 0 : ereport(ERROR,
1881 : : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1882 : : errmsg("bit index %d out of valid range (0..%d)",
1883 : : n, bitlen - 1)));
1884 : :
5193 tgl@sss.pgh.pa.us 1885 :CBC 3 : p = VARBITS(arg1);
1886 : :
1887 : 3 : byteNo = n / BITS_PER_BYTE;
1888 : 3 : bitNo = BITS_PER_BYTE - 1 - (n % BITS_PER_BYTE);
1889 : :
1890 [ + - ]: 3 : if (p[byteNo] & (1 << bitNo))
1891 : 3 : PG_RETURN_INT32(1);
1892 : : else
5193 tgl@sss.pgh.pa.us 1893 :UBC 0 : PG_RETURN_INT32(0);
1894 : : }
|