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 *
pqt_copyresult(PGtypeArgs * args,int nattrs)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
pqt_buf_getint2(char * buffer)79 pqt_buf_getint2(char *buffer)
80 {
81 short n;
82 memcpy(&n, buffer, 2);
83 return (short) ntohs(n);
84 }
85
86 int
pqt_buf_getint4(char * buffer)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
pqt_swap8(void * outp,void * inp,int tonet)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
pqt_text_to_int8(char * val,void * out)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
pqt_text_to_float8(double * f8,char * text,char ** endptr)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 *
pqt_strcpy(char * dest,size_t size,const char * src)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
pqt_tolower(unsigned char ch)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
pqt_strcasecmp(const char * s1,const char * s2)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
pqt_strncasecmp(const char * s1,const char * s2,size_t n)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 }
263
264
265
266