]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/varlena.c
pgindent run. Make it all clean.
[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.69 2001/03/22 03:59:55 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++ == '\\')
57                 {
58                         if (*tp == '\\')
59                                 tp++;
60                         else if (!isdigit((unsigned char) *tp++) ||
61                                          !isdigit((unsigned char) *tp++) ||
62                                          !isdigit((unsigned char) *tp++))
63                                 elog(ERROR, "Bad input string for type bytea");
64                 }
65         }
66
67         byte += VARHDRSZ;
68         result = (bytea *) palloc(byte);
69         result->vl_len = byte;          /* set varlena length */
70
71         tp = inputText;
72         rp = result->vl_dat;
73         while (*tp != '\0')
74         {
75                 if (*tp != '\\' || *++tp == '\\')
76                         *rp++ = *tp++;
77                 else
78                 {
79                         byte = VAL(*tp++);
80                         byte <<= 3;
81                         byte += VAL(*tp++);
82                         byte <<= 3;
83                         *rp++ = byte + VAL(*tp++);
84                 }
85         }
86
87         PG_RETURN_BYTEA_P(result);
88 }
89
90 /*
91  *              byteaout                - converts to printable representation of byte array
92  *
93  *              Non-printable characters are inserted as '\nnn' (octal) and '\' as
94  *              '\\'.
95  *
96  *              NULL vlena should be an error--returning string with NULL for now.
97  */
98 Datum
99 byteaout(PG_FUNCTION_ARGS)
100 {
101         bytea      *vlena = PG_GETARG_BYTEA_P(0);
102         char       *result;
103         char       *vp;
104         char       *rp;
105         int                     val;                    /* holds unprintable chars */
106         int                     i;
107         int                     len;
108
109         len = 1;                                        /* empty string has 1 char */
110         vp = vlena->vl_dat;
111         for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
112         {
113                 if (*vp == '\\')
114                         len += 2;
115                 else if (isprint((unsigned char) *vp))
116                         len++;
117                 else
118                         len += 4;
119         }
120         rp = result = (char *) palloc(len);
121         vp = vlena->vl_dat;
122         for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
123         {
124                 if (*vp == '\\')
125                 {
126                         *rp++ = '\\';
127                         *rp++ = '\\';
128                 }
129                 else if (isprint((unsigned char) *vp))
130                         *rp++ = *vp;
131                 else
132                 {
133                         val = *vp;
134                         rp[0] = '\\';
135                         rp[3] = DIG(val & 07);
136                         val >>= 3;
137                         rp[2] = DIG(val & 07);
138                         val >>= 3;
139                         rp[1] = DIG(val & 03);
140                         rp += 4;
141                 }
142         }
143         *rp = '\0';
144         PG_RETURN_CSTRING(result);
145 }
146
147
148 /*
149  *              textin                  - converts "..." to internal representation
150  */
151 Datum
152 textin(PG_FUNCTION_ARGS)
153 {
154         char       *inputText = PG_GETARG_CSTRING(0);
155         text       *result;
156         int                     len;
157
158         len = strlen(inputText) + VARHDRSZ;
159         result = (text *) palloc(len);
160         VARATT_SIZEP(result) = len;
161
162         memcpy(VARDATA(result), inputText, len - VARHDRSZ);
163
164 #ifdef CYR_RECODE
165         convertstr(VARDATA(result), len - VARHDRSZ, 0);
166 #endif
167
168         PG_RETURN_TEXT_P(result);
169 }
170
171 /*
172  *              textout                 - converts internal representation to "..."
173  */
174 Datum
175 textout(PG_FUNCTION_ARGS)
176 {
177         text       *t = PG_GETARG_TEXT_P(0);
178         int                     len;
179         char       *result;
180
181         len = VARSIZE(t) - VARHDRSZ;
182         result = (char *) palloc(len + 1);
183         memcpy(result, VARDATA(t), len);
184         result[len] = '\0';
185
186 #ifdef CYR_RECODE
187         convertstr(result, len, 1);
188 #endif
189
190         PG_RETURN_CSTRING(result);
191 }
192
193
194 /* ========== PUBLIC ROUTINES ========== */
195
196 /*
197  * textlen -
198  *        returns the logical length of a text*
199  *         (which is less than the VARSIZE of the text*)
200  */
201 Datum
202 textlen(PG_FUNCTION_ARGS)
203 {
204         text       *t = PG_GETARG_TEXT_P(0);
205
206 #ifdef MULTIBYTE
207         unsigned char *s;
208         int                     len,
209                                 l,
210                                 wl;
211
212         len = 0;
213         s = VARDATA(t);
214         l = VARSIZE(t) - VARHDRSZ;
215         while (l > 0)
216         {
217                 wl = pg_mblen(s);
218                 l -= wl;
219                 s += wl;
220                 len++;
221         }
222         PG_RETURN_INT32(len);
223 #else
224         PG_RETURN_INT32(VARSIZE(t) - VARHDRSZ);
225 #endif
226 }
227
228 /*
229  * textoctetlen -
230  *        returns the physical length of a text*
231  *         (which is less than the VARSIZE of the text*)
232  *
233  * XXX is it actually appropriate to return the compressed length
234  * when the value is compressed?  It's not at all clear to me that
235  * this is what SQL92 has in mind ...
236  */
237 Datum
238 textoctetlen(PG_FUNCTION_ARGS)
239 {
240         struct varattrib *t = (struct varattrib *) PG_GETARG_RAW_VARLENA_P(0);
241
242         if (!VARATT_IS_EXTERNAL(t))
243                 PG_RETURN_INT32(VARATT_SIZE(t) - VARHDRSZ);
244
245         PG_RETURN_INT32(t->va_content.va_external.va_extsize);
246 }
247
248 /*
249  * textcat -
250  *        takes two text* and returns a text* that is the concatenation of
251  *        the two.
252  *
253  * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
254  * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
255  * Allocate space for output in all cases.
256  * XXX - thomas 1997-07-10
257  */
258 Datum
259 textcat(PG_FUNCTION_ARGS)
260 {
261         text       *t1 = PG_GETARG_TEXT_P(0);
262         text       *t2 = PG_GETARG_TEXT_P(1);
263         int                     len1,
264                                 len2,
265                                 len;
266         text       *result;
267         char       *ptr;
268
269         len1 = (VARSIZE(t1) - VARHDRSZ);
270         if (len1 < 0)
271                 len1 = 0;
272
273         len2 = (VARSIZE(t2) - VARHDRSZ);
274         if (len2 < 0)
275                 len2 = 0;
276
277         len = len1 + len2 + VARHDRSZ;
278         result = (text *) palloc(len);
279
280         /* Set size of result string... */
281         VARATT_SIZEP(result) = len;
282
283         /* Fill data field of result string... */
284         ptr = VARDATA(result);
285         if (len1 > 0)
286                 memcpy(ptr, VARDATA(t1), len1);
287         if (len2 > 0)
288                 memcpy(ptr + len1, VARDATA(t2), len2);
289
290         PG_RETURN_TEXT_P(result);
291 }
292
293 /*
294  * text_substr()
295  * Return a substring starting at the specified position.
296  * - thomas 1997-12-31
297  *
298  * Input:
299  *      - string
300  *      - starting position (is one-based)
301  *      - string length
302  *
303  * If the starting position is zero or less, then return from the start of the string
304  *      adjusting the length to be consistant with the "negative start" per SQL92.
305  * If the length is less than zero, return the remaining string.
306  *
307  * Note that the arguments operate on octet length,
308  *      so not aware of multi-byte character sets.
309  *
310  * Added multi-byte support.
311  * - Tatsuo Ishii 1998-4-21
312  * Changed behavior if starting position is less than one to conform to SQL92 behavior.
313  * Formerly returned the entire string; now returns a portion.
314  * - Thomas Lockhart 1998-12-10
315  */
316 Datum
317 text_substr(PG_FUNCTION_ARGS)
318 {
319         text       *string = PG_GETARG_TEXT_P(0);
320         int32           m = PG_GETARG_INT32(1);
321         int32           n = PG_GETARG_INT32(2);
322         text       *ret;
323         int                     len;
324
325 #ifdef MULTIBYTE
326         int                     i;
327         char       *p;
328
329 #endif
330
331         len = VARSIZE(string) - VARHDRSZ;
332 #ifdef MULTIBYTE
333         len = pg_mbstrlen_with_len(VARDATA(string), len);
334 #endif
335
336         /* starting position after the end of the string? */
337         if (m > len)
338         {
339                 m = 1;
340                 n = 0;
341         }
342
343         /*
344          * starting position before the start of the string? then offset into
345          * the string per SQL92 spec...
346          */
347         else if (m < 1)
348         {
349                 n += (m - 1);
350                 m = 1;
351         }
352
353         /* m will now become a zero-based starting position */
354         m--;
355         if (((m + n) > len) || (n < 0))
356                 n = (len - m);
357
358 #ifdef MULTIBYTE
359         p = VARDATA(string);
360         for (i = 0; i < m; i++)
361                 p += pg_mblen(p);
362         m = p - VARDATA(string);
363         for (i = 0; i < n; i++)
364                 p += pg_mblen(p);
365         n = p - (VARDATA(string) + m);
366 #endif
367
368         ret = (text *) palloc(VARHDRSZ + n);
369         VARATT_SIZEP(ret) = VARHDRSZ + n;
370
371         memcpy(VARDATA(ret), VARDATA(string) + m, n);
372
373         PG_RETURN_TEXT_P(ret);
374 }
375
376 /*
377  * textpos -
378  *        Return the position of the specified substring.
379  *        Implements the SQL92 POSITION() function.
380  *        Ref: A Guide To The SQL Standard, Date & Darwen, 1997
381  * - thomas 1997-07-27
382  *
383  * Added multi-byte support.
384  * - Tatsuo Ishii 1998-4-21
385  */
386 Datum
387 textpos(PG_FUNCTION_ARGS)
388 {
389         text       *t1 = PG_GETARG_TEXT_P(0);
390         text       *t2 = PG_GETARG_TEXT_P(1);
391         int                     pos;
392         int                     px,
393                                 p;
394         int                     len1,
395                                 len2;
396         pg_wchar   *p1,
397                            *p2;
398
399 #ifdef MULTIBYTE
400         pg_wchar   *ps1,
401                            *ps2;
402
403 #endif
404
405         if (VARSIZE(t2) <= VARHDRSZ)
406                 PG_RETURN_INT32(1);             /* result for empty pattern */
407
408         len1 = (VARSIZE(t1) - VARHDRSZ);
409         len2 = (VARSIZE(t2) - VARHDRSZ);
410 #ifdef MULTIBYTE
411         ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
412         (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
413         len1 = pg_wchar_strlen(p1);
414         ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
415         (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
416         len2 = pg_wchar_strlen(p2);
417 #else
418         p1 = VARDATA(t1);
419         p2 = VARDATA(t2);
420 #endif
421         pos = 0;
422         px = (len1 - len2);
423         for (p = 0; p <= px; p++)
424         {
425 #ifdef MULTIBYTE
426                 if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
427 #else
428                 if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
429 #endif
430                 {
431                         pos = p + 1;
432                         break;
433                 };
434                 p1++;
435         };
436 #ifdef MULTIBYTE
437         pfree(ps1);
438         pfree(ps2);
439 #endif
440         PG_RETURN_INT32(pos);
441 }
442
443 /*
444  *              texteq                  - returns true iff arguments are equal
445  *              textne                  - returns true iff arguments are not equal
446  *
447  * Note: btree indexes need these routines not to leak memory; therefore,
448  * be careful to free working copies of toasted datums.  Most places don't
449  * need to be so careful.
450  */
451 Datum
452 texteq(PG_FUNCTION_ARGS)
453 {
454         text       *arg1 = PG_GETARG_TEXT_P(0);
455         text       *arg2 = PG_GETARG_TEXT_P(1);
456         bool            result;
457
458         if (VARSIZE(arg1) != VARSIZE(arg2))
459                 result = false;
460         else
461         {
462                 int                     len;
463                 char       *a1p,
464                                    *a2p;
465
466                 len = VARSIZE(arg1) - VARHDRSZ;
467
468                 a1p = VARDATA(arg1);
469                 a2p = VARDATA(arg2);
470
471                 result = (memcmp(a1p, a2p, len) == 0);
472         }
473
474         PG_FREE_IF_COPY(arg1, 0);
475         PG_FREE_IF_COPY(arg2, 1);
476
477         PG_RETURN_BOOL(result);
478 }
479
480 Datum
481 textne(PG_FUNCTION_ARGS)
482 {
483         text       *arg1 = PG_GETARG_TEXT_P(0);
484         text       *arg2 = PG_GETARG_TEXT_P(1);
485         bool            result;
486
487         if (VARSIZE(arg1) != VARSIZE(arg2))
488                 result = true;
489         else
490         {
491                 int                     len;
492                 char       *a1p,
493                                    *a2p;
494
495                 len = VARSIZE(arg1) - VARHDRSZ;
496
497                 a1p = VARDATA(arg1);
498                 a2p = VARDATA(arg2);
499
500                 result = (memcmp(a1p, a2p, len) != 0);
501         }
502
503         PG_FREE_IF_COPY(arg1, 0);
504         PG_FREE_IF_COPY(arg2, 1);
505
506         PG_RETURN_BOOL(result);
507 }
508
509 /* varstr_cmp()
510  * Comparison function for text strings with given lengths.
511  * Includes locale support, but must copy strings to temporary memory
512  *      to allow null-termination for inputs to strcoll().
513  * Returns -1, 0 or 1
514  */
515 int
516 varstr_cmp(char *arg1, int len1, char *arg2, int len2)
517 {
518         int                     result;
519         char       *a1p,
520                            *a2p;
521
522 #ifdef USE_LOCALE
523         a1p = (unsigned char *) palloc(len1 + 1);
524         a2p = (unsigned char *) palloc(len2 + 1);
525
526         memcpy(a1p, arg1, len1);
527         *(a1p + len1) = '\0';
528         memcpy(a2p, arg2, len2);
529         *(a2p + len2) = '\0';
530
531         result = strcoll(a1p, a2p);
532
533         pfree(a1p);
534         pfree(a2p);
535
536 #else
537
538         a1p = arg1;
539         a2p = arg2;
540
541         result = strncmp(a1p, a2p, Min(len1, len2));
542         if ((result == 0) && (len1 != len2))
543                 result = (len1 < len2) ? -1 : 1;
544 #endif
545
546         return result;
547 }
548
549
550 /* text_cmp()
551  * Comparison function for text strings.
552  * Includes locale support, but must copy strings to temporary memory
553  *      to allow null-termination for inputs to strcoll().
554  * XXX HACK code for textlen() indicates that there can be embedded nulls
555  *      but it appears that most routines (incl. this one) assume not! - tgl 97/04/07
556  * Returns -1, 0 or 1
557  */
558 static int
559 text_cmp(text *arg1, text *arg2)
560 {
561         char       *a1p,
562                            *a2p;
563         int                     len1,
564                                 len2;
565
566         a1p = VARDATA(arg1);
567         a2p = VARDATA(arg2);
568
569         len1 = VARSIZE(arg1) - VARHDRSZ;
570         len2 = VARSIZE(arg2) - VARHDRSZ;
571
572         return varstr_cmp(a1p, len1, a2p, len2);
573 }
574
575 /*
576  * Comparison functions for text strings.
577  *
578  * Note: btree indexes need these routines not to leak memory; therefore,
579  * be careful to free working copies of toasted datums.  Most places don't
580  * need to be so careful.
581  */
582
583 Datum
584 text_lt(PG_FUNCTION_ARGS)
585 {
586         text       *arg1 = PG_GETARG_TEXT_P(0);
587         text       *arg2 = PG_GETARG_TEXT_P(1);
588         bool            result;
589
590         result = (text_cmp(arg1, arg2) < 0);
591
592         PG_FREE_IF_COPY(arg1, 0);
593         PG_FREE_IF_COPY(arg2, 1);
594
595         PG_RETURN_BOOL(result);
596 }
597
598 Datum
599 text_le(PG_FUNCTION_ARGS)
600 {
601         text       *arg1 = PG_GETARG_TEXT_P(0);
602         text       *arg2 = PG_GETARG_TEXT_P(1);
603         bool            result;
604
605         result = (text_cmp(arg1, arg2) <= 0);
606
607         PG_FREE_IF_COPY(arg1, 0);
608         PG_FREE_IF_COPY(arg2, 1);
609
610         PG_RETURN_BOOL(result);
611 }
612
613 Datum
614 text_gt(PG_FUNCTION_ARGS)
615 {
616         text       *arg1 = PG_GETARG_TEXT_P(0);
617         text       *arg2 = PG_GETARG_TEXT_P(1);
618         bool            result;
619
620         result = (text_cmp(arg1, arg2) > 0);
621
622         PG_FREE_IF_COPY(arg1, 0);
623         PG_FREE_IF_COPY(arg2, 1);
624
625         PG_RETURN_BOOL(result);
626 }
627
628 Datum
629 text_ge(PG_FUNCTION_ARGS)
630 {
631         text       *arg1 = PG_GETARG_TEXT_P(0);
632         text       *arg2 = PG_GETARG_TEXT_P(1);
633         bool            result;
634
635         result = (text_cmp(arg1, arg2) >= 0);
636
637         PG_FREE_IF_COPY(arg1, 0);
638         PG_FREE_IF_COPY(arg2, 1);
639
640         PG_RETURN_BOOL(result);
641 }
642
643 Datum
644 text_larger(PG_FUNCTION_ARGS)
645 {
646         text       *arg1 = PG_GETARG_TEXT_P(0);
647         text       *arg2 = PG_GETARG_TEXT_P(1);
648         text       *result;
649
650         result = ((text_cmp(arg1, arg2) > 0) ? arg1 : arg2);
651
652         PG_RETURN_TEXT_P(result);
653 }
654
655 Datum
656 text_smaller(PG_FUNCTION_ARGS)
657 {
658         text       *arg1 = PG_GETARG_TEXT_P(0);
659         text       *arg2 = PG_GETARG_TEXT_P(1);
660         text       *result;
661
662         result = ((text_cmp(arg1, arg2) < 0) ? arg1 : arg2);
663
664         PG_RETURN_TEXT_P(result);
665 }
666
667 /*-------------------------------------------------------------
668  * byteaoctetlen
669  *
670  * get the number of bytes contained in an instance of type 'bytea'
671  *-------------------------------------------------------------
672  */
673 Datum
674 byteaoctetlen(PG_FUNCTION_ARGS)
675 {
676         bytea      *v = PG_GETARG_BYTEA_P(0);
677
678         PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
679 }
680
681 /*-------------------------------------------------------------
682  * byteaGetByte
683  *
684  * this routine treats "bytea" as an array of bytes.
685  * It returns the Nth byte (a number between 0 and 255).
686  *-------------------------------------------------------------
687  */
688 Datum
689 byteaGetByte(PG_FUNCTION_ARGS)
690 {
691         bytea      *v = PG_GETARG_BYTEA_P(0);
692         int32           n = PG_GETARG_INT32(1);
693         int                     len;
694         int                     byte;
695
696         len = VARSIZE(v) - VARHDRSZ;
697
698         if (n < 0 || n >= len)
699                 elog(ERROR, "byteaGetByte: index %d out of range [0..%d]",
700                          n, len - 1);
701
702         byte = ((unsigned char *) VARDATA(v))[n];
703
704         PG_RETURN_INT32(byte);
705 }
706
707 /*-------------------------------------------------------------
708  * byteaGetBit
709  *
710  * This routine treats a "bytea" type like an array of bits.
711  * It returns the value of the Nth bit (0 or 1).
712  *
713  *-------------------------------------------------------------
714  */
715 Datum
716 byteaGetBit(PG_FUNCTION_ARGS)
717 {
718         bytea      *v = PG_GETARG_BYTEA_P(0);
719         int32           n = PG_GETARG_INT32(1);
720         int                     byteNo,
721                                 bitNo;
722         int                     len;
723         int                     byte;
724
725         len = VARSIZE(v) - VARHDRSZ;
726
727         if (n < 0 || n >= len * 8)
728                 elog(ERROR, "byteaGetBit: index %d out of range [0..%d]",
729                          n, len * 8 - 1);
730
731         byteNo = n / 8;
732         bitNo = n % 8;
733
734         byte = ((unsigned char *) VARDATA(v))[byteNo];
735
736         if (byte & (1 << bitNo))
737                 PG_RETURN_INT32(1);
738         else
739                 PG_RETURN_INT32(0);
740 }
741
742 /*-------------------------------------------------------------
743  * byteaSetByte
744  *
745  * Given an instance of type 'bytea' creates a new one with
746  * the Nth byte set to the given value.
747  *
748  *-------------------------------------------------------------
749  */
750 Datum
751 byteaSetByte(PG_FUNCTION_ARGS)
752 {
753         bytea      *v = PG_GETARG_BYTEA_P(0);
754         int32           n = PG_GETARG_INT32(1);
755         int32           newByte = PG_GETARG_INT32(2);
756         int                     len;
757         bytea      *res;
758
759         len = VARSIZE(v) - VARHDRSZ;
760
761         if (n < 0 || n >= len)
762                 elog(ERROR, "byteaSetByte: index %d out of range [0..%d]",
763                          n, len - 1);
764
765         /*
766          * Make a copy of the original varlena.
767          */
768         res = (bytea *) palloc(VARSIZE(v));
769         memcpy((char *) res, (char *) v, VARSIZE(v));
770
771         /*
772          * Now set the byte.
773          */
774         ((unsigned char *) VARDATA(res))[n] = newByte;
775
776         PG_RETURN_BYTEA_P(res);
777 }
778
779 /*-------------------------------------------------------------
780  * byteaSetBit
781  *
782  * Given an instance of type 'bytea' creates a new one with
783  * the Nth bit set to the given value.
784  *
785  *-------------------------------------------------------------
786  */
787 Datum
788 byteaSetBit(PG_FUNCTION_ARGS)
789 {
790         bytea      *v = PG_GETARG_BYTEA_P(0);
791         int32           n = PG_GETARG_INT32(1);
792         int32           newBit = PG_GETARG_INT32(2);
793         bytea      *res;
794         int                     len;
795         int                     oldByte,
796                                 newByte;
797         int                     byteNo,
798                                 bitNo;
799
800         len = VARSIZE(v) - VARHDRSZ;
801
802         if (n < 0 || n >= len * 8)
803                 elog(ERROR, "byteaSetBit: index %d out of range [0..%d]",
804                          n, len * 8 - 1);
805
806         byteNo = n / 8;
807         bitNo = n % 8;
808
809         /*
810          * sanity check!
811          */
812         if (newBit != 0 && newBit != 1)
813                 elog(ERROR, "byteaSetBit: new bit must be 0 or 1");
814
815         /*
816          * Make a copy of the original varlena.
817          */
818         res = (bytea *) palloc(VARSIZE(v));
819         memcpy((char *) res, (char *) v, VARSIZE(v));
820
821         /*
822          * Update the byte.
823          */
824         oldByte = ((unsigned char *) VARDATA(res))[byteNo];
825
826         if (newBit == 0)
827                 newByte = oldByte & (~(1 << bitNo));
828         else
829                 newByte = oldByte | (1 << bitNo);
830
831         ((unsigned char *) VARDATA(res))[byteNo] = newByte;
832
833         PG_RETURN_BYTEA_P(res);
834 }
835
836
837 /* text_name()
838  * Converts a text type to a Name type.
839  */
840 Datum
841 text_name(PG_FUNCTION_ARGS)
842 {
843         text       *s = PG_GETARG_TEXT_P(0);
844         Name            result;
845         int                     len;
846
847         len = VARSIZE(s) - VARHDRSZ;
848
849         /* Truncate oversize input */
850         if (len >= NAMEDATALEN)
851                 len = NAMEDATALEN - 1;
852
853 #ifdef STRINGDEBUG
854         printf("text- convert string length %d (%d) ->%d\n",
855                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
856 #endif
857
858         result = (Name) palloc(NAMEDATALEN);
859         memcpy(NameStr(*result), VARDATA(s), len);
860
861         /* now null pad to full length... */
862         while (len < NAMEDATALEN)
863         {
864                 *(NameStr(*result) + len) = '\0';
865                 len++;
866         }
867
868         PG_RETURN_NAME(result);
869 }
870
871 /* name_text()
872  * Converts a Name type to a text type.
873  */
874 Datum
875 name_text(PG_FUNCTION_ARGS)
876 {
877         Name            s = PG_GETARG_NAME(0);
878         text       *result;
879         int                     len;
880
881         len = strlen(NameStr(*s));
882
883 #ifdef STRINGDEBUG
884         printf("text- convert string length %d (%d) ->%d\n",
885                    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
886 #endif
887
888         result = palloc(VARHDRSZ + len);
889         VARATT_SIZEP(result) = VARHDRSZ + len;
890         memcpy(VARDATA(result), NameStr(*s), len);
891
892         PG_RETURN_TEXT_P(result);
893 }