postgresql/src/interfaces/libpq/pqexpbuffer.c
Tom Lane ab5cafa5d3 Update frontend libpq to remove limits on query lengths,
error/notice message lengths, and number of fields per tuple.  Add
pqexpbuffer.c/.h, a frontend version of backend's stringinfo module.
This is first step in applying Mike Ansley's long-query patches,
even though he didn't do any of these particular changes...
1999-08-31 01:37:37 +00:00

255 lines
6.2 KiB
C

/*-------------------------------------------------------------------------
*
* pqexpbuffer.c
*
* PQExpBuffer provides an indefinitely-extensible string data type.
* It can be used to buffer either ordinary C strings (null-terminated text)
* or arbitrary binary data. All storage is allocated with malloc().
*
* This module is essentially the same as the backend's StringInfo data type,
* but it is intended for use in frontend libpq and client applications.
* Thus, it does not rely on palloc(), elog(), nor vsnprintf().
*
* Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.1 1999/08/31 01:37:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "pqexpbuffer.h"
/*
* createPQExpBuffer
*
* Create an empty 'PQExpBufferData' & return a pointer to it.
*/
PQExpBuffer
createPQExpBuffer(void)
{
PQExpBuffer res;
res = (PQExpBuffer) malloc(sizeof(PQExpBufferData));
if (res != NULL)
initPQExpBuffer(res);
return res;
}
/*
* initPQExpBuffer
*
* Initialize a PQExpBufferData struct (with previously undefined contents)
* to describe an empty string.
*/
void
initPQExpBuffer(PQExpBuffer str)
{
str->data = (char *) malloc(INITIAL_EXPBUFFER_SIZE);
if (str->data == NULL)
{
str->maxlen = 0;
str->len = 0;
}
else
{
str->maxlen = INITIAL_EXPBUFFER_SIZE;
str->len = 0;
str->data[0] = '\0';
}
}
/*------------------------
* destroyPQExpBuffer(str);
* free()s both the data buffer and the PQExpBufferData.
* This is the inverse of createPQExpBuffer().
*/
void
destroyPQExpBuffer(PQExpBuffer str)
{
if (str)
{
termPQExpBuffer(str);
free(str);
}
}
/*------------------------
* termPQExpBuffer(str)
* free()s the data buffer but not the PQExpBufferData itself.
* This is the inverse of initPQExpBuffer().
*/
void
termPQExpBuffer(PQExpBuffer str)
{
if (str->data)
{
free(str->data);
str->data = NULL;
}
}
/*------------------------
* resetPQExpBuffer
* Reset a PQExpBuffer to empty
*/
void
resetPQExpBuffer(PQExpBuffer str)
{
if (str)
{
str->len = 0;
if (str->data)
str->data[0] = '\0';
}
}
/*------------------------
* enlargePQExpBuffer
* Make sure there is enough space for 'needed' more bytes in the buffer
* ('needed' does not include the terminating null).
*
* Returns 1 if OK, 0 if failed to enlarge buffer.
*/
int
enlargePQExpBuffer(PQExpBuffer str, int needed)
{
int newlen;
char *newdata;
needed += str->len + 1; /* total space required now */
if (needed <= str->maxlen)
return 1; /* got enough space already */
/*
* We don't want to allocate just a little more space with each
* append; for efficiency, double the buffer size each time it
* overflows. Actually, we might need to more than double it if
* 'needed' is big...
*/
newlen = str->maxlen ? (2 * str->maxlen) : 64;
while (needed > newlen)
newlen = 2 * newlen;
newdata = (char *) realloc(str->data, newlen);
if (newdata != NULL)
{
str->data = newdata;
str->maxlen = newlen;
return 1;
}
return 0;
}
/*------------------------
* printfPQExpBuffer
* Format text data under the control of fmt (an sprintf-like format string)
* and insert it into str. More space is allocated to str if necessary.
* This is a convenience routine that does the same thing as
* resetPQExpBuffer() followed by appendPQExpBuffer().
*
* CAUTION: the frontend version of this routine WILL FAIL if the result of
* the sprintf formatting operation exceeds 1KB of data (but the size of the
* pre-existing string in the buffer doesn't matter). We could make it
* support larger strings, but that requires vsnprintf() which is not
* universally available. Currently there is no need for long strings to be
* formatted in the frontend. We could support it, if necessary, by
* conditionally including a vsnprintf emulation.
*/
void
printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
char buffer[1024];
va_start(args, fmt);
vsprintf(buffer, fmt, args);
va_end(args);
resetPQExpBuffer(str);
appendPQExpBufferStr(str, buffer);
}
/*------------------------
* appendPQExpBuffer
*
* Format text data under the control of fmt (an sprintf-like format string)
* and append it to whatever is already in str. More space is allocated
* to str if necessary. This is sort of like a combination of sprintf and
* strcat.
*
* CAUTION: the frontend version of this routine WILL FAIL if the result of
* the sprintf formatting operation exceeds 1KB of data (but the size of the
* pre-existing string in the buffer doesn't matter). We could make it
* support larger strings, but that requires vsnprintf() which is not
* universally available. Currently there is no need for long strings to be
* formatted in the frontend. We could support it, if necessary, by
* conditionally including a vsnprintf emulation.
*/
void
appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
char buffer[1024];
va_start(args, fmt);
vsprintf(buffer, fmt, args);
va_end(args);
appendPQExpBufferStr(str, buffer);
}
/*------------------------
* appendPQExpBufferStr
* Append the given string to a PQExpBuffer, allocating more space
* if necessary.
*/
void
appendPQExpBufferStr(PQExpBuffer str, const char *data)
{
appendBinaryPQExpBuffer(str, data, strlen(data));
}
/*------------------------
* appendPQExpBufferChar
* Append a single byte to str.
* Like appendPQExpBuffer(str, "%c", ch) but much faster.
*/
void
appendPQExpBufferChar(PQExpBuffer str, char ch)
{
/* Make more room if needed */
if (! enlargePQExpBuffer(str, 1))
return;
/* OK, append the character */
str->data[str->len] = ch;
str->len++;
str->data[str->len] = '\0';
}
/*
* appendBinaryPQExpBuffer
*
* Append arbitrary binary data to a PQExpBuffer, allocating more space
* if necessary.
*/
void
appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, int datalen)
{
/* Make more room if needed */
if (! enlargePQExpBuffer(str, datalen))
return;
/* OK, append the data */
memcpy(str->data + str->len, data, datalen);
str->len += datalen;
/*
* Keep a trailing null in place, even though it's probably useless
* for binary data...
*/
str->data[str->len] = '\0';
}