]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/varlena.c
pgindent run on all C files. Java run to follow. initdb/regression
[postgresql] / src / backend / utils / adt / varlena.c
1 /*-------------------------------------------------------------------------
2  *
3  * varlena.c
4  *        Functions for the variable-length built-in types.
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.74 2001/10/25 05:49:46 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <ctype.h>
18
19 #include "mb/pg_wchar.h"
20 #include "miscadmin.h"
21 #include "utils/builtins.h"
22
23 static int      text_cmp(text *arg1, text *arg2);
24
25
26 /*****************************************************************************
27  *       USER I/O ROUTINES                                                                                                               *
28  *****************************************************************************/
29
30
31 #define VAL(CH)                 ((CH) - '0')
32 #define DIG(VAL)                ((VAL) + '0')
33
34 /*
35  *              byteain                 - converts from printable representation of byte array
36  *
37  *              Non-printable characters must be passed as '\nnn' (octal) and are
38  *              converted to internal form.  '\' must be passed as '\\'.
39  *              elog(ERROR, ...) if bad form.
40  *
41  *              BUGS:
42  *                              The input is scaned twice.
43  *                              The error checking of input is minimal.
44  */
45 Datum
46 byteain(PG_FUNCTION_ARGS)
47 {
48         char       *inputText = PG_GETARG_CSTRING(0);
49         char       *tp;
50         char       *rp;
51         int                     byte;
52         bytea      *result;
53
54         for (byte = 0, tp = inputText; *tp != '\0'; byte++)
55         {
56                 if (tp[0] != '\\')
57                         tp++;
58                 else if ((tp[0] == '\\') &&
59                                  (tp[1] >= '0' && tp[1] <= '3') &&
60                                  (tp[2] >= '0' && tp[2] <= '7') &&
61                                  (tp[3] >= '0' && tp[3] <= '7'))
62                         tp += 4;
63                 else if ((tp[0] == '\\') &&
64                                  (tp[1] == '\\'))
65                         tp += 2;
66                 else
67                 {
68                         /*
69                          * one backslash, not followed by 0 or ### valid octal
70                          */
71                         elog(ERROR, "Bad input string for type bytea");
72                 }
73         }
74
75         byte += VARHDRSZ;
76         result = (bytea *) palloc(byte);
77         result->vl_len = byte;          /* set varlena length */
78
79         tp = inputText;
80         rp = result->vl_dat;
81         while (*tp != '\0')
82         {
83                 if (tp[0] != '\\')
84                         *rp++ = *tp++;
85                 else if ((tp[0] == '\\') &&
86                                  (tp[1] >= '0' && tp[1] <= '3') &&
87                                  (tp[2] >= '0' && tp[2] <= '7') &&
88                                  (tp[3] >= '0' && tp[3] <= '7'))
89                 {
90                         byte = VAL(tp[1]);
91                         byte <<= 3;
92                         byte += VAL(tp[2]);
93                         byte <<= 3;
94                         *rp++ = byte + VAL(tp[3]);
95                         tp += 4;
96                 }
97                 else if ((tp[0] == '\\') &&
98                                  (tp[1] == '\\'))
99                 {
100                         *rp++ = '\\';
101                         tp += 2;
102                 }
103                 else
104                 {
105                         /*
106                          * We should never get here. The first pass should not allow
107                          * it.
108                          */
109                         elog(ERROR, "Bad input string for type bytea");
110                 }
111         }
112
113         PG_RETURN_BYTEA_P(result);
114 }
115
116 /*
117  *              byteaout                - converts to printable representation of byte array
118  *
119  *              Non-printable characters are inserted as '\nnn' (octal) and '\' as
120  *              '\\'.
121  *
122  *              NULL vlena should be an error--returning string with NULL for now.
123  */
124 Datum
125 byteaout(PG_FUNCTION_ARGS)
126 {
127         bytea      *vlena = PG_GETARG_BYTEA_P(0);
128         char       *result;
129         char       *vp;
130         char       *rp;
131         int                     val;                    /* holds unprintable chars */
132         int                     i;
133         int                     len;
134
135         len = 1;                                        /* empty string has 1 char */
136         vp = vlena->vl_dat;
137         for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
138         {
139                 if (*vp == '\\')
140                         len += 2;
141                 else if (isprint((unsigned char) *vp))
142                         len++;
143                 else
144                         len += 4;
145         }
146         rp = result = (char *) palloc(len);
147         vp = vlena->vl_dat;
148         for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
149         {
150                 if (*vp == '\\')
151                 {
152                         *rp++ = '\\';
153                         *rp++ = '\\';
154                 }
155                 else if (isprint((unsigned char) *vp))
156                         *rp++ = *vp;
157                 else
158                 {
159                         val = *vp;
160                         rp[0] = '\\';
161                         rp[3] = DIG(val & 07);
162                         val >>= 3;
163                         rp[2] = DIG(val & 07);
164                         val >>= 3;
165                         rp[1] = DIG(val & 03);
166                         rp += 4;
167                 }
168         }
169         *rp = '\0';
170         PG_RETURN_CSTRING(result);
171 }
172
173
174 /*
175  *              textin                  - converts "..." to internal representation
176  */
177 Datum
178 textin(PG_FUNCTION_ARGS)
179 {
180         char       *inputText = PG_GETARG_CSTRING(0);
181         text       *result;
182         int                     len;
183
184 #ifdef MULTIBYTE
185         char       *ermsg;
186 #endif
187
188         len = strlen(inputText) + VARHDRSZ;
189
190 #ifdef MULTIBYTE
191         if ((ermsg = pg_verifymbstr(inputText, len - VARHDRSZ)))
192                 elog(ERROR, "%s", ermsg);
193 #endif
194
195         result = (text *) palloc(len);
196         VARATT_SIZEP(result) = len;
197
198         memcpy(VARDATA(result), inputText, len - VARHDRSZ);
199
200 #ifdef CYR_RECODE
201         convertstr(VARDATA(result), len - VARHDRSZ, 0);
202 #endif
203
204         PG_RETURN_TEXT_P(result);
205 }
206
207 /*
208  *              textout                 - converts internal representation to "..."
209  */
210 Datum
211 textout(PG_FUNCTION_ARGS)
212 {
213         text       *t = PG_GETARG_TEXT_P(0);
214         int                     len;
215         char       *result;
216
217         len = VARSIZE(t) - VARHDRSZ;
218         result = (char *) palloc(len + 1);
219         memcpy(result, VARDATA(t), len);
220         result[len] = '\0';
221
222 #ifdef CYR_RECODE
223         convertstr(result, len, 1);
224 #endif
225
226         PG_RETURN_CSTRING(result);
227 }
228
229
230 /* ========== PUBLIC ROUTINES ========== */
231
232 /*
233  * textlen -
234  *        returns the logical length of a text*
235  *         (which is less than the VARSIZE of the text*)
236  */
237 Datum
238 textlen(PG_FUNCTION_ARGS)
239 {
240         text       *t = PG_GETARG_TEXT_P(0);
241
242 #ifdef MULTIBYTE
243         unsigned char *s;
244         int                     len,
245                                 l,
246                                 wl;
247
248         len = 0;
249         s = VARDATA(t);
250         l = VARSIZE(t) - VARHDRSZ;
251         while (l > 0)
252         {
253                 wl = pg_mblen(s);
254                 l -= wl;
255                 s += wl;
256                 len++;
257         }
258         PG_RETURN_INT32(len);
259 #else
260         PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
261 #endif
262 }
263
264 /*
265  * textoctetlen -
266  *        returns the physical length of a text*
267  *         (which is less than the VARSIZE of the text*)
268  *
269  * XXX is it actually appropriate to return the compressed length
270  * when the value is compressed?  It's not at all clear to me that
271  * this is what SQL92 has in mind ...
272  */
273 Datum
274 textoctetlen(PG_FUNCTION_ARGS)
275 {
276         struct varattrib *t = (struct varattrib *) PG_GETARG_RAW_VARLENA_P(0);
277
278         if (!VARATT_IS_EXTERNAL(t))
279                 PG_RETURN_INT32(VARATT_SIZE(t) - VARHDRSZ);
280
281         PG_RETURN_INT32(t->va_content.va_external.va_extsize);
282 }
283
284 /*
285  * textcat -
286  *        takes two text* and returns a text* that is the concatenation of
287  *        the two.
288  *
289  * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
290  * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
291  * Allocate space for output in all cases.
292  * XXX - thomas 1997-07-10
293  */
294 Datum
295 textcat(PG_FUNCTION_ARGS)
296 {
297         text       *t1 = PG_GETARG_TEXT_P(0);
298         text       *t2 = PG_GETARG_TEXT_P(1);
299         int                     len1,
300                                 len2,
301                                 len;
302         text       *result;
303         char       *ptr;
304
305         len1 = (VARSIZE(t1) - VARHDRSZ);
306         if (len1 < 0)
307                 len1 = 0;
308
309         len2 = (VARSIZE(t2) - VARHDRSZ);
310         if (len2 < 0)
311                 len2 = 0;
312
313         len = len1 + len2 + VARHDRSZ;
314         result = (text *) palloc(len);
315
316         /* Set size of result string... */
317         VARATT_SIZEP(result) = len;
318
319         /* Fill data field of result string... */
320         ptr = VARDATA(result);
321         if (len1 > 0)
322                 memcpy(ptr, VARDATA(t1), len1);
323         if (len2 > 0)
324                 memcpy(ptr + len1, VARDATA(t2), len2);
325
326         PG_RETURN_TEXT_P(result);
327 }
328
329 /*
330  * text_substr()
331  * Return a substring starting at the specified position.
332  * - thomas 1997-12-31
333  *
334  * Input:
335  *      - string
336  *      - starting position (is one-based)
337  *      - string length
338  *
339  * If the starting position is zero or less, then return from the start of the string
340  *      adjusting the length to be consistant with the "negative start" per SQL92.
341  * If the length is less than zero, return the remaining string.
342  *
343  * Note that the arguments operate on octet length,
344  *      so not aware of multi-byte character sets.
345  *
346  * Added multi-byte support.
347  * - Tatsuo Ishii 1998-4-21
348  * Changed behavior if starting position is less than one to conform to SQL92 behavior.
349  * Formerly returned the entire string; now returns a portion.
350  * - Thomas Lockhart 1998-12-10
351  */
352 Datum
353 text_substr(PG_FUNCTION_ARGS)
354 {
355         text       *string = PG_GETARG_TEXT_P(0);
356         int32           m = PG_GETARG_INT32(1);
357         int32           n = PG_GETARG_INT32(2);
358         text       *ret;
359         int                     len;
360
361 #ifdef MULTIBYTE
362         int                     i;
363         char       *p;
364 #endif
365
366         len = VARSIZE(string) - VARHDRSZ;
367 #ifdef MULTIBYTE
368         len = pg_mbstrlen_with_len(VARDATA(string), len);
369 #endif
370
371         /* starting position after the end of the string? */
372         if (m > len)
373         {
374                 m = 1;
375                 n = 0;
376         }
377
378         /*
379          * starting position before the start of the string? then offset into
380          * the string per SQL92 spec...
381          */
382         else if (m < 1)
383         {
384                 n += (m - 1);
385                 m = 1;
386         }
387
388         /* m will now become a zero-based starting position */
389         m--;
390         if (((m + n) > len) || (n < 0))
391                 n = (len - m);
392
393 #ifdef MULTIBYTE
394         p = VARDATA(string);
395         for (i = 0; i < m; i++)
396                 p += pg_mblen(p);
397         m = p - VARDATA(string);
398         for (i = 0; i < n; i++)
399                 p += pg_mblen(p);
400         n = p - (VARDATA(string) + m);
401 #endif
402
403         ret = (text *) palloc(VARHDRSZ + n);
404         VARATT_SIZEP(ret) = VARHDRSZ + n;
405
406         memcpy(VARDATA(ret), VARDATA(string) + m, n);
407
408         PG_RETURN_TEXT_P(ret);
409 }
410
411 /*
412  * textpos -
413  *        Return the position of the specified substring.
414  *        Implements the SQL92 POSITION() function.
415  *        Ref: A Guide To The SQL Standard, Date & Darwen, 1997
416  * - thomas 1997-07-27
417  *
418  * Added multi-byte support.
419  * - Tatsuo Ishii 1998-4-21
420  */
421 Datum
422 textpos(PG_FUNCTION_ARGS)
423 {
424         text       *t1 = PG_GETARG_TEXT_P(0);
425         text       *t2 = PG_GETARG_TEXT_P(1);
426         int                     pos;
427         int                     px,
428                                 p;
429         int                     len1,
430                                 len2;
431         pg_wchar   *p1,
432                            *p2;
433
434 #ifdef MULTIBYTE
435         pg_wchar   *ps1,
436                            *ps2;
437 #endif
438
439         if (VARSIZE(t2) <= VARHDRSZ)
440                 PG_RETURN_INT32(1);             /* result for empty pattern */
441
442         len1 = (VARSIZE(t1) - VARHDRSZ);
443         len2 = (VARSIZE(t2) - VARHDRSZ);
444 #ifdef MULTIBYTE
445         ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
446         (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
447         len1 = pg_wchar_strlen(p1);
448         ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
449         (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
450         len2 = pg_wchar_strlen(p2);
451 #else
452         p1 = VARDATA(t1);
453         p2 = VARDATA(t2);
454 #endif
455         pos = 0;
456         px = (len1 - len2);
457         for (p = 0; p <= px; p++)
458         {
459 #ifdef MULTIBYTE
460                 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
461 #else
462                 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
463 #endif
464                 {
465                         pos = p + 1;
466                         break;
467                 };
468                 p1++;
469         };
470 #ifdef MULTIBYTE
471         pfree(ps1);
472         pfree(ps2);
473 #endif
474         PG_RETURN_INT32(pos);
475 }
476
477 /* varstr_cmp()
478  * Comparison function for text strings with given lengths.
479  * Includes locale support, but must copy strings to temporary memory
480  *      to allow null-termination for inputs to strcoll().
481  * Returns -1, 0 or 1
482  */
483 int
484 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
485 {
486         int                     result;
487         char       *a1p,
488                            *a2p;
489
490 #ifdef USE_LOCALE
491         a1p = (char *) palloc(len1 + 1);
492         a2p = (char *) palloc(len2 + 1);
493
494         memcpy(a1p, arg1, len1);
495         *(a1p + len1) = '\0';
496         memcpy(a2p, arg2, len2);
497         *(a2p + len2) = '\0';
498
499         result = strcoll(a1p, a2p);
500
501         pfree(a1p);
502         pfree(a2p);
503
504 #else
505
506         a1p = arg1;
507         a2p = arg2;
508
509         result = strncmp(a1p, a2p, Min(len1, len2));
510         if ((result == 0) && (len1 != len2))
511                 result = (len1 < len2) ? -1 : 1;
512 #endif
513
514         return result;
515 }
516
517
518 /* text_cmp()
519  * Internal comparison function for text strings.
520  * Returns -1, 0 or 1
521  */
522 static int
523 text_cmp(text *arg1, text *arg2)
524 {
525         char       *a1p,
526                            *a2p;
527         int                     len1,
528                                 len2;
529
530         a1p = VARDATA(arg1);
531         a2p = VARDATA(arg2);
532
533         len1 = VARSIZE(arg1) - VARHDRSZ;
534         len2 = VARSIZE(arg2) - VARHDRSZ;
535
536         return varstr_cmp(a1p, len1, a2p, len2);
537 }
538
539 /*
540  * Comparison functions for text strings.
541  *
542  * Note: btree indexes need these routines not to leak memory; therefore,
543  * be careful to free working copies of toasted datums.  Most places don't
544  * need to be so careful.
545  */
546
547 Datum
548 texteq(PG_FUNCTION_ARGS)
549 {
550         text       *arg1 = PG_GETARG_TEXT_P(0);
551         text       *arg2 = PG_GETARG_TEXT_P(1);
552         bool            result;
553
554         /* fast path for different-length inputs */
555         if (VARSIZE(arg1) != VARSIZE(arg2))
556                 result = false;
557         else
558                 result = (text_cmp(arg1, arg2) == 0);
559
560         PG_FREE_IF_COPY(arg1, 0);
561         PG_FREE_IF_COPY(arg2, 1);
562
563         PG_RETURN_BOOL(result);
564 }
565
566 Datum
567 textne(PG_FUNCTION_ARGS)
568 {
569         text       *arg1 = PG_GETARG_TEXT_P(0);
570         text       *arg2 = PG_GETARG_TEXT_P(1);
571         bool            result;
572
573         /* fast path for different-length inputs */
574         if (VARSIZE(arg1) != VARSIZE(arg2))
575                 result = true;
576         else
577                 result = (text_cmp(arg1, arg2) != 0);
578
579         PG_FREE_IF_COPY(arg1, 0);
580         PG_FREE_IF_COPY(arg2, 1);
581
582         PG_RETURN_BOOL(result);
583 }
584
585 Datum
586 text_lt(PG_FUNCTION_ARGS)
587 {
588         text       *arg1 = PG_GETARG_TEXT_P(0);
589         text       *arg2 = PG_GETARG_TEXT_P(1);
590         bool            result;
591
592         result = (text_cmp(arg1, arg2) < 0);
593
594         PG_FREE_IF_COPY(arg1, 0);
595         PG_FREE_IF_COPY(arg2, 1);
596
597         PG_RETURN_BOOL(result);
598 }
599
600 Datum
601 text_le(PG_FUNCTION_ARGS)
602 {
603         text       *arg1 = PG_GETARG_TEXT_P(0);
604         text       *arg2 = PG_GETARG_TEXT_P(1);
605         bool            result;
606
607         result = (text_cmp(arg1, arg2) <= 0);
608
609         PG_FREE_IF_COPY(arg1, 0);
610         PG_FREE_IF_COPY(arg2, 1);
611
612         PG_RETURN_BOOL(result);
613 }
614
615 Datum
616 text_gt(PG_FUNCTION_ARGS)
617 {
618         text       *arg1 = PG_GETARG_TEXT_P(0);
619         text       *arg2 = PG_GETARG_TEXT_P(1);
620         bool            result;
621
622         result = (text_cmp(arg1, arg2) > 0);
623
624         PG_FREE_IF_COPY(arg1, 0);
625         PG_FREE_IF_COPY(arg2, 1);
626
627         PG_RETURN_BOOL(result);
628 }
629
630 Datum
631 text_ge(PG_FUNCTION_ARGS)
632 {
633         text       *arg1 = PG_GETARG_TEXT_P(0);
634         text       *arg2 = PG_GETARG_TEXT_P(1);
635         bool            result;
636
637         result = (text_cmp(arg1, arg2) >= 0);
638
639         PG_FREE_IF_COPY(arg1, 0);
640         PG_FREE_IF_COPY(arg2, 1);
641
642         PG_RETURN_BOOL(result);
643 }
644
645 Datum
646 bttextcmp(PG_FUNCTION_ARGS)
647 {
648         text       *arg1 = PG_GETARG_TEXT_P(0);
649         text       *arg2 = PG_GETARG_TEXT_P(1);
650         int32           result;
651
652         result = text_cmp(arg1, arg2);
653
654         PG_FREE_IF_COPY(arg1, 0);
655         PG_FREE_IF_COPY(arg2, 1);
656
657         PG_RETURN_INT32(result);
658 }
659
660
661 Datum
662 text_larger(PG_FUNCTION_ARGS)
663 {
664         text       *arg1 = PG_GETARG_TEXT_P(0);
665         text       *arg2 = PG_GETARG_TEXT_P(1);
666         text       *result;
667
668         result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
669
670         PG_RETURN_TEXT_P(result);
671 }
672
673 Datum
674 text_smaller(PG_FUNCTION_ARGS)
675 {
676         text       *arg1 = PG_GETARG_TEXT_P(0);
677         text       *arg2 = PG_GETARG_TEXT_P(1);
678         text       *result;
679
680         result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
681
682         PG_RETURN_TEXT_P(result);
683 }
684
685 /*-------------------------------------------------------------
686  * byteaoctetlen
687  *
688  * get the number of bytes contained in an instance of type 'bytea'
689  *-------------------------------------------------------------
690  */
691 Datum
692 byteaoctetlen(PG_FUNCTION_ARGS)
693 {
694         bytea      *v = PG_GETARG_BYTEA_P(0);
695
696         PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
697 }
698
699 /*
700  * byteacat -
701  *        takes two bytea* and returns a bytea* that is the concatenation of
702  *        the two.
703  *
704  * Cloned from textcat and modified as required.
705  */
706 Datum
707 byteacat(PG_FUNCTION_ARGS)
708 {
709         bytea      *t1 = PG_GETARG_BYTEA_P(0);
710         bytea      *t2 = PG_GETARG_BYTEA_P(1);
711         int                     len1,
712                                 len2,
713                                 len;
714         bytea      *result;
715         char       *ptr;
716
717         len1 = (VARSIZE(t1) - VARHDRSZ);
718         if (len1 < 0)
719                 len1 = 0;
720
721         len2 = (VARSIZE(t2) - VARHDRSZ);
722         if (len2 < 0)
723                 len2 = 0;
724
725         len = len1 + len2 + VARHDRSZ;
726         result = (bytea *) palloc(len);
727
728         /* Set size of result string... */
729         VARATT_SIZEP(result) = len;
730
731         /* Fill data field of result string... */
732         ptr = VARDATA(result);
733         if (len1 > 0)
734                 memcpy(ptr, VARDATA(t1), len1);
735         if (len2 > 0)
736                 memcpy(ptr + len1, VARDATA(t2), len2);
737
738         PG_RETURN_BYTEA_P(result);
739 }
740
741 /*
742  * bytea_substr()
743  * Return a substring starting at the specified position.
744  * Cloned from text_substr and modified as required.
745  *
746  * Input:
747  *      - string
748  *      - starting position (is one-based)
749  *      - string length
750  *
751  * If the starting position is zero or less, then return from the start of the string
752  * adjusting the length to be consistant with the "negative start" per SQL92.
753  * If the length is less than zero, return the remaining string.
754  *
755  */
756 Datum
757 bytea_substr(PG_FUNCTION_ARGS)
758 {
759         bytea      *string = PG_GETARG_BYTEA_P(0);
760         int32           m = PG_GETARG_INT32(1);
761         int32           n = PG_GETARG_INT32(2);
762         bytea      *ret;
763         int                     len;
764
765         len = VARSIZE(string) - VARHDRSZ;
766
767         /* starting position after the end of the string? */
768         if (m > len)
769         {
770                 m = 1;
771                 n = 0;
772         }
773
774         /*
775          * starting position before the start of the string? then offset into
776          * the string per SQL92 spec...
777          */
778         else if (m < 1)
779         {
780                 n += (m - 1);
781                 m = 1;
782         }
783
784         /* m will now become a zero-based starting position */
785         m--;
786         if (((m + n) > len) || (n < 0))
787                 n = (len - m);
788
789         ret = (bytea *) palloc(VARHDRSZ + n);
790         VARATT_SIZEP(ret) = VARHDRSZ + n;
791
792         memcpy(VARDATA(ret), VARDATA(string) + m, n);
793
794         PG_RETURN_BYTEA_P(ret);
795 }
796
797 /*
798  * byteapos -
799  *        Return the position of the specified substring.
800  *        Implements the SQL92 POSITION() function.
801  * Cloned from textpos and modified as required.
802  */
803 Datum
804 byteapos(PG_FUNCTION_ARGS)
805 {
806         bytea      *t1 = PG_GETARG_BYTEA_P(0);
807         bytea      *t2 = PG_GETARG_BYTEA_P(1);
808         int                     pos;
809         int                     px,
810                                 p;
811         int                     len1,
812                                 len2;
813         char       *p1,
814                            *p2;
815
816         if (VARSIZE(t2) <= VARHDRSZ)
817                 PG_RETURN_INT32(1);             /* result for empty pattern */
818
819         len1 = (VARSIZE(t1) - VARHDRSZ);
820         len2 = (VARSIZE(t2) - VARHDRSZ);
821
822         p1 = VARDATA(t1);
823         p2 = VARDATA(t2);
824
825         pos = 0;
826         px = (len1 - len2);
827         for (p = 0; p <= px; p++)
828         {
829                 if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
830                 {
831                         pos = p + 1;
832                         break;
833                 };
834                 p1++;
835         };
836
837         PG_RETURN_INT32(pos);
838 }
839
840 /*-------------------------------------------------------------
841  * byteaGetByte
842  *
843  * this routine treats "bytea" as an array of bytes.
844  * It returns the Nth byte (a number between 0 and 255).
845  *-------------------------------------------------------------
846  */
847 Datum
848 byteaGetByte(PG_FUNCTION_ARGS)
849 {
850         bytea      *v = PG_GETARG_BYTEA_P(0);
851         int32           n = PG_GETARG_INT32(1);
852         int                     len;
853         int                     byte;
854
855         len = VARSIZE(v) - VARHDRSZ;
856
857         if (n < 0 || n >= len)
858                 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
859                          n, len - 1);
860
861         byte = ((unsigned char *) VARDATA(v))[n];
862
863         PG_RETURN_INT32(byte);
864 }
865
866 /*-------------------------------------------------------------
867  * byteaGetBit
868  *
869  * This routine treats a "bytea" type like an array of bits.
870  * It returns the value of the Nth bit (0 or 1).
871  *
872  *-------------------------------------------------------------
873  */
874 Datum
875 byteaGetBit(PG_FUNCTION_ARGS)
876 {
877         bytea      *v = PG_GETARG_BYTEA_P(0);
878         int32           n = PG_GETARG_INT32(1);
879         int                     byteNo,
880                                 bitNo;
881         int                     len;
882         int                     byte;
883
884         len = VARSIZE(v) - VARHDRSZ;
885
886         if (n < 0 || n >= len * 8)
887                 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
888                          n, len * 8 - 1);
889
890         byteNo = n / 8;
891         bitNo = n % 8;
892
893         byte = ((unsigned char *) VARDATA(v))[byteNo];
894
895         if (byte & (1 << bitNo))
896                 PG_RETURN_INT32(1);
897         else
898                 PG_RETURN_INT32(0);
899 }
900
901 /*-------------------------------------------------------------
902  * byteaSetByte
903  *
904  * Given an instance of type 'bytea' creates a new one with
905  * the Nth byte set to the given value.
906  *
907  *-------------------------------------------------------------
908  */
909 Datum
910 byteaSetByte(PG_FUNCTION_ARGS)
911 {
912         bytea      *v = PG_GETARG_BYTEA_P(0);
913         int32           n = PG_GETARG_INT32(1);
914         int32           newByte = PG_GETARG_INT32(2);
915         int                     len;
916         bytea      *res;
917
918         len = VARSIZE(v) - VARHDRSZ;
919
920         if (n < 0 || n >= len)
921                 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
922                          n, len - 1);
923
924         /*
925          * Make a copy of the original varlena.
926          */
927         res = (bytea *) palloc(VARSIZE(v));
928         memcpy((char *) res, (char *) v, VARSIZE(v));
929
930         /*
931          * Now set the byte.
932          */
933         ((unsigned char *) VARDATA(res))[n] = newByte;
934
935         PG_RETURN_BYTEA_P(res);
936 }
937
938 /*-------------------------------------------------------------
939  * byteaSetBit
940  *
941  * Given an instance of type 'bytea' creates a new one with
942  * the Nth bit set to the given value.
943  *
944  *-------------------------------------------------------------
945  */
946 Datum
947 byteaSetBit(PG_FUNCTION_ARGS)
948 {
949         bytea      *v = PG_GETARG_BYTEA_P(0);
950         int32           n = PG_GETARG_INT32(1);
951         int32           newBit = PG_GETARG_INT32(2);
952         bytea      *res;
953         int                     len;
954         int                     oldByte,
955                                 newByte;
956         int                     byteNo,
957                                 bitNo;
958
959         len = VARSIZE(v) - VARHDRSZ;
960
961         if (n < 0 || n >= len * 8)
962                 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
963                          n, len * 8 - 1);
964
965         byteNo = n / 8;
966         bitNo = n % 8;
967
968         /*
969          * sanity check!
970          */
971         if (newBit != 0 && newBit != 1)
972                 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
973
974         /*
975          * Make a copy of the original varlena.
976          */
977         res = (bytea *) palloc(VARSIZE(v));
978         memcpy((char *) res, (char *) v, VARSIZE(v));
979
980         /*
981          * Update the byte.
982          */
983         oldByte = ((unsigned char *) VARDATA(res))[byteNo];
984
985         if (newBit == 0)
986                 newByte = oldByte & (~(1 << bitNo));
987         else
988                 newByte = oldByte | (1 << bitNo);
989
990         ((unsigned char *) VARDATA(res))[byteNo] = newByte;
991
992         PG_RETURN_BYTEA_P(res);
993 }
994
995
996 /* text_name()
997  * Converts a text type to a Name type.
998  */
999 Datum
1000 text_name(PG_FUNCTION_ARGS)
1001 {
1002         text       *s = PG_GETARG_TEXT_P(0);
1003         Name            result;
1004         int                     len;
1005
1006         len = VARSIZE(s) - VARHDRSZ;
1007
1008         /* Truncate oversize input */
1009         if (len >= NAMEDATALEN)
1010                 len = NAMEDATALEN - 1;
1011
1012 #ifdef STRINGDEBUG
1013         printf("text- convert string length %d (%d) ->%d\n",
1014                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1015 #endif
1016
1017         result = (Name) palloc(NAMEDATALEN);
1018         memcpy(NameStr(*result), VARDATA(s), len);
1019
1020         /* now null pad to full length... */
1021         while (len < NAMEDATALEN)
1022         {
1023                 *(NameStr(*result) + len) = '\0';
1024                 len++;
1025         }
1026
1027         PG_RETURN_NAME(result);
1028 }
1029
1030 /* name_text()
1031  * Converts a Name type to a text type.
1032  */
1033 Datum
1034 name_text(PG_FUNCTION_ARGS)
1035 {
1036         Name            s = PG_GETARG_NAME(0);
1037         text       *result;
1038         int                     len;
1039
1040         len = strlen(NameStr(*s));
1041
1042 #ifdef STRINGDEBUG
1043         printf("text- convert string length %d (%d) ->%d\n",
1044                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
1045 #endif
1046
1047         result = palloc(VARHDRSZ + len);
1048         VARATT_SIZEP(result) = VARHDRSZ + len;
1049         memcpy(VARDATA(result), NameStr(*s), len);
1050
1051         PG_RETURN_TEXT_P(result);
1052 }
1053
1054
1055 /*****************************************************************************
1056  *      Comparison Functions used for bytea
1057  *
1058  * Note: btree indexes need these routines not to leak memory; therefore,
1059  * be careful to free working copies of toasted datums.  Most places don't
1060  * need to be so careful.
1061  *****************************************************************************/
1062
1063 Datum
1064 byteaeq(PG_FUNCTION_ARGS)
1065 {
1066         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1067         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1068         int                     len1,
1069                                 len2;
1070         bool            result;
1071
1072         len1 = VARSIZE(arg1) - VARHDRSZ;
1073         len2 = VARSIZE(arg2) - VARHDRSZ;
1074
1075         /* fast path for different-length inputs */
1076         if (len1 != len2)
1077                 result = false;
1078         else
1079                 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
1080
1081         PG_FREE_IF_COPY(arg1, 0);
1082         PG_FREE_IF_COPY(arg2, 1);
1083
1084         PG_RETURN_BOOL(result);
1085 }
1086
1087 Datum
1088 byteane(PG_FUNCTION_ARGS)
1089 {
1090         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1091         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1092         int                     len1,
1093                                 len2;
1094         bool            result;
1095
1096         len1 = VARSIZE(arg1) - VARHDRSZ;
1097         len2 = VARSIZE(arg2) - VARHDRSZ;
1098
1099         /* fast path for different-length inputs */
1100         if (len1 != len2)
1101                 result = true;
1102         else
1103                 result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
1104
1105         PG_FREE_IF_COPY(arg1, 0);
1106         PG_FREE_IF_COPY(arg2, 1);
1107
1108         PG_RETURN_BOOL(result);
1109 }
1110
1111 Datum
1112 bytealt(PG_FUNCTION_ARGS)
1113 {
1114         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1115         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1116         int                     len1,
1117                                 len2;
1118         int                     cmp;
1119
1120         len1 = VARSIZE(arg1) - VARHDRSZ;
1121         len2 = VARSIZE(arg2) - VARHDRSZ;
1122
1123         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1124
1125         PG_FREE_IF_COPY(arg1, 0);
1126         PG_FREE_IF_COPY(arg2, 1);
1127
1128         PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));
1129 }
1130
1131 Datum
1132 byteale(PG_FUNCTION_ARGS)
1133 {
1134         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1135         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1136         int                     len1,
1137                                 len2;
1138         int                     cmp;
1139
1140         len1 = VARSIZE(arg1) - VARHDRSZ;
1141         len2 = VARSIZE(arg2) - VARHDRSZ;
1142
1143         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1144
1145         PG_FREE_IF_COPY(arg1, 0);
1146         PG_FREE_IF_COPY(arg2, 1);
1147
1148         PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));
1149 }
1150
1151 Datum
1152 byteagt(PG_FUNCTION_ARGS)
1153 {
1154         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1155         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1156         int                     len1,
1157                                 len2;
1158         int                     cmp;
1159
1160         len1 = VARSIZE(arg1) - VARHDRSZ;
1161         len2 = VARSIZE(arg2) - VARHDRSZ;
1162
1163         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1164
1165         PG_FREE_IF_COPY(arg1, 0);
1166         PG_FREE_IF_COPY(arg2, 1);
1167
1168         PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));
1169 }
1170
1171 Datum
1172 byteage(PG_FUNCTION_ARGS)
1173 {
1174         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1175         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1176         int                     len1,
1177                                 len2;
1178         int                     cmp;
1179
1180         len1 = VARSIZE(arg1) - VARHDRSZ;
1181         len2 = VARSIZE(arg2) - VARHDRSZ;
1182
1183         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1184
1185         PG_FREE_IF_COPY(arg1, 0);
1186         PG_FREE_IF_COPY(arg2, 1);
1187
1188         PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));
1189 }
1190
1191 Datum
1192 byteacmp(PG_FUNCTION_ARGS)
1193 {
1194         bytea      *arg1 = PG_GETARG_BYTEA_P(0);
1195         bytea      *arg2 = PG_GETARG_BYTEA_P(1);
1196         int                     len1,
1197                                 len2;
1198         int                     cmp;
1199
1200         len1 = VARSIZE(arg1) - VARHDRSZ;
1201         len2 = VARSIZE(arg2) - VARHDRSZ;
1202
1203         cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));
1204         if ((cmp == 0) && (len1 != len2))
1205                 cmp = (len1 < len2) ? -1 : 1;
1206
1207         PG_FREE_IF_COPY(arg1, 0);
1208         PG_FREE_IF_COPY(arg2, 1);
1209
1210         PG_RETURN_INT32(cmp);
1211 }