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