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