OSDN Git Service

Fix for text_lt/text_le to avoid warnings if not def USE_LOCALE.
[pg-rex/syncrep.git] / src / backend / utils / adt / varlena.c
1 /*-------------------------------------------------------------------------
2  *
3  * varlena.c--
4  *    Functions for the variable-length built-in types.
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *    $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.14 1997/04/21 04:31:53 vadim Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <ctype.h>
15 #include <string.h>
16
17 #include "postgres.h"
18 #include "utils/palloc.h"
19 #include "utils/builtins.h"     /* where function declarations go */
20
21 /***************************************************************************** 
22  *   USER I/O ROUTINES                                                       *
23  *****************************************************************************/
24
25
26 #define VAL(CH)         ((CH) - '0')
27 #define DIG(VAL)        ((VAL) + '0')
28
29 /*
30  *      byteain         - converts from printable representation of byte array
31  *
32  *      Non-printable characters must be passed as '\nnn' (octal) and are
33  *      converted to internal form.  '\' must be passed as '\\'.
34  *      elog(WARN, ...) if bad form.
35  *
36  *      BUGS:
37  *              The input is scaned twice.
38  *              The error checking of input is minimal.
39  */
40 struct varlena *
41 byteain(char *inputText)
42 {
43     register char       *tp;
44     register char       *rp;
45     register int        byte;
46     struct varlena      *result;
47     
48     if (inputText == NULL)
49         elog(WARN, "Bad input string for type bytea");
50     
51     for (byte = 0, tp = inputText; *tp != '\0'; byte++)
52         if (*tp++ == '\\')
53             {
54                 if (*tp == '\\')
55                     tp++;
56                 else if (!isdigit(*tp++) ||
57                          !isdigit(*tp++) ||
58                          !isdigit(*tp++))
59                     elog(WARN, "Bad input string for type bytea");
60             }
61     tp = inputText;
62     byte += sizeof(int32);                                      /* varlena? */
63     result = (struct varlena *) palloc(byte);
64     result->vl_len = byte;                                      /* varlena? */
65     rp = result->vl_dat;
66     while (*tp != '\0')
67         if (*tp != '\\' || *++tp == '\\')
68             *rp++ = *tp++;
69         else {
70             byte = VAL(*tp++);
71             byte <<= 3;
72             byte += VAL(*tp++);
73             byte <<= 3;
74             *rp++ = byte + VAL(*tp++);
75         }
76     return(result);
77 }
78
79 /*
80  * Shoves a bunch of memory pointed at by bytes into varlena.
81  * BUGS:  Extremely unportable as things shoved can be string
82  * representations of structs, etc.
83  */
84 struct varlena *
85 shove_bytes(unsigned char *stuff, int len)
86 {
87     struct varlena *result;
88     
89     result = (struct varlena *) palloc(len + sizeof(int32));
90     result->vl_len = len;
91     memmove(result->vl_dat, 
92             stuff + sizeof(int32),
93             len - sizeof(int32)); 
94     return(result);
95 }
96
97
98
99 /*
100  *      byteaout        - converts to printable representation of byte array
101  *
102  *      Non-printable characters are inserted as '\nnn' (octal) and '\' as
103  *      '\\'.
104  *
105  *      NULL vlena should be an error--returning string with NULL for now.
106  */
107 char *
108 byteaout(struct varlena *vlena)
109 {
110     register char       *vp;
111     register char       *rp;
112     register int        val;            /* holds unprintable chars */
113     int         i;
114     int         len;
115     static      char    *result;
116     
117     if (vlena == NULL) {
118         result = (char *) palloc(2);
119         result[0] = '-';
120         result[1] = '\0';
121         return(result);
122     }
123     vp = vlena->vl_dat;
124     len = 1;            /* empty string has 1 char */
125     for (i = vlena->vl_len - sizeof(int32); i != 0; i--, vp++)  /* varlena? */
126         if (*vp == '\\')
127             len += 2;
128         else if (isascii(*vp) && isprint(*vp))
129             len++;
130         else
131             len += 4;
132     rp = result = (char *) palloc(len);
133     vp = vlena->vl_dat;
134     for (i = vlena->vl_len - sizeof(int32); i != 0; i--)        /* varlena? */
135         if (*vp == '\\') {
136             vp++;
137             *rp++ = '\\';
138             *rp++ = '\\';
139         } else if (isascii(*vp) && isprint(*vp))
140             *rp++ = *vp++;
141         else {
142             val = *vp++;
143             *rp = '\\';
144             rp += 3;
145             *rp-- = DIG(val & 07);
146             val >>= 3;
147             *rp-- = DIG(val & 07);
148             val >>= 3;
149             *rp = DIG(val & 03);
150             rp += 3;
151         }
152     *rp = '\0';
153     return(result);
154 }
155
156
157 /*
158  *      textin          - converts "..." to internal representation
159  */
160 struct varlena *
161 textin(char *inputText)
162 {
163     struct varlena      *result;
164     int         len;
165     
166     if (inputText == NULL)
167         return(NULL);
168     len = strlen(inputText) + VARHDRSZ;         
169     result = (struct varlena *) palloc(len);
170     VARSIZE(result) = len;
171     memmove(VARDATA(result), inputText, len - VARHDRSZ);        
172     return(result);
173 }
174
175 /*
176  *      textout         - converts internal representation to "..."
177  */
178 char *
179 textout(struct varlena *vlena)
180 {
181     int len;
182     char *result;
183     
184     if (vlena == NULL) {
185         result = (char *) palloc(2);
186         result[0] = '-';
187         result[1] = '\0';
188         return(result);
189     }
190     len = VARSIZE(vlena) - VARHDRSZ;
191     result = (char *) palloc(len + 1);
192     memmove(result, VARDATA(vlena), len);
193     result[len] = '\0';
194     return(result);
195 }
196
197
198 /* ========== PUBLIC ROUTINES ========== */
199
200 /*
201  * textlen -
202  *    returns the actual length of a text* (which may be less than
203  *    the VARSIZE of the text*)
204  */
205
206 int textlen (text* t)
207 {
208     int i = 0;
209     int max = VARSIZE(t) - VARHDRSZ;
210     char *ptr = VARDATA(t);
211     while (i < max && *ptr++)
212         i++;
213     return i;
214 }
215
216 /*
217  * textcat -
218  *    takes two text* and returns a text* that is the concatentation of 
219  *  the two
220  */
221
222 /*
223  * Rewrited by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
224  */
225
226 text* 
227 textcat(text* t1, text* t2)
228 {
229     int len1, len2, newlen;
230     char *ptr;
231     text* result;
232
233     /* Check for NULL strings... */
234     if (t1 == NULL) return t2;
235     if (t2 == NULL) return t1;
236
237     /* Check for ZERO-LENGTH strings... */
238     /* I use <= instead of == , I know - it's paranoia, but... */
239     if((len1 = VARSIZE(t1) - VARHDRSZ) <= 0) return t2;
240     if((len2 = VARSIZE(t2) - VARHDRSZ) <= 0) return t1;
241
242     result = (text *)palloc(newlen = len1 + len2 + VARHDRSZ);
243
244     /* Fill data field of result string... */
245     memcpy(ptr = VARDATA(result), VARDATA(t1), len1);
246     memcpy(ptr + len1, VARDATA(t2), len2);
247
248     /* Set size of result string... */
249     VARSIZE(result) = newlen;
250
251     return result;
252 }
253
254 /*
255  *      texteq          - returns 1 iff arguments are equal
256  *      textne          - returns 1 iff arguments are not equal
257  */
258 bool
259 texteq(struct varlena *arg1, struct varlena *arg2)
260 {
261     register int        len;
262     register char       *a1p, *a2p;
263     
264     if (arg1 == NULL || arg2 == NULL)
265         return((bool) NULL);
266     if ((len = arg1->vl_len) != arg2->vl_len)
267         return((bool) 0);
268     a1p = arg1->vl_dat;
269     a2p = arg2->vl_dat;
270     /*
271      * Varlenas are stored as the total size (data + size variable)
272      * followed by the data.  The size variable is an int32 so the
273      * length of the data is the total length less sizeof(int32)
274      */
275     len -= sizeof(int32);
276     while (len-- != 0)
277         if (*a1p++ != *a2p++)
278             return((bool) 0);
279     return((bool) 1);
280 }
281
282 bool
283 textne(struct varlena *arg1, struct varlena *arg2) 
284 {
285     return((bool) !texteq(arg1, arg2));
286 }
287
288 /* text_lt()
289  * Comparison function for text strings.
290  * Includes locale support, but must copy strings to temporary memory
291  * to allow null-termination for inputs to strcoll().
292  */
293 bool
294 text_lt(struct varlena *arg1, struct varlena *arg2) 
295 {
296     int len;
297 #ifdef UNSIGNED_CHAR_TEXT
298     unsigned
299 #endif
300     char *a1p, *a2p;
301 #ifdef USE_LOCALE
302     int cval;
303 #endif
304     
305     if (arg1 == NULL || arg2 == NULL)
306         return((bool) FALSE);
307     
308     len = (((VARSIZE(arg1) <= VARSIZE(arg2))? VARSIZE(arg1): VARSIZE(arg2))-VARHDRSZ);
309     
310 #ifdef USE_LOCALE
311
312     a1p = palloc (len+1);
313     a2p = palloc (len+1);
314
315     memcpy(a1p, VARDATA(arg1), len);
316     *(a1p+len) = '\0';
317     memcpy(a2p, VARDATA(arg2), len);
318     *(a2p+len) = '\0';
319
320     cval = strcoll(a1p,a2p);
321     
322     pfree (a1p);
323     pfree (a2p);
324
325     return((bool) ( (cval < 0) || 
326                 ( (cval == 0) && (VARSIZE(arg1) < VARSIZE(arg2)) ) ) );
327
328 #else
329
330     a1p = (unsigned char *)VARDATA(arg1);
331     a2p = (unsigned char *)VARDATA(arg2);
332     
333     while (len != 0 && *a1p == *a2p) {
334         a1p++;
335         a2p++;
336         len--;
337     };
338     return((bool) (len? (*a1p < *a2p): (VARSIZE(arg1) < VARSIZE(arg2))));
339
340 #endif
341
342 } /* text_lt() */
343
344 /* text_le()
345  * Comparison function for text strings.
346  * Includes locale support, but must copy strings to temporary memory
347  * to allow null-termination for inputs to strcoll().
348  */
349 bool
350 text_le(struct varlena *arg1, struct varlena *arg2) 
351 {
352     int len;
353 #ifdef UNSIGNED_CHAR_TEXT
354     unsigned
355 #endif
356     char *a1p, *a2p;
357 #ifdef USE_LOCALE
358     int cval;
359 #endif
360     
361     if (arg1 == NULL || arg2 == NULL)
362         return((bool) 0);
363     
364     len = (((VARSIZE(arg1) <= VARSIZE(arg2))? VARSIZE(arg1): VARSIZE(arg2))-VARHDRSZ);
365     
366 #ifdef USE_LOCALE
367
368     a1p = palloc (len+1);
369     a2p = palloc (len+1);
370
371     memcpy(a1p, VARDATA(arg1), len);
372     *(a1p+len) = '\0';
373     memcpy(a2p, VARDATA(arg2), len);
374     *(a2p+len) = '\0';
375
376     cval = strcoll(a1p,a2p);
377     
378     pfree (a1p);
379     pfree (a2p);
380
381     return ((bool) ( (cval < 0) || 
382                 ( (cval == 0) && (VARSIZE(arg1) <= VARSIZE(arg2)) ) ) );
383
384 #else
385
386     a1p = (unsigned char *)VARDATA(arg1);
387     a2p = (unsigned char *)VARDATA(arg2);
388     
389     while (len != 0 && *a1p == *a2p) {
390         a1p++;
391         a2p++;
392         len--;
393     };
394
395     return((bool) (len? (*a1p <= *a2p): (VARSIZE(arg1) <= VARSIZE(arg2))));
396
397 #endif
398
399 } /* text_le() */
400
401 bool
402 text_gt(struct varlena *arg1, struct varlena *arg2) 
403 {
404     return ((bool) !text_le(arg1, arg2));
405 }
406
407 bool
408 text_ge(struct varlena *arg1, struct varlena *arg2) 
409 {
410     return ((bool) !text_lt(arg1, arg2));
411 }
412
413 /*-------------------------------------------------------------
414  * byteaGetSize
415  *
416  * get the number of bytes contained in an instance of type 'bytea'
417  *-------------------------------------------------------------
418  */
419 int32
420 byteaGetSize(struct varlena *v)
421 {
422     register int len;
423     
424     len = v->vl_len - sizeof(v->vl_len);
425     
426     return(len);
427 }
428
429 /*-------------------------------------------------------------
430  * byteaGetByte
431  *
432  * this routine treats "bytea" as an array of bytes.
433  * It returns the Nth byte (a number between 0 and 255) or
434  * it dies if the length of this array is less than n.
435  *-------------------------------------------------------------
436  */
437 int32
438 byteaGetByte(struct varlena *v, int32 n)
439 {
440     int len;
441     int byte;
442     
443     len = byteaGetSize(v);
444     
445     if (n>=len) {
446         elog(WARN, "byteaGetByte: index (=%d) out of range [0..%d]",
447              n,len-1);
448     }
449     
450     byte = (unsigned char) (v->vl_dat[n]);
451     
452     return((int32) byte);
453 }
454
455 /*-------------------------------------------------------------
456  * byteaGetBit
457  *
458  * This routine treats a "bytea" type like an array of bits.
459  * It returns the value of the Nth bit (0 or 1).
460  * If 'n' is out of range, it dies!
461  *
462  *-------------------------------------------------------------
463  */
464 int32
465 byteaGetBit(struct varlena *v, int32 n)
466 {
467     int byteNo, bitNo;
468     int byte;
469     
470     byteNo = n/8;
471     bitNo = n%8;
472     
473     byte = byteaGetByte(v, byteNo);
474     
475     if (byte & (1<<bitNo)) {
476         return((int32)1);
477     } else {
478         return((int32)0);
479     }
480 }
481 /*-------------------------------------------------------------
482  * byteaSetByte
483  *
484  * Given an instance of type 'bytea' creates a new one with
485  * the Nth byte set to the given value.
486  *
487  *-------------------------------------------------------------
488  */
489 struct varlena *
490 byteaSetByte(struct varlena *v, int32 n, int32 newByte)
491 {
492     int len;
493     struct varlena *res;
494     
495     len = byteaGetSize(v);
496     
497     if (n>=len) {
498         elog(WARN,
499              "byteaSetByte: index (=%d) out of range [0..%d]",
500              n, len-1);
501     }
502     
503     /*
504      * Make a copy of the original varlena.
505      */
506     res = (struct varlena *) palloc(VARSIZE(v));
507     if (res==NULL) {
508         elog(WARN, "byteaSetByte: Out of memory (%d bytes requested)",
509              VARSIZE(v));
510     }
511     memmove((char *)res, (char *)v, VARSIZE(v));
512     
513     /*
514      *  Now set the byte.
515      */
516     res->vl_dat[n] = newByte;
517     
518     return(res);
519 }
520
521 /*-------------------------------------------------------------
522  * byteaSetBit
523  *
524  * Given an instance of type 'bytea' creates a new one with
525  * the Nth bit set to the given value.
526  *
527  *-------------------------------------------------------------
528  */
529 struct varlena *
530 byteaSetBit(struct varlena *v, int32 n, int32 newBit)
531 {
532     struct varlena *res;
533     int oldByte, newByte;
534     int byteNo, bitNo;
535     
536     /*
537      * sanity check!
538      */
539     if (newBit != 0 && newBit != 1) {
540         elog(WARN, "byteaSetByte: new bit must be 0 or 1");
541     }
542     
543     /*
544      * get the byte where the bit we want is stored.
545      */
546     byteNo = n / 8;
547     bitNo = n % 8;
548     oldByte = byteaGetByte(v, byteNo);
549     
550     /*
551      * calculate the new value for that byte
552      */
553     if (newBit == 0) {
554         newByte = oldByte & (~(1<<bitNo));
555     } else {
556         newByte = oldByte | (1<<bitNo);
557     }
558     
559     /*
560      * NOTE: 'byteaSetByte' creates a copy of 'v' & sets the byte.
561      */
562     res = byteaSetByte(v, byteNo, newByte);
563     
564     return(res);
565 }