~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/varbit.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * varbit.c
 
4
 *        Functions for the SQL datatypes BIT() and BIT VARYING().
 
5
 *
 
6
 * Code originally contributed by Adriaan Joubert.
 
7
 *
 
8
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
9
 * Portions Copyright (c) 1994, Regents of the University of California
 
10
 *
 
11
 * IDENTIFICATION
 
12
 *        $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.44 2004-12-31 22:01:22 pgsql Exp $
 
13
 *
 
14
 *-------------------------------------------------------------------------
 
15
 */
 
16
 
 
17
#include "postgres.h"
 
18
 
 
19
#include "catalog/pg_type.h"
 
20
#include "libpq/pqformat.h"
 
21
#include "utils/array.h"
 
22
#include "utils/fmgroids.h"
 
23
#include "utils/memutils.h"
 
24
#include "utils/varbit.h"
 
25
 
 
26
#define HEXDIG(z)        ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
 
27
 
 
28
 
 
29
/*----------
 
30
 *      attypmod -- contains the length of the bit string in bits, or for
 
31
 *                         varying bits the maximum length.
 
32
 *
 
33
 *      The data structure contains the following elements:
 
34
 *        header  -- length of the whole data structure (incl header)
 
35
 *                               in bytes. (as with all varying length datatypes)
 
36
 *        data section -- private data section for the bits data structures
 
37
 *              bitlength -- length of the bit string in bits
 
38
 *              bitdata   -- bit string, most significant byte first
 
39
 *
 
40
 *      The length of the bitdata vector should always be exactly as many
 
41
 *      bytes as are needed for the given bitlength.  If the bitlength is
 
42
 *      not a multiple of 8, the extra low-order padding bits of the last
 
43
 *      byte must be zeroes.
 
44
 *----------
 
45
 */
 
46
 
 
47
/*
 
48
 * bit_in -
 
49
 *        converts a char string to the internal representation of a bitstring.
 
50
 *                The length is determined by the number of bits required plus
 
51
 *                VARHDRSZ bytes or from atttypmod.
 
52
 */
 
53
Datum
 
54
bit_in(PG_FUNCTION_ARGS)
 
55
{
 
56
        char       *input_string = PG_GETARG_CSTRING(0);
 
57
 
 
58
#ifdef NOT_USED
 
59
        Oid                     typelem = PG_GETARG_OID(1);
 
60
#endif
 
61
        int32           atttypmod = PG_GETARG_INT32(2);
 
62
        VarBit     *result;                     /* The resulting bit string                       */
 
63
        char       *sp;                         /* pointer into the character string  */
 
64
        bits8      *r;                          /* pointer into the result */
 
65
        int                     len,                    /* Length of the whole data structure */
 
66
                                bitlen,                 /* Number of bits in the bit string   */
 
67
                                slen;                   /* Length of the input string             */
 
68
        bool            bit_not_hex;    /* false = hex string  true = bit string */
 
69
        int                     bc;
 
70
        bits8           x = 0;
 
71
 
 
72
        /* Check that the first character is a b or an x */
 
73
        if (input_string[0] == 'b' || input_string[0] == 'B')
 
74
        {
 
75
                bit_not_hex = true;
 
76
                sp = input_string + 1;
 
77
        }
 
78
        else if (input_string[0] == 'x' || input_string[0] == 'X')
 
79
        {
 
80
                bit_not_hex = false;
 
81
                sp = input_string + 1;
 
82
        }
 
83
        else
 
84
        {
 
85
                /*
 
86
                 * Otherwise it's binary.  This allows things like cast('1001' as
 
87
                 * bit) to work transparently.
 
88
                 */
 
89
                bit_not_hex = true;
 
90
                sp = input_string;
 
91
        }
 
92
 
 
93
        slen = strlen(sp);
 
94
        /* Determine bitlength from input string */
 
95
        if (bit_not_hex)
 
96
                bitlen = slen;
 
97
        else
 
98
                bitlen = slen * 4;
 
99
 
 
100
        /*
 
101
         * Sometimes atttypmod is not supplied. If it is supplied we need to
 
102
         * make sure that the bitstring fits.
 
103
         */
 
104
        if (atttypmod <= 0)
 
105
                atttypmod = bitlen;
 
106
        else if (bitlen != atttypmod)
 
107
                ereport(ERROR,
 
108
                                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 
109
                           errmsg("bit string length %d does not match type bit(%d)",
 
110
                                          bitlen, atttypmod)));
 
111
 
 
112
        len = VARBITTOTALLEN(atttypmod);
 
113
        /* set to 0 so that *r is always initialised and string is zero-padded */
 
114
        result = (VarBit *) palloc0(len);
 
115
        VARATT_SIZEP(result) = len;
 
116
        VARBITLEN(result) = atttypmod;
 
117
 
 
118
        r = VARBITS(result);
 
119
        if (bit_not_hex)
 
120
        {
 
121
                /* Parse the bit representation of the string */
 
122
                /* We know it fits, as bitlen was compared to atttypmod */
 
123
                x = BITHIGH;
 
124
                for (; *sp; sp++)
 
125
                {
 
126
                        if (*sp == '1')
 
127
                                *r |= x;
 
128
                        else if (*sp != '0')
 
129
                                ereport(ERROR,
 
130
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
131
                                                 errmsg("\"%c\" is not a valid binary digit",
 
132
                                                                *sp)));
 
133
 
 
134
                        x >>= 1;
 
135
                        if (x == 0)
 
136
                        {
 
137
                                x = BITHIGH;
 
138
                                r++;
 
139
                        }
 
140
                }
 
141
        }
 
142
        else
 
143
        {
 
144
                /* Parse the hex representation of the string */
 
145
                for (bc = 0; *sp; sp++)
 
146
                {
 
147
                        if (*sp >= '0' && *sp <= '9')
 
148
                                x = (bits8) (*sp - '0');
 
149
                        else if (*sp >= 'A' && *sp <= 'F')
 
150
                                x = (bits8) (*sp - 'A') + 10;
 
151
                        else if (*sp >= 'a' && *sp <= 'f')
 
152
                                x = (bits8) (*sp - 'a') + 10;
 
153
                        else
 
154
                                ereport(ERROR,
 
155
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
156
                                                 errmsg("\"%c\" is not a valid hexadecimal digit",
 
157
                                                                *sp)));
 
158
 
 
159
                        if (bc)
 
160
                        {
 
161
                                *r++ |= x;
 
162
                                bc = 0;
 
163
                        }
 
164
                        else
 
165
                        {
 
166
                                *r = x << 4;
 
167
                                bc = 1;
 
168
                        }
 
169
                }
 
170
        }
 
171
 
 
172
        PG_RETURN_VARBIT_P(result);
 
173
}
 
174
 
 
175
 
 
176
Datum
 
177
bit_out(PG_FUNCTION_ARGS)
 
178
{
 
179
#if 1
 
180
        /* same as varbit output */
 
181
        return varbit_out(fcinfo);
 
182
#else
 
183
/* This is how one would print a hex string, in case someone wants to
 
184
   write a formatting function. */
 
185
        VarBit     *s = PG_GETARG_VARBIT_P(0);
 
186
        char       *result,
 
187
                           *r;
 
188
        bits8      *sp;
 
189
        int                     i,
 
190
                                len,
 
191
                                bitlen;
 
192
 
 
193
        bitlen = VARBITLEN(s);
 
194
        len = (bitlen + 3) / 4;
 
195
        result = (char *) palloc(len + 2);
 
196
        sp = VARBITS(s);
 
197
        r = result;
 
198
        *r++ = 'X';
 
199
        /* we cheat by knowing that we store full bytes zero padded */
 
200
        for (i = 0; i < len; i += 2, sp++)
 
201
        {
 
202
                *r++ = HEXDIG((*sp) >> 4);
 
203
                *r++ = HEXDIG((*sp) & 0xF);
 
204
        }
 
205
 
 
206
        /*
 
207
         * Go back one step if we printed a hex number that was not part of
 
208
         * the bitstring anymore
 
209
         */
 
210
        if (i > len)
 
211
                r--;
 
212
        *r = '\0';
 
213
 
 
214
        PG_RETURN_CSTRING(result);
 
215
#endif
 
216
}
 
217
 
 
218
/*
 
219
 *              bit_recv                        - converts external binary format to bit
 
220
 */
 
221
Datum
 
222
bit_recv(PG_FUNCTION_ARGS)
 
223
{
 
224
        /* Exactly the same as varbit_recv, so share code */
 
225
        return varbit_recv(fcinfo);
 
226
}
 
227
 
 
228
/*
 
229
 *              bit_send                        - converts bit to binary format
 
230
 */
 
231
Datum
 
232
bit_send(PG_FUNCTION_ARGS)
 
233
{
 
234
        /* Exactly the same as varbit_send, so share code */
 
235
        return varbit_send(fcinfo);
 
236
}
 
237
 
 
238
/* bit()
 
239
 * Converts a bit() type to a specific internal length.
 
240
 * len is the bitlength specified in the column definition.
 
241
 *
 
242
 * If doing implicit cast, raise error when source data is wrong length.
 
243
 * If doing explicit cast, silently truncate or zero-pad to specified length.
 
244
 */
 
245
Datum
 
246
bit(PG_FUNCTION_ARGS)
 
247
{
 
248
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
249
        int32           len = PG_GETARG_INT32(1);
 
250
        bool            isExplicit = PG_GETARG_BOOL(2);
 
251
        VarBit     *result;
 
252
        int                     rlen;
 
253
        int                     ipad;
 
254
        bits8           mask;
 
255
 
 
256
        /* No work if typmod is invalid or supplied data matches it already */
 
257
        if (len <= 0 || len == VARBITLEN(arg))
 
258
                PG_RETURN_VARBIT_P(arg);
 
259
 
 
260
        if (!isExplicit)
 
261
                ereport(ERROR,
 
262
                                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 
263
                           errmsg("bit string length %d does not match type bit(%d)",
 
264
                                          VARBITLEN(arg), len)));
 
265
 
 
266
        rlen = VARBITTOTALLEN(len);
 
267
        /* set to 0 so that string is zero-padded */
 
268
        result = (VarBit *) palloc0(rlen);
 
269
        VARATT_SIZEP(result) = rlen;
 
270
        VARBITLEN(result) = len;
 
271
 
 
272
        memcpy(VARBITS(result), VARBITS(arg),
 
273
                   Min(VARBITBYTES(result), VARBITBYTES(arg)));
 
274
 
 
275
        /*
 
276
         * Make sure last byte is zero-padded if needed.  This is useless but
 
277
         * safe if source data was shorter than target length (we assume the
 
278
         * last byte of the source data was itself correctly zero-padded).
 
279
         */
 
280
        ipad = VARBITPAD(result);
 
281
        if (ipad > 0)
 
282
        {
 
283
                mask = BITMASK << ipad;
 
284
                *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
 
285
        }
 
286
 
 
287
        PG_RETURN_VARBIT_P(result);
 
288
}
 
289
 
 
290
/*
 
291
 * varbit_in -
 
292
 *        converts a string to the internal representation of a bitstring.
 
293
 *              This is the same as bit_in except that atttypmod is taken as
 
294
 *              the maximum length, not the exact length to force the bitstring to.
 
295
 */
 
296
Datum
 
297
varbit_in(PG_FUNCTION_ARGS)
 
298
{
 
299
        char       *input_string = PG_GETARG_CSTRING(0);
 
300
 
 
301
#ifdef NOT_USED
 
302
        Oid                     typelem = PG_GETARG_OID(1);
 
303
#endif
 
304
        int32           atttypmod = PG_GETARG_INT32(2);
 
305
        VarBit     *result;                     /* The resulting bit string                       */
 
306
        char       *sp;                         /* pointer into the character string  */
 
307
        bits8      *r;                          /* pointer into the result */
 
308
        int                     len,                    /* Length of the whole data structure */
 
309
                                bitlen,                 /* Number of bits in the bit string   */
 
310
                                slen;                   /* Length of the input string             */
 
311
        bool            bit_not_hex;    /* false = hex string  true = bit string */
 
312
        int                     bc;
 
313
        bits8           x = 0;
 
314
 
 
315
        /* Check that the first character is a b or an x */
 
316
        if (input_string[0] == 'b' || input_string[0] == 'B')
 
317
        {
 
318
                bit_not_hex = true;
 
319
                sp = input_string + 1;
 
320
        }
 
321
        else if (input_string[0] == 'x' || input_string[0] == 'X')
 
322
        {
 
323
                bit_not_hex = false;
 
324
                sp = input_string + 1;
 
325
        }
 
326
        else
 
327
        {
 
328
                bit_not_hex = true;
 
329
                sp = input_string;
 
330
        }
 
331
 
 
332
        slen = strlen(sp);
 
333
        /* Determine bitlength from input string */
 
334
        if (bit_not_hex)
 
335
                bitlen = slen;
 
336
        else
 
337
                bitlen = slen * 4;
 
338
 
 
339
        /*
 
340
         * Sometimes atttypmod is not supplied. If it is supplied we need to
 
341
         * make sure that the bitstring fits.
 
342
         */
 
343
        if (atttypmod <= 0)
 
344
                atttypmod = bitlen;
 
345
        else if (bitlen > atttypmod)
 
346
                ereport(ERROR,
 
347
                                (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 
348
                                 errmsg("bit string too long for type bit varying(%d)",
 
349
                                                atttypmod)));
 
350
 
 
351
        len = VARBITTOTALLEN(bitlen);
 
352
        /* set to 0 so that *r is always initialised and string is zero-padded */
 
353
        result = (VarBit *) palloc0(len);
 
354
        VARATT_SIZEP(result) = len;
 
355
        VARBITLEN(result) = Min(bitlen, atttypmod);
 
356
 
 
357
        r = VARBITS(result);
 
358
        if (bit_not_hex)
 
359
        {
 
360
                /* Parse the bit representation of the string */
 
361
                /* We know it fits, as bitlen was compared to atttypmod */
 
362
                x = BITHIGH;
 
363
                for (; *sp; sp++)
 
364
                {
 
365
                        if (*sp == '1')
 
366
                                *r |= x;
 
367
                        else if (*sp != '0')
 
368
                                ereport(ERROR,
 
369
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
370
                                                 errmsg("\"%c\" is not a valid binary digit",
 
371
                                                                *sp)));
 
372
 
 
373
                        x >>= 1;
 
374
                        if (x == 0)
 
375
                        {
 
376
                                x = BITHIGH;
 
377
                                r++;
 
378
                        }
 
379
                }
 
380
        }
 
381
        else
 
382
        {
 
383
                /* Parse the hex representation of the string */
 
384
                for (bc = 0; *sp; sp++)
 
385
                {
 
386
                        if (*sp >= '0' && *sp <= '9')
 
387
                                x = (bits8) (*sp - '0');
 
388
                        else if (*sp >= 'A' && *sp <= 'F')
 
389
                                x = (bits8) (*sp - 'A') + 10;
 
390
                        else if (*sp >= 'a' && *sp <= 'f')
 
391
                                x = (bits8) (*sp - 'a') + 10;
 
392
                        else
 
393
                                ereport(ERROR,
 
394
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
395
                                                 errmsg("\"%c\" is not a valid hexadecimal digit",
 
396
                                                                *sp)));
 
397
 
 
398
                        if (bc)
 
399
                        {
 
400
                                *r++ |= x;
 
401
                                bc = 0;
 
402
                        }
 
403
                        else
 
404
                        {
 
405
                                *r = x << 4;
 
406
                                bc = 1;
 
407
                        }
 
408
                }
 
409
        }
 
410
 
 
411
        PG_RETURN_VARBIT_P(result);
 
412
}
 
413
 
 
414
/* varbit_out -
 
415
 *        Prints the string as bits to preserve length accurately
 
416
 */
 
417
Datum
 
418
varbit_out(PG_FUNCTION_ARGS)
 
419
{
 
420
        VarBit     *s = PG_GETARG_VARBIT_P(0);
 
421
        char       *result,
 
422
                           *r;
 
423
        bits8      *sp;
 
424
        bits8           x;
 
425
        int                     i,
 
426
                                k,
 
427
                                len;
 
428
 
 
429
        len = VARBITLEN(s);
 
430
        result = (char *) palloc(len + 1);
 
431
        sp = VARBITS(s);
 
432
        r = result;
 
433
        for (i = 0; i < len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++)
 
434
        {
 
435
                x = *sp;
 
436
                for (k = 0; k < BITS_PER_BYTE; k++)
 
437
                {
 
438
                        *r++ = (x & BITHIGH) ? '1' : '0';
 
439
                        x <<= 1;
 
440
                }
 
441
        }
 
442
        x = *sp;
 
443
        for (k = i; k < len; k++)
 
444
        {
 
445
                *r++ = (x & BITHIGH) ? '1' : '0';
 
446
                x <<= 1;
 
447
        }
 
448
        *r = '\0';
 
449
 
 
450
        PG_RETURN_CSTRING(result);
 
451
}
 
452
 
 
453
/*
 
454
 *              varbit_recv                     - converts external binary format to varbit
 
455
 *
 
456
 * External format is the bitlen as an int32, then the byte array.
 
457
 */
 
458
Datum
 
459
varbit_recv(PG_FUNCTION_ARGS)
 
460
{
 
461
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
462
        VarBit     *result;
 
463
        int                     len,
 
464
                                bitlen;
 
465
        int                     ipad;
 
466
        bits8           mask;
 
467
 
 
468
        bitlen = pq_getmsgint(buf, sizeof(int32));
 
469
        if (bitlen < 0)
 
470
                ereport(ERROR,
 
471
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 
472
                                 errmsg("invalid length in external bit string")));
 
473
 
 
474
        len = VARBITTOTALLEN(bitlen);
 
475
        result = (VarBit *) palloc(len);
 
476
        VARATT_SIZEP(result) = len;
 
477
        VARBITLEN(result) = bitlen;
 
478
 
 
479
        pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
 
480
 
 
481
        /* Make sure last byte is zero-padded if needed */
 
482
        ipad = VARBITPAD(result);
 
483
        if (ipad > 0)
 
484
        {
 
485
                mask = BITMASK << ipad;
 
486
                *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
 
487
        }
 
488
 
 
489
        PG_RETURN_VARBIT_P(result);
 
490
}
 
491
 
 
492
/*
 
493
 *              varbit_send                     - converts varbit to binary format
 
494
 */
 
495
Datum
 
496
varbit_send(PG_FUNCTION_ARGS)
 
497
{
 
498
        VarBit     *s = PG_GETARG_VARBIT_P(0);
 
499
        StringInfoData buf;
 
500
 
 
501
        pq_begintypsend(&buf);
 
502
        pq_sendint(&buf, VARBITLEN(s), sizeof(int32));
 
503
        pq_sendbytes(&buf, VARBITS(s), VARBITBYTES(s));
 
504
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 
505
}
 
506
 
 
507
/* varbit()
 
508
 * Converts a varbit() type to a specific internal length.
 
509
 * len is the maximum bitlength specified in the column definition.
 
510
 *
 
511
 * If doing implicit cast, raise error when source data is too long.
 
512
 * If doing explicit cast, silently truncate to max length.
 
513
 */
 
514
Datum
 
515
varbit(PG_FUNCTION_ARGS)
 
516
{
 
517
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
518
        int32           len = PG_GETARG_INT32(1);
 
519
        bool            isExplicit = PG_GETARG_BOOL(2);
 
520
        VarBit     *result;
 
521
        int                     rlen;
 
522
        int                     ipad;
 
523
        bits8           mask;
 
524
 
 
525
        /* No work if typmod is invalid or supplied data matches it already */
 
526
        if (len <= 0 || len >= VARBITLEN(arg))
 
527
                PG_RETURN_VARBIT_P(arg);
 
528
 
 
529
        if (!isExplicit)
 
530
                ereport(ERROR,
 
531
                                (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 
532
                                 errmsg("bit string too long for type bit varying(%d)",
 
533
                                                len)));
 
534
 
 
535
        rlen = VARBITTOTALLEN(len);
 
536
        result = (VarBit *) palloc(rlen);
 
537
        VARATT_SIZEP(result) = rlen;
 
538
        VARBITLEN(result) = len;
 
539
 
 
540
        memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));
 
541
 
 
542
        /* Make sure last byte is zero-padded if needed */
 
543
        ipad = VARBITPAD(result);
 
544
        if (ipad > 0)
 
545
        {
 
546
                mask = BITMASK << ipad;
 
547
                *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
 
548
        }
 
549
 
 
550
        PG_RETURN_VARBIT_P(result);
 
551
}
 
552
 
 
553
 
 
554
/*
 
555
 * Comparison operators
 
556
 *
 
557
 * We only need one set of comparison operators for bitstrings, as the lengths
 
558
 * are stored in the same way for zero-padded and varying bit strings.
 
559
 *
 
560
 * Note that the standard is not unambiguous about the comparison between
 
561
 * zero-padded bit strings and varying bitstrings. If the same value is written
 
562
 * into a zero padded bitstring as into a varying bitstring, but the zero
 
563
 * padded bitstring has greater length, it will be bigger.
 
564
 *
 
565
 * Zeros from the beginning of a bitstring cannot simply be ignored, as they
 
566
 * may be part of a bit string and may be significant.
 
567
 *
 
568
 * Note: btree indexes need these routines not to leak memory; therefore,
 
569
 * be careful to free working copies of toasted datums.  Most places don't
 
570
 * need to be so careful.
 
571
 */
 
572
 
 
573
/* bit_cmp
 
574
 *
 
575
 * Compares two bitstrings and returns <0, 0, >0 depending on whether the first
 
576
 * string is smaller, equal, or bigger than the second. All bits are considered
 
577
 * and additional zero bits may make one string smaller/larger than the other,
 
578
 * even if their zero-padded values would be the same.
 
579
 */
 
580
static int32
 
581
bit_cmp(VarBit *arg1, VarBit *arg2)
 
582
{
 
583
        int                     bitlen1,
 
584
                                bytelen1,
 
585
                                bitlen2,
 
586
                                bytelen2;
 
587
        int32           cmp;
 
588
 
 
589
        bytelen1 = VARBITBYTES(arg1);
 
590
        bytelen2 = VARBITBYTES(arg2);
 
591
 
 
592
        cmp = memcmp(VARBITS(arg1), VARBITS(arg2), Min(bytelen1, bytelen2));
 
593
        if (cmp == 0)
 
594
        {
 
595
                bitlen1 = VARBITLEN(arg1);
 
596
                bitlen2 = VARBITLEN(arg2);
 
597
                if (bitlen1 != bitlen2)
 
598
                        cmp = (bitlen1 < bitlen2) ? -1 : 1;
 
599
        }
 
600
        return cmp;
 
601
}
 
602
 
 
603
Datum
 
604
biteq(PG_FUNCTION_ARGS)
 
605
{
 
606
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
607
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
608
        bool            result;
 
609
        int                     bitlen1,
 
610
                                bitlen2;
 
611
 
 
612
        bitlen1 = VARBITLEN(arg1);
 
613
        bitlen2 = VARBITLEN(arg2);
 
614
 
 
615
        /* fast path for different-length inputs */
 
616
        if (bitlen1 != bitlen2)
 
617
                result = false;
 
618
        else
 
619
                result = (bit_cmp(arg1, arg2) == 0);
 
620
 
 
621
        PG_FREE_IF_COPY(arg1, 0);
 
622
        PG_FREE_IF_COPY(arg2, 1);
 
623
 
 
624
        PG_RETURN_BOOL(result);
 
625
}
 
626
 
 
627
Datum
 
628
bitne(PG_FUNCTION_ARGS)
 
629
{
 
630
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
631
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
632
        bool            result;
 
633
        int                     bitlen1,
 
634
                                bitlen2;
 
635
 
 
636
        bitlen1 = VARBITLEN(arg1);
 
637
        bitlen2 = VARBITLEN(arg2);
 
638
 
 
639
        /* fast path for different-length inputs */
 
640
        if (bitlen1 != bitlen2)
 
641
                result = true;
 
642
        else
 
643
                result = (bit_cmp(arg1, arg2) != 0);
 
644
 
 
645
        PG_FREE_IF_COPY(arg1, 0);
 
646
        PG_FREE_IF_COPY(arg2, 1);
 
647
 
 
648
        PG_RETURN_BOOL(result);
 
649
}
 
650
 
 
651
Datum
 
652
bitlt(PG_FUNCTION_ARGS)
 
653
{
 
654
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
655
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
656
        bool            result;
 
657
 
 
658
        result = (bit_cmp(arg1, arg2) < 0);
 
659
 
 
660
        PG_FREE_IF_COPY(arg1, 0);
 
661
        PG_FREE_IF_COPY(arg2, 1);
 
662
 
 
663
        PG_RETURN_BOOL(result);
 
664
}
 
665
 
 
666
Datum
 
667
bitle(PG_FUNCTION_ARGS)
 
668
{
 
669
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
670
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
671
        bool            result;
 
672
 
 
673
        result = (bit_cmp(arg1, arg2) <= 0);
 
674
 
 
675
        PG_FREE_IF_COPY(arg1, 0);
 
676
        PG_FREE_IF_COPY(arg2, 1);
 
677
 
 
678
        PG_RETURN_BOOL(result);
 
679
}
 
680
 
 
681
Datum
 
682
bitgt(PG_FUNCTION_ARGS)
 
683
{
 
684
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
685
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
686
        bool            result;
 
687
 
 
688
        result = (bit_cmp(arg1, arg2) > 0);
 
689
 
 
690
        PG_FREE_IF_COPY(arg1, 0);
 
691
        PG_FREE_IF_COPY(arg2, 1);
 
692
 
 
693
        PG_RETURN_BOOL(result);
 
694
}
 
695
 
 
696
Datum
 
697
bitge(PG_FUNCTION_ARGS)
 
698
{
 
699
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
700
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
701
        bool            result;
 
702
 
 
703
        result = (bit_cmp(arg1, arg2) >= 0);
 
704
 
 
705
        PG_FREE_IF_COPY(arg1, 0);
 
706
        PG_FREE_IF_COPY(arg2, 1);
 
707
 
 
708
        PG_RETURN_BOOL(result);
 
709
}
 
710
 
 
711
Datum
 
712
bitcmp(PG_FUNCTION_ARGS)
 
713
{
 
714
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
715
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
716
        int32           result;
 
717
 
 
718
        result = bit_cmp(arg1, arg2);
 
719
 
 
720
        PG_FREE_IF_COPY(arg1, 0);
 
721
        PG_FREE_IF_COPY(arg2, 1);
 
722
 
 
723
        PG_RETURN_INT32(result);
 
724
}
 
725
 
 
726
/* bitcat
 
727
 * Concatenation of bit strings
 
728
 */
 
729
Datum
 
730
bitcat(PG_FUNCTION_ARGS)
 
731
{
 
732
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
733
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
734
        VarBit     *result;
 
735
        int                     bitlen1,
 
736
                                bitlen2,
 
737
                                bytelen,
 
738
                                bit1pad,
 
739
                                bit2shift;
 
740
        bits8      *pr,
 
741
                           *pa;
 
742
 
 
743
        bitlen1 = VARBITLEN(arg1);
 
744
        bitlen2 = VARBITLEN(arg2);
 
745
 
 
746
        bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);
 
747
 
 
748
        result = (VarBit *) palloc(bytelen);
 
749
        VARATT_SIZEP(result) = bytelen;
 
750
        VARBITLEN(result) = bitlen1 + bitlen2;
 
751
 
 
752
        /* Copy the first bitstring in */
 
753
        memcpy(VARBITS(result), VARBITS(arg1), VARBITBYTES(arg1));
 
754
 
 
755
        /* Copy the second bit string */
 
756
        bit1pad = VARBITPAD(arg1);
 
757
        if (bit1pad == 0)
 
758
        {
 
759
                memcpy(VARBITS(result) + VARBITBYTES(arg1), VARBITS(arg2),
 
760
                           VARBITBYTES(arg2));
 
761
        }
 
762
        else if (bitlen2 > 0)
 
763
        {
 
764
                /* We need to shift all the bits to fit */
 
765
                bit2shift = BITS_PER_BYTE - bit1pad;
 
766
                pr = VARBITS(result) + VARBITBYTES(arg1) - 1;
 
767
                for (pa = VARBITS(arg2); pa < VARBITEND(arg2); pa++)
 
768
                {
 
769
                        *pr |= ((*pa >> bit2shift) & BITMASK);
 
770
                        pr++;
 
771
                        if (pr < VARBITEND(result))
 
772
                                *pr = (*pa << bit1pad) & BITMASK;
 
773
                }
 
774
        }
 
775
 
 
776
        PG_RETURN_VARBIT_P(result);
 
777
}
 
778
 
 
779
/* bitsubstr
 
780
 * retrieve a substring from the bit string.
 
781
 * Note, s is 1-based.
 
782
 * SQL draft 6.10 9)
 
783
 */
 
784
Datum
 
785
bitsubstr(PG_FUNCTION_ARGS)
 
786
{
 
787
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
788
        int32           s = PG_GETARG_INT32(1);
 
789
        int32           l = PG_GETARG_INT32(2);
 
790
        VarBit     *result;
 
791
        int                     bitlen,
 
792
                                rbitlen,
 
793
                                len,
 
794
                                ipad = 0,
 
795
                                ishift,
 
796
                                i;
 
797
        int                     e,
 
798
                                s1,
 
799
                                e1;
 
800
        bits8           mask,
 
801
                           *r,
 
802
                           *ps;
 
803
 
 
804
        bitlen = VARBITLEN(arg);
 
805
        /* If we do not have an upper bound, set bitlen */
 
806
        if (l == -1)
 
807
                l = bitlen;
 
808
        e = s + l;
 
809
        s1 = Max(s, 1);
 
810
        e1 = Min(e, bitlen + 1);
 
811
        if (s1 > bitlen || e1 < 1)
 
812
        {
 
813
                /* Need to return a zero-length bitstring */
 
814
                len = VARBITTOTALLEN(0);
 
815
                result = (VarBit *) palloc(len);
 
816
                VARATT_SIZEP(result) = len;
 
817
                VARBITLEN(result) = 0;
 
818
        }
 
819
        else
 
820
        {
 
821
                /*
 
822
                 * OK, we've got a true substring starting at position s1-1 and
 
823
                 * ending at position e1-1
 
824
                 */
 
825
                rbitlen = e1 - s1;
 
826
                len = VARBITTOTALLEN(rbitlen);
 
827
                result = (VarBit *) palloc(len);
 
828
                VARATT_SIZEP(result) = len;
 
829
                VARBITLEN(result) = rbitlen;
 
830
                len -= VARHDRSZ + VARBITHDRSZ;
 
831
                /* Are we copying from a byte boundary? */
 
832
                if ((s1 - 1) % BITS_PER_BYTE == 0)
 
833
                {
 
834
                        /* Yep, we are copying bytes */
 
835
                        memcpy(VARBITS(result), VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE,
 
836
                                   len);
 
837
                }
 
838
                else
 
839
                {
 
840
                        /* Figure out how much we need to shift the sequence by */
 
841
                        ishift = (s1 - 1) % BITS_PER_BYTE;
 
842
                        r = VARBITS(result);
 
843
                        ps = VARBITS(arg) + (s1 - 1) / BITS_PER_BYTE;
 
844
                        for (i = 0; i < len; i++)
 
845
                        {
 
846
                                *r = (*ps << ishift) & BITMASK;
 
847
                                if ((++ps) < VARBITEND(arg))
 
848
                                        *r |= *ps >> (BITS_PER_BYTE - ishift);
 
849
                                r++;
 
850
                        }
 
851
                }
 
852
                /* Do we need to pad at the end? */
 
853
                ipad = VARBITPAD(result);
 
854
                if (ipad > 0)
 
855
                {
 
856
                        mask = BITMASK << ipad;
 
857
                        *(VARBITS(result) + len - 1) &= mask;
 
858
                }
 
859
        }
 
860
 
 
861
        PG_RETURN_VARBIT_P(result);
 
862
}
 
863
 
 
864
/* bitlength, bitoctetlength
 
865
 * Return the length of a bit string
 
866
 */
 
867
Datum
 
868
bitlength(PG_FUNCTION_ARGS)
 
869
{
 
870
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
871
 
 
872
        PG_RETURN_INT32(VARBITLEN(arg));
 
873
}
 
874
 
 
875
Datum
 
876
bitoctetlength(PG_FUNCTION_ARGS)
 
877
{
 
878
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
879
 
 
880
        PG_RETURN_INT32(VARBITBYTES(arg));
 
881
}
 
882
 
 
883
/* bitand
 
884
 * perform a logical AND on two bit strings.
 
885
 */
 
886
Datum
 
887
bitand(PG_FUNCTION_ARGS)
 
888
{
 
889
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
890
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
891
        VarBit     *result;
 
892
        int                     len,
 
893
                                bitlen1,
 
894
                                bitlen2,
 
895
                                i;
 
896
        bits8      *p1,
 
897
                           *p2,
 
898
                           *r;
 
899
 
 
900
        bitlen1 = VARBITLEN(arg1);
 
901
        bitlen2 = VARBITLEN(arg2);
 
902
        if (bitlen1 != bitlen2)
 
903
                ereport(ERROR,
 
904
                                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 
905
                                 errmsg("cannot AND bit strings of different sizes")));
 
906
 
 
907
        len = VARSIZE(arg1);
 
908
        result = (VarBit *) palloc(len);
 
909
        VARATT_SIZEP(result) = len;
 
910
        VARBITLEN(result) = bitlen1;
 
911
 
 
912
        p1 = VARBITS(arg1);
 
913
        p2 = VARBITS(arg2);
 
914
        r = VARBITS(result);
 
915
        for (i = 0; i < VARBITBYTES(arg1); i++)
 
916
                *r++ = *p1++ & *p2++;
 
917
 
 
918
        /* Padding is not needed as & of 0 pad is 0 */
 
919
 
 
920
        PG_RETURN_VARBIT_P(result);
 
921
}
 
922
 
 
923
/* bitor
 
924
 * perform a logical OR on two bit strings.
 
925
 */
 
926
Datum
 
927
bitor(PG_FUNCTION_ARGS)
 
928
{
 
929
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
930
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
931
        VarBit     *result;
 
932
        int                     len,
 
933
                                bitlen1,
 
934
                                bitlen2,
 
935
                                i;
 
936
        bits8      *p1,
 
937
                           *p2,
 
938
                           *r;
 
939
        bits8           mask;
 
940
 
 
941
        bitlen1 = VARBITLEN(arg1);
 
942
        bitlen2 = VARBITLEN(arg2);
 
943
        if (bitlen1 != bitlen2)
 
944
                ereport(ERROR,
 
945
                                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 
946
                                 errmsg("cannot OR bit strings of different sizes")));
 
947
        len = VARSIZE(arg1);
 
948
        result = (VarBit *) palloc(len);
 
949
        VARATT_SIZEP(result) = len;
 
950
        VARBITLEN(result) = bitlen1;
 
951
 
 
952
        p1 = VARBITS(arg1);
 
953
        p2 = VARBITS(arg2);
 
954
        r = VARBITS(result);
 
955
        for (i = 0; i < VARBITBYTES(arg1); i++)
 
956
                *r++ = *p1++ | *p2++;
 
957
 
 
958
        /* Pad the result */
 
959
        mask = BITMASK << VARBITPAD(result);
 
960
        if (mask)
 
961
        {
 
962
                r--;
 
963
                *r &= mask;
 
964
        }
 
965
 
 
966
        PG_RETURN_VARBIT_P(result);
 
967
}
 
968
 
 
969
/* bitxor
 
970
 * perform a logical XOR on two bit strings.
 
971
 */
 
972
Datum
 
973
bitxor(PG_FUNCTION_ARGS)
 
974
{
 
975
        VarBit     *arg1 = PG_GETARG_VARBIT_P(0);
 
976
        VarBit     *arg2 = PG_GETARG_VARBIT_P(1);
 
977
        VarBit     *result;
 
978
        int                     len,
 
979
                                bitlen1,
 
980
                                bitlen2,
 
981
                                i;
 
982
        bits8      *p1,
 
983
                           *p2,
 
984
                           *r;
 
985
        bits8           mask;
 
986
 
 
987
        bitlen1 = VARBITLEN(arg1);
 
988
        bitlen2 = VARBITLEN(arg2);
 
989
        if (bitlen1 != bitlen2)
 
990
                ereport(ERROR,
 
991
                                (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 
992
                                 errmsg("cannot XOR bit strings of different sizes")));
 
993
 
 
994
        len = VARSIZE(arg1);
 
995
        result = (VarBit *) palloc(len);
 
996
        VARATT_SIZEP(result) = len;
 
997
        VARBITLEN(result) = bitlen1;
 
998
 
 
999
        p1 = VARBITS(arg1);
 
1000
        p2 = VARBITS(arg2);
 
1001
        r = VARBITS(result);
 
1002
        for (i = 0; i < VARBITBYTES(arg1); i++)
 
1003
                *r++ = *p1++ ^ *p2++;
 
1004
 
 
1005
        /* Pad the result */
 
1006
        mask = BITMASK << VARBITPAD(result);
 
1007
        if (mask)
 
1008
        {
 
1009
                r--;
 
1010
                *r &= mask;
 
1011
        }
 
1012
 
 
1013
        PG_RETURN_VARBIT_P(result);
 
1014
}
 
1015
 
 
1016
/* bitnot
 
1017
 * perform a logical NOT on a bit string.
 
1018
 */
 
1019
Datum
 
1020
bitnot(PG_FUNCTION_ARGS)
 
1021
{
 
1022
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
1023
        VarBit     *result;
 
1024
        bits8      *p,
 
1025
                           *r;
 
1026
        bits8           mask;
 
1027
 
 
1028
        result = (VarBit *) palloc(VARSIZE(arg));
 
1029
        VARATT_SIZEP(result) = VARSIZE(arg);
 
1030
        VARBITLEN(result) = VARBITLEN(arg);
 
1031
 
 
1032
        p = VARBITS(arg);
 
1033
        r = VARBITS(result);
 
1034
        for (; p < VARBITEND(arg); p++)
 
1035
                *r++ = ~*p;
 
1036
 
 
1037
        /* Pad the result */
 
1038
        mask = BITMASK << VARBITPAD(result);
 
1039
        if (mask)
 
1040
        {
 
1041
                r--;
 
1042
                *r &= mask;
 
1043
        }
 
1044
 
 
1045
        PG_RETURN_VARBIT_P(result);
 
1046
}
 
1047
 
 
1048
/* bitshiftleft
 
1049
 * do a left shift (i.e. towards the beginning of the string)
 
1050
 */
 
1051
Datum
 
1052
bitshiftleft(PG_FUNCTION_ARGS)
 
1053
{
 
1054
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
1055
        int32           shft = PG_GETARG_INT32(1);
 
1056
        VarBit     *result;
 
1057
        int                     byte_shift,
 
1058
                                ishift,
 
1059
                                len;
 
1060
        bits8      *p,
 
1061
                           *r;
 
1062
 
 
1063
        /* Negative shift is a shift to the right */
 
1064
        if (shft < 0)
 
1065
                PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
 
1066
                                                                                        VarBitPGetDatum(arg),
 
1067
                                                                                        Int32GetDatum(-shft)));
 
1068
 
 
1069
        result = (VarBit *) palloc(VARSIZE(arg));
 
1070
        VARATT_SIZEP(result) = VARSIZE(arg);
 
1071
        VARBITLEN(result) = VARBITLEN(arg);
 
1072
        r = VARBITS(result);
 
1073
 
 
1074
        /* If we shifted all the bits out, return an all-zero string */
 
1075
        if (shft >= VARBITLEN(arg))
 
1076
        {
 
1077
                MemSet(r, 0, VARBITBYTES(arg));
 
1078
                PG_RETURN_VARBIT_P(result);
 
1079
        }
 
1080
 
 
1081
        byte_shift = shft / BITS_PER_BYTE;
 
1082
        ishift = shft % BITS_PER_BYTE;
 
1083
        p = VARBITS(arg) + byte_shift;
 
1084
 
 
1085
        if (ishift == 0)
 
1086
        {
 
1087
                /* Special case: we can do a memcpy */
 
1088
                len = VARBITBYTES(arg) - byte_shift;
 
1089
                memcpy(r, p, len);
 
1090
                MemSet(r + len, 0, byte_shift);
 
1091
        }
 
1092
        else
 
1093
        {
 
1094
                for (; p < VARBITEND(arg); r++)
 
1095
                {
 
1096
                        *r = *p << ishift;
 
1097
                        if ((++p) < VARBITEND(arg))
 
1098
                                *r |= *p >> (BITS_PER_BYTE - ishift);
 
1099
                }
 
1100
                for (; r < VARBITEND(result); r++)
 
1101
                        *r = 0;
 
1102
        }
 
1103
 
 
1104
        PG_RETURN_VARBIT_P(result);
 
1105
}
 
1106
 
 
1107
/* bitshiftright
 
1108
 * do a right shift (i.e. towards the end of the string)
 
1109
 */
 
1110
Datum
 
1111
bitshiftright(PG_FUNCTION_ARGS)
 
1112
{
 
1113
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
1114
        int32           shft = PG_GETARG_INT32(1);
 
1115
        VarBit     *result;
 
1116
        int                     byte_shift,
 
1117
                                ishift,
 
1118
                                len;
 
1119
        bits8      *p,
 
1120
                           *r;
 
1121
 
 
1122
        /* Negative shift is a shift to the left */
 
1123
        if (shft < 0)
 
1124
                PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
 
1125
                                                                                        VarBitPGetDatum(arg),
 
1126
                                                                                        Int32GetDatum(-shft)));
 
1127
 
 
1128
        result = (VarBit *) palloc(VARSIZE(arg));
 
1129
        VARATT_SIZEP(result) = VARSIZE(arg);
 
1130
        VARBITLEN(result) = VARBITLEN(arg);
 
1131
        r = VARBITS(result);
 
1132
 
 
1133
        /* If we shifted all the bits out, return an all-zero string */
 
1134
        if (shft >= VARBITLEN(arg))
 
1135
        {
 
1136
                MemSet(r, 0, VARBITBYTES(arg));
 
1137
                PG_RETURN_VARBIT_P(result);
 
1138
        }
 
1139
 
 
1140
        byte_shift = shft / BITS_PER_BYTE;
 
1141
        ishift = shft % BITS_PER_BYTE;
 
1142
        p = VARBITS(arg);
 
1143
 
 
1144
        /* Set the first part of the result to 0 */
 
1145
        MemSet(r, 0, byte_shift);
 
1146
        r += byte_shift;
 
1147
 
 
1148
        if (ishift == 0)
 
1149
        {
 
1150
                /* Special case: we can do a memcpy */
 
1151
                len = VARBITBYTES(arg) - byte_shift;
 
1152
                memcpy(r, p, len);
 
1153
        }
 
1154
        else
 
1155
        {
 
1156
                if (r < VARBITEND(result))
 
1157
                        *r = 0;                         /* initialize first byte */
 
1158
                for (; r < VARBITEND(result); p++)
 
1159
                {
 
1160
                        *r |= *p >> ishift;
 
1161
                        if ((++r) < VARBITEND(result))
 
1162
                                *r = (*p << (BITS_PER_BYTE - ishift)) & BITMASK;
 
1163
                }
 
1164
        }
 
1165
 
 
1166
        PG_RETURN_VARBIT_P(result);
 
1167
}
 
1168
 
 
1169
/*
 
1170
 * This is not defined in any standard. We retain the natural ordering of
 
1171
 * bits here, as it just seems more intuitive.
 
1172
 */
 
1173
Datum
 
1174
bitfromint4(PG_FUNCTION_ARGS)
 
1175
{
 
1176
        int32           a = PG_GETARG_INT32(0);
 
1177
        int32           typmod = PG_GETARG_INT32(1);
 
1178
        VarBit     *result;
 
1179
        bits8      *r;
 
1180
        int                     rlen;
 
1181
        int                     destbitsleft,
 
1182
                                srcbitsleft;
 
1183
 
 
1184
        if (typmod <= 0)
 
1185
                typmod = 1;                             /* default bit length */
 
1186
 
 
1187
        rlen = VARBITTOTALLEN(typmod);
 
1188
        result = (VarBit *) palloc(rlen);
 
1189
        VARATT_SIZEP(result) = rlen;
 
1190
        VARBITLEN(result) = typmod;
 
1191
 
 
1192
        r = VARBITS(result);
 
1193
        destbitsleft = typmod;
 
1194
        srcbitsleft = 32;
 
1195
        /* drop any input bits that don't fit */
 
1196
        srcbitsleft = Min(srcbitsleft, destbitsleft);
 
1197
        /* sign-fill any excess bytes in output */
 
1198
        while (destbitsleft >= srcbitsleft + 8)
 
1199
        {
 
1200
                *r++ = (bits8) ((a < 0) ? BITMASK : 0);
 
1201
                destbitsleft -= 8;
 
1202
        }
 
1203
        /* store first fractional byte */
 
1204
        if (destbitsleft > srcbitsleft)
 
1205
        {
 
1206
                *r++ = (bits8) ((a >> (srcbitsleft - 8)) & BITMASK);
 
1207
                destbitsleft -= 8;
 
1208
        }
 
1209
        /* Now srcbitsleft and destbitsleft are the same, need not track both */
 
1210
        /* store whole bytes */
 
1211
        while (destbitsleft >= 8)
 
1212
        {
 
1213
                *r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
 
1214
                destbitsleft -= 8;
 
1215
        }
 
1216
        /* store last fractional byte */
 
1217
        if (destbitsleft > 0)
 
1218
                *r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);
 
1219
 
 
1220
        PG_RETURN_VARBIT_P(result);
 
1221
}
 
1222
 
 
1223
Datum
 
1224
bittoint4(PG_FUNCTION_ARGS)
 
1225
{
 
1226
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
1227
        uint32          result;
 
1228
        bits8      *r;
 
1229
 
 
1230
        /* Check that the bit string is not too long */
 
1231
        if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
 
1232
                ereport(ERROR,
 
1233
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1234
                                 errmsg("integer out of range")));
 
1235
 
 
1236
        result = 0;
 
1237
        for (r = VARBITS(arg); r < VARBITEND(arg); r++)
 
1238
        {
 
1239
                result <<= BITS_PER_BYTE;
 
1240
                result |= *r;
 
1241
        }
 
1242
        /* Now shift the result to take account of the padding at the end */
 
1243
        result >>= VARBITPAD(arg);
 
1244
 
 
1245
        PG_RETURN_INT32(result);
 
1246
}
 
1247
 
 
1248
Datum
 
1249
bitfromint8(PG_FUNCTION_ARGS)
 
1250
{
 
1251
        int64           a = PG_GETARG_INT64(0);
 
1252
        int32           typmod = PG_GETARG_INT32(1);
 
1253
        VarBit     *result;
 
1254
        bits8      *r;
 
1255
        int                     rlen;
 
1256
        int                     destbitsleft,
 
1257
                                srcbitsleft;
 
1258
 
 
1259
        if (typmod <= 0)
 
1260
                typmod = 1;                             /* default bit length */
 
1261
 
 
1262
        rlen = VARBITTOTALLEN(typmod);
 
1263
        result = (VarBit *) palloc(rlen);
 
1264
        VARATT_SIZEP(result) = rlen;
 
1265
        VARBITLEN(result) = typmod;
 
1266
 
 
1267
        r = VARBITS(result);
 
1268
        destbitsleft = typmod;
 
1269
#ifndef INT64_IS_BUSTED
 
1270
        srcbitsleft = 64;
 
1271
#else
 
1272
        srcbitsleft = 32;                       /* don't try to shift more than 32 */
 
1273
#endif
 
1274
        /* drop any input bits that don't fit */
 
1275
        srcbitsleft = Min(srcbitsleft, destbitsleft);
 
1276
        /* sign-fill any excess bytes in output */
 
1277
        while (destbitsleft >= srcbitsleft + 8)
 
1278
        {
 
1279
                *r++ = (bits8) ((a < 0) ? BITMASK : 0);
 
1280
                destbitsleft -= 8;
 
1281
        }
 
1282
        /* store first fractional byte */
 
1283
        if (destbitsleft > srcbitsleft)
 
1284
        {
 
1285
                *r++ = (bits8) ((a >> (srcbitsleft - 8)) & BITMASK);
 
1286
                destbitsleft -= 8;
 
1287
        }
 
1288
        /* Now srcbitsleft and destbitsleft are the same, need not track both */
 
1289
        /* store whole bytes */
 
1290
        while (destbitsleft >= 8)
 
1291
        {
 
1292
                *r++ = (bits8) ((a >> (destbitsleft - 8)) & BITMASK);
 
1293
                destbitsleft -= 8;
 
1294
        }
 
1295
        /* store last fractional byte */
 
1296
        if (destbitsleft > 0)
 
1297
                *r = (bits8) ((a << (8 - destbitsleft)) & BITMASK);
 
1298
 
 
1299
        PG_RETURN_VARBIT_P(result);
 
1300
}
 
1301
 
 
1302
Datum
 
1303
bittoint8(PG_FUNCTION_ARGS)
 
1304
{
 
1305
        VarBit     *arg = PG_GETARG_VARBIT_P(0);
 
1306
        uint64          result;
 
1307
        bits8      *r;
 
1308
 
 
1309
        /* Check that the bit string is not too long */
 
1310
        if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
 
1311
                ereport(ERROR,
 
1312
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
1313
                                 errmsg("bigint out of range")));
 
1314
 
 
1315
        result = 0;
 
1316
        for (r = VARBITS(arg); r < VARBITEND(arg); r++)
 
1317
        {
 
1318
                result <<= BITS_PER_BYTE;
 
1319
                result |= *r;
 
1320
        }
 
1321
        /* Now shift the result to take account of the padding at the end */
 
1322
        result >>= VARBITPAD(arg);
 
1323
 
 
1324
        PG_RETURN_INT64(result);
 
1325
}
 
1326
 
 
1327
 
 
1328
/* Determines the position of S2 in the bitstring S1 (1-based string).
 
1329
 * If S2 does not appear in S1 this function returns 0.
 
1330
 * If S2 is of length 0 this function returns 1.
 
1331
 * Compatible in usage with POSITION() functions for other data types.
 
1332
 */
 
1333
Datum
 
1334
bitposition(PG_FUNCTION_ARGS)
 
1335
{
 
1336
        VarBit     *str = PG_GETARG_VARBIT_P(0);
 
1337
        VarBit     *substr = PG_GETARG_VARBIT_P(1);
 
1338
        int                     substr_length,
 
1339
                                str_length,
 
1340
                                i,
 
1341
                                is;
 
1342
        bits8      *s,                          /* pointer into substring */
 
1343
                           *p;                          /* pointer into str */
 
1344
        bits8           cmp,                    /* shifted substring byte to compare */
 
1345
                                mask1,                  /* mask for substring byte shifted right */
 
1346
                                mask2,                  /* mask for substring byte shifted left */
 
1347
                                end_mask,               /* pad mask for last substring byte */
 
1348
                                str_mask;               /* pad mask for last string byte */
 
1349
        bool            is_match;
 
1350
 
 
1351
        /* Get the substring length */
 
1352
        substr_length = VARBITLEN(substr);
 
1353
        str_length = VARBITLEN(str);
 
1354
 
 
1355
        /* String has zero length or substring longer than string, return 0 */
 
1356
        if ((str_length == 0) || (substr_length > str_length))
 
1357
                PG_RETURN_INT32(0);
 
1358
 
 
1359
        /* zero-length substring means return 1 */
 
1360
        if (substr_length == 0)
 
1361
                PG_RETURN_INT32(1);
 
1362
 
 
1363
        /* Initialise the padding masks */
 
1364
        end_mask = BITMASK << VARBITPAD(substr);
 
1365
        str_mask = BITMASK << VARBITPAD(str);
 
1366
        for (i = 0; i < VARBITBYTES(str) - VARBITBYTES(substr) + 1; i++)
 
1367
        {
 
1368
                for (is = 0; is < BITS_PER_BYTE; is++)
 
1369
                {
 
1370
                        is_match = true;
 
1371
                        p = VARBITS(str) + i;
 
1372
                        mask1 = BITMASK >> is;
 
1373
                        mask2 = ~mask1;
 
1374
                        for (s = VARBITS(substr);
 
1375
                                 is_match && s < VARBITEND(substr); s++)
 
1376
                        {
 
1377
                                cmp = *s >> is;
 
1378
                                if (s == VARBITEND(substr) - 1)
 
1379
                                {
 
1380
                                        mask1 &= end_mask >> is;
 
1381
                                        if (p == VARBITEND(str) - 1)
 
1382
                                        {
 
1383
                                                /* Check that there is enough of str left */
 
1384
                                                if (mask1 & ~str_mask)
 
1385
                                                {
 
1386
                                                        is_match = false;
 
1387
                                                        break;
 
1388
                                                }
 
1389
                                                mask1 &= str_mask;
 
1390
                                        }
 
1391
                                }
 
1392
                                is_match = ((cmp ^ *p) & mask1) == 0;
 
1393
                                if (!is_match)
 
1394
                                        break;
 
1395
                                /* Move on to the next byte */
 
1396
                                p++;
 
1397
                                if (p == VARBITEND(str))
 
1398
                                {
 
1399
                                        mask2 = end_mask << (BITS_PER_BYTE - is);
 
1400
                                        is_match = mask2 == 0;
 
1401
#if 0
 
1402
                                        elog(DEBUG4, "S. %d %d em=%2x sm=%2x r=%d",
 
1403
                                                 i, is, end_mask, mask2, is_match);
 
1404
#endif
 
1405
                                        break;
 
1406
                                }
 
1407
                                cmp = *s << (BITS_PER_BYTE - is);
 
1408
                                if (s == VARBITEND(substr) - 1)
 
1409
                                {
 
1410
                                        mask2 &= end_mask << (BITS_PER_BYTE - is);
 
1411
                                        if (p == VARBITEND(str) - 1)
 
1412
                                        {
 
1413
                                                if (mask2 & ~str_mask)
 
1414
                                                {
 
1415
                                                        is_match = false;
 
1416
                                                        break;
 
1417
                                                }
 
1418
                                                mask2 &= str_mask;
 
1419
                                        }
 
1420
                                }
 
1421
                                is_match = ((cmp ^ *p) & mask2) == 0;
 
1422
                        }
 
1423
                        /* Have we found a match? */
 
1424
                        if (is_match)
 
1425
                                PG_RETURN_INT32(i * BITS_PER_BYTE + is + 1);
 
1426
                }
 
1427
        }
 
1428
        PG_RETURN_INT32(0);
 
1429
}