hpqtypes-1.2.2: libpqtypes/src/error.c
/*
* error.c
* The functions in this file represent the libpqtypes error
* system. It offers the API user the ability to set/get errors.
* The error system uses local PGerror structure.
*
* 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 <assert.h>
#include "libpqtypes-int.h"
static void
vseterror(PGerror *err, const char *format, va_list ap, int append);
void
PQseterror(PGerror *err, const char *format, ...)
{
assert(format != NULL);
va_list ap;
va_start(ap, format);
vseterror(err, format, ap, FALSE);
}
/* errorf() callback for PGtypeArgs, see PQputf() and PQgetf().
* Always returns -1.
*/
int
pqt_argserrorf(PGtypeArgs *args, const char *format, ...)
{
va_list ap;
char fqtn[200];
if (!args || !format || !*format)
return -1;
pqt_fqtn(fqtn, sizeof(fqtn), args->typhandler->typschema,
args->typhandler->typname);
/* put the header */
PQseterror(args->err, "%s[pos:%d] - ", fqtn, args->typpos);
/* append message from type handler */
va_start(ap, format);
vseterror(args->err, format, ap, TRUE);
return -1;
}
static void
vseterror(PGerror *err, const char *format, va_list ap, int append)
{
int n;
int curlen = 0;
int size;
va_list ap2;
char *msg = NULL;
if (!err)
return;
if (append)
curlen = (int) strlen(err->msg);
else
*err->msg = 0;
va_copy(ap2, ap);
n = pqt_vsnprintf(err->msg + curlen, sizeof(err->msg) - curlen, format, ap2);
va_end(ap2);
if (n > -1)
return;
/* pqterr_t msg buffer is too small for the complete message. We have
* use a temporary buffer to get a successful sprintf so we can
* pqt_strcpy() the result; which truncates to fit.
*/
size = (int) sizeof(err->msg) * 2;
if (!(msg = (char *) malloc(size)))
return;
while (1)
{
char *p;
va_copy(ap2, ap);
n = pqt_vsnprintf(msg + curlen, size - curlen, format, ap2);
va_end(ap2);
/* success */
if (n > -1)
break;
/* need more space */
n = size * 2;
if (!(p = pqt_realloc(msg, n)))
{
/* we're here because sprintf failed, don't trust buffer contents */
*msg = 0;
break;
}
msg = p;
size = n;
}
pqt_strcpy(err->msg, sizeof(err->msg), msg);
free(msg);
}