hpqtypes-1.2.2: libpqtypes/src/utils.c
/*
* util.c
* Utility functions.
*
* Copyright (c) 2011 eSilo, LLC. All rights reserved.
* This is free software; see the source for copying conditions. There is
* NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "libpqtypes-int.h"
PGresult *
pqt_copyresult(PGtypeArgs *args, int nattrs)
{
int i;
PGresult *res;
int tableid, columnid, format;
PGresAttDesc *ad = (PGresAttDesc *) malloc(nattrs * sizeof(PGresAttDesc));
if (!ad)
{
PQseterror(args->err, PQT_OUTOFMEMORY);
return NULL;
}
tableid = PQftable(args->get.result, args->get.field_num);
columnid = PQftablecol(args->get.result, args->get.field_num);
format = PQfformat(args->get.result, args->get.field_num);
for (i=0; i < nattrs; i++)
{
ad[i].tableid = tableid;
ad[i].columnid = columnid;
ad[i].format = format;
/* simple array */
if (args->typhandler->nattrs == 0)
{
ad[i].typid = args->typhandler->typoid;
ad[i].typlen = args->typhandler->typlen;
ad[i].name = NULL;
ad[i].atttypmod = -1;
}
/* composite/record */
else
{
ad[i].typid = args->typhandler->attDescs[i].attoid;
ad[i].typlen = args->typhandler->attDescs[i].attlen;
ad[i].name = args->typhandler->attDescs[i].attname;
ad[i].atttypmod = args->typhandler->attDescs[i].atttypmod;
}
}
res = PQcopyResult(args->get.result,
PG_COPYRES_EVENTS | PG_COPYRES_NOTICEHOOKS);
if (!res)
{
free(ad);
PQseterror(args->err, PQT_OUTOFMEMORY);
return NULL;
}
if (!PQsetResultAttrs(res, nattrs, ad))
{
PQclear(res);
PQseterror(args->err, PQT_OUTOFMEMORY);
res = NULL;
}
free(ad);
return res;
}
#ifdef STRICT_MEMORY_ALIGNMENT
short
pqt_buf_getint2(char *buffer)
{
short n;
memcpy(&n, buffer, 2);
return (short) ntohs(n);
}
int
pqt_buf_getint4(char *buffer)
{
int n;
memcpy(&n, buffer, 4);
return (int) ntohl(n);
}
#endif
void
pqt_swap8(void *outp, void *inp, int tonet)
{
static int n = 1;
#ifdef STRICT_MEMORY_ALIGNMENT
unsigned int in[2];
unsigned int out[2];
memcpy(&in, inp, 8);
#else
unsigned int *in = (unsigned int *) inp;
unsigned int *out = (unsigned int *) outp;
#endif
/* swap when needed */
if (*(char *)&n == 1)
{
out[0] = (unsigned int) (tonet ? htonl(in[1]) : ntohl(in[1]));
out[1] = (unsigned int) (tonet ? htonl(in[0]) : ntohl(in[0]));
}
else
{
out[0] = in[0];
out[1] = in[1];
}
#ifdef STRICT_MEMORY_ALIGNMENT
memcpy(outp, out, 8);
#endif
}
int
pqt_text_to_int8(char *val, void *out)
{
PGint8 n;
/* NOTE: port version of strtoll in port.c. */
errno = 0;
if ((n = (PGint8) strtoll(val, NULL, 10)) == 0 && errno)
return -1;
*(PGint8 *) out = n;
return 0;
}
int
pqt_text_to_float8(double *f8, char *text, char **endptr)
{
double d;
errno = 0;
if ((d = strtod(text, endptr)) == 0 && errno)
return 0;
*f8 = d;
return 1;
}
/* Checks buffer and truncates 'src' if 'dest' is too small. */
char *
pqt_strcpy(char *dest, size_t size, const char *src)
{
size_t src_len = strlen(src);
/* truncate if needed */
if (src_len >= size)
src_len = size - 1;
memcpy(dest, src, src_len);
dest[src_len] = 0;
return dest;
}
/* ---------------------------
* Everything below was taken from postgresql project
* A couple of changes here and there.
*/
#ifndef HIGHBIT
# define HIGHBIT (0x80)
#endif
#ifndef IS_HIGHBIT_SET
# define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT)
#endif
/*
* Fold a character to lower case.
*
* Unlike some versions of tolower(), this is safe to apply to characters
* that aren't upper case letters. Note however that the whole thing is
* a bit bogus for multibyte character sets.
*/
unsigned char
pqt_tolower(unsigned char ch)
{
if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch) && isupper(ch))
ch = (unsigned char) tolower(ch);
return ch;
}
/*
* Case-independent comparison of two null-terminated strings.
*/
int
pqt_strcasecmp(const char *s1, const char *s2)
{
for (;;)
{
unsigned char ch1 = (unsigned char) *s1++;
unsigned char ch2 = (unsigned char) *s2++;
if (ch1 != ch2)
{
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
ch1 = (unsigned char)tolower(ch1);
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
ch2 = (unsigned char)tolower(ch2);
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
}
if (ch1 == 0)
break;
}
return 0;
}
/*
* Case-independent comparison of two not-necessarily-null-terminated
* strings. At most n bytes will be examined from each string.
*/
int
pqt_strncasecmp(const char *s1, const char *s2, size_t n)
{
while (n-- > 0)
{
unsigned char ch1 = (unsigned char) *s1++;
unsigned char ch2 = (unsigned char) *s2++;
if (ch1 != ch2)
{
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
ch1 = (unsigned char)tolower(ch1);
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
ch2 = (unsigned char)tolower(ch2);
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
}
if (ch1 == 0)
break;
}
return 0;
}