libpqtypes - utils.c

Home Page

array.c
datetime.c
error.c
events.c
exec.c
geo.c
getaddrinfo.h
handler.c
libpqtypes-int.h
libpqtypes.h
misc.c
network.c
numerics.c
param.c
port.c
record.c
regression-test.c
spec.c
utils.c
varlena.c
  1 
  2 /*
  3  * util.c
  4  *   Utility functions.
  5  *
  6  * Copyright (c) 2011 eSilo, LLC. All rights reserved.
  7  * This is free software; see the source for copying conditions.  There is
  8  * NO warranty; not even for MERCHANTABILITY or  FITNESS FOR A  PARTICULAR
  9  * PURPOSE.
 10  */
 11 
 12 #include "libpqtypes-int.h"
 13 
 14 PGresult *
 15 pqt_copyresult(PGtypeArgs *args, int nattrs)
 16 {
 17   int i;
 18   PGresult *res;
 19   int tableid, columnid, format;
 20   PGresAttDesc *ad = (PGresAttDesc *) malloc(nattrs * sizeof(PGresAttDesc));
 21 
 22   if (!ad)
 23   {
 24     PQseterror(PQT_OUTOFMEMORY);
 25     return NULL;
 26   }
 27 
 28   tableid  = PQftable(args->get.result, args->get.field_num);
 29   columnid = PQftablecol(args->get.result, args->get.field_num);
 30   format   = PQfformat(args->get.result, args->get.field_num);
 31 
 32   for (i=0; i < nattrs; i++)
 33   {
 34     ad[i].tableid  = tableid;
 35     ad[i].columnid = columnid;
 36     ad[i].format   = format;
 37 
 38     /* simple array */
 39     if (args->typhandler->nattrs == 0)
 40     {
 41       ad[i].typid     = args->typhandler->typoid;
 42       ad[i].typlen    = args->typhandler->typlen;
 43       ad[i].name      = NULL;
 44       ad[i].atttypmod = -1;
 45     }
 46     /* composite/record */
 47     else
 48     {
 49       ad[i].typid     = args->typhandler->attDescs[i].attoid;
 50       ad[i].typlen    = args->typhandler->attDescs[i].attlen;
 51       ad[i].name      = args->typhandler->attDescs[i].attname;
 52       ad[i].atttypmod = args->typhandler->attDescs[i].atttypmod;
 53     }
 54   }
 55 
 56   res = PQcopyResult(args->get.result,
 57     PG_COPYRES_EVENTS | PG_COPYRES_NOTICEHOOKS);
 58 
 59   if (!res)
 60   {
 61     free(ad);
 62     PQseterror(PQT_OUTOFMEMORY);
 63     return NULL;
 64   }
 65 
 66   if (!PQsetResultAttrs(res, nattrs, ad))
 67   {
 68     PQclear(res);
 69     PQseterror(PQT_OUTOFMEMORY);
 70     res = NULL;
 71   }
 72 
 73   free(ad);
 74   return res;
 75 }
 76 
 77 #ifdef STRICT_MEMORY_ALIGNMENT
 78 short
 79 pqt_buf_getint2(char *buffer)
 80 {
 81   short n;
 82   memcpy(&n, buffer, 2);
 83   return (short) ntohs(n);
 84 }
 85 
 86 int
 87 pqt_buf_getint4(char *buffer)
 88 {
 89   int n;
 90   memcpy(&n, buffer, 4);
 91   return (int) ntohl(n);
 92 }
 93 #endif
 94 
 95 void
 96 pqt_swap8(void *outp, void *inp, int tonet)
 97 {
 98   static int n = 1;
 99 
100 #ifdef STRICT_MEMORY_ALIGNMENT
101   unsigned int in[2];
102   unsigned int out[2];
103   memcpy(&in, inp, 8);
104 #else
105   unsigned int *in = (unsigned int *) inp;
106   unsigned int *out = (unsigned int *) outp;
107 #endif
108 
109   /* swap when needed */
110   if (*(char *)&n == 1)
111   {
112     out[0] = (unsigned int) (tonet ? htonl(in[1]) : ntohl(in[1]));
113     out[1] = (unsigned int) (tonet ? htonl(in[0]) : ntohl(in[0]));
114   }
115   else
116   {
117     out[0] = in[0];
118     out[1] = in[1];
119   }
120 
121 #ifdef STRICT_MEMORY_ALIGNMENT
122   memcpy(outp, out, 8);
123 #endif
124 }
125 
126 int
127 pqt_text_to_int8(char *val, void *out)
128 {
129   PGint8 n;
130 
131   /* NOTE: port version of strtoll in port.c. */
132   errno = 0;
133   if ((n = (PGint8) strtoll(val, NULL, 10)) == 0 && errno)
134     return -1;
135 
136   *(PGint8 *) out = n;
137   return 0;
138 }
139 
140 int
141 pqt_text_to_float8(double *f8, char *text, char **endptr)
142 {
143   double d;
144 
145   errno = 0;
146   if ((d = strtod(text, endptr)) == 0 && errno)
147     return 0;
148 
149   *f8 = d;
150   return 1;
151 }
152 
153 /* Checks buffer and truncates 'src' if 'dest' is too small. */
154 char *
155 pqt_strcpy(char *dest, size_t size, const char *src)
156 {
157   size_t src_len = strlen(src);
158 
159   /* truncate if needed */
160   if (src_len >= size)
161     src_len = size - 1;
162 
163   memcpy(dest, src, src_len);
164   dest[src_len] = 0;
165   return dest;
166 }
167 
168 
169 /* ---------------------------
170  * Everything below was taken from postgresql project
171  * A couple of changes here and there.
172  */
173 
174 #ifndef HIGHBIT
175 # define HIGHBIT (0x80)
176 #endif
177 
178 #ifndef IS_HIGHBIT_SET
179 # define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT)
180 #endif
181 
182 /*
183  * Fold a character to lower case.
184  *
185  * Unlike some versions of tolower(), this is safe to apply to characters
186  * that aren't upper case letters.  Note however that the whole thing is
187  * a bit bogus for multibyte character sets.
188  */
189 unsigned char
190 pqt_tolower(unsigned char ch)
191 {
192   if (ch >= 'A' && ch <= 'Z')
193     ch += 'a' - 'A';
194   else if (IS_HIGHBIT_SET(ch) && isupper(ch))
195     ch = (unsigned char) tolower(ch);
196   return ch;
197 }
198 
199 /*
200  * Case-independent comparison of two null-terminated strings.
201  */
202 int
203 pqt_strcasecmp(const char *s1, const char *s2)
204 {
205   for (;;)
206   {
207     unsigned char ch1 = (unsigned char) *s1++;
208     unsigned char ch2 = (unsigned char) *s2++;
209 
210     if (ch1 != ch2)
211     {
212       if (ch1 >= 'A' && ch1 <= 'Z')
213         ch1 += 'a' - 'A';
214       else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
215         ch1 = (unsigned char)tolower(ch1);
216 
217       if (ch2 >= 'A' && ch2 <= 'Z')
218         ch2 += 'a' - 'A';
219       else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
220         ch2 = (unsigned char)tolower(ch2);
221 
222       if (ch1 != ch2)
223         return (int) ch1 - (int) ch2;
224     }
225     if (ch1 == 0)
226       break;
227   }
228   return 0;
229 }
230 
231 /*
232  * Case-independent comparison of two not-necessarily-null-terminated
233  * strings. At most n bytes will be examined from each string.
234  */
235 int
236 pqt_strncasecmp(const char *s1, const char *s2, size_t n)
237 {
238   while (n-- > 0)
239   {
240     unsigned char ch1 = (unsigned char) *s1++;
241     unsigned char ch2 = (unsigned char) *s2++;
242 
243     if (ch1 != ch2)
244     {
245       if (ch1 >= 'A' && ch1 <= 'Z')
246         ch1 += 'a' - 'A';
247       else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
248         ch1 = (unsigned char)tolower(ch1);
249 
250       if (ch2 >= 'A' && ch2 <= 'Z')
251         ch2 += 'a' - 'A';
252       else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
253         ch2 = (unsigned char)tolower(ch2);
254 
255       if (ch1 != ch2)
256         return (int) ch1 - (int) ch2;
257     }
258     if (ch1 == 0)
259       break;
260   }
261   return 0;
262 }