1 2 /* 3 * util.c 4 * Utility functions. 5 * 6 * Copyright (c) 2009 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 strings. 233 * 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 } |