1999-04-25 05:19:27 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* stringinfo.c
|
1999-04-25 05:19:27 +02:00
|
|
|
*
|
|
|
|
* StringInfo 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 palloc().
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
1999-04-25 05:19:27 +02:00
|
|
|
* $Id: stringinfo.c,v 1.15 1999/04/25 03:19:25 tgl Exp $
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-12-14 09:11:17 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
1996-07-09 08:22:35 +02:00
|
|
|
#include <string.h>
|
1996-11-06 09:27:16 +01:00
|
|
|
|
1999-04-25 05:19:27 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
#include "lib/stringinfo.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1998-12-14 09:11:17 +01:00
|
|
|
/*
|
1996-07-09 08:22:35 +02:00
|
|
|
* makeStringInfo
|
|
|
|
*
|
1999-04-25 05:19:27 +02:00
|
|
|
* Create an empty 'StringInfoData' & return a pointer to it.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
StringInfo
|
1999-04-25 05:19:27 +02:00
|
|
|
makeStringInfo(void)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
StringInfo res;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
res = (StringInfo) palloc(sizeof(StringInfoData));
|
|
|
|
if (res == NULL)
|
1999-04-25 05:19:27 +02:00
|
|
|
elog(ERROR, "makeStringInfo: Out of memory");
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-04-25 05:19:27 +02:00
|
|
|
initStringInfo(res);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-09-01 05:29:17 +02:00
|
|
|
return res;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1998-12-14 09:11:17 +01:00
|
|
|
/*
|
1999-04-25 05:19:27 +02:00
|
|
|
* initStringInfo
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-04-25 05:19:27 +02:00
|
|
|
* Initialize a StringInfoData struct (with previously undefined contents)
|
|
|
|
* to describe an empty string.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
initStringInfo(StringInfo str)
|
|
|
|
{
|
|
|
|
int size = 256; /* initial default buffer size */
|
|
|
|
|
|
|
|
str->data = palloc(size);
|
|
|
|
if (str->data == NULL)
|
|
|
|
elog(ERROR,
|
|
|
|
"initStringInfo: Out of memory (%d bytes requested)", size);
|
|
|
|
str->maxlen = size;
|
|
|
|
str->len = 0;
|
|
|
|
str->data[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* enlargeStringInfo
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-04-25 05:19:27 +02:00
|
|
|
* Internal routine: make sure there is enough space for 'needed' more bytes
|
|
|
|
* ('needed' does not include the terminating null).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
enlargeStringInfo(StringInfo str, int needed)
|
|
|
|
{
|
|
|
|
int newlen;
|
|
|
|
char *newdata;
|
|
|
|
|
|
|
|
needed += str->len + 1; /* total space required now */
|
|
|
|
if (needed <= str->maxlen)
|
|
|
|
return; /* 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 = 2 * str->maxlen;
|
|
|
|
while (needed > newlen)
|
|
|
|
newlen = 2 * newlen;
|
|
|
|
|
|
|
|
newdata = palloc(newlen);
|
|
|
|
if (newdata == NULL)
|
|
|
|
elog(ERROR,
|
|
|
|
"enlargeStringInfo: Out of memory (%d bytes requested)", newlen);
|
|
|
|
|
|
|
|
/* OK, transfer data into new buffer, and release old buffer */
|
|
|
|
memcpy(newdata, str->data, str->len + 1);
|
|
|
|
pfree(str->data);
|
|
|
|
str->data = newdata;
|
|
|
|
str->maxlen = newlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* appendStringInfo
|
|
|
|
*
|
|
|
|
* 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.
|
1998-12-14 09:11:17 +01:00
|
|
|
*
|
1999-04-25 05:19:27 +02:00
|
|
|
* CAUTION: the current implementation has a 1K limit on the amount of text
|
|
|
|
* generated in a single call (not on the total string length).
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
1999-04-25 05:19:27 +02:00
|
|
|
appendStringInfo(StringInfo str, const char *fmt, ...)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-04-25 05:19:27 +02:00
|
|
|
va_list args;
|
|
|
|
char buffer[1024];
|
|
|
|
int buflen;
|
|
|
|
|
|
|
|
Assert(str != NULL);
|
1998-12-14 09:11:17 +01:00
|
|
|
|
|
|
|
va_start(args, fmt);
|
1999-04-25 05:19:27 +02:00
|
|
|
buflen = vsnprintf(buffer, sizeof(buffer), fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
/* Make more room if needed */
|
|
|
|
enlargeStringInfo(str, buflen);
|
|
|
|
|
|
|
|
/* OK, append the data, including the trailing null */
|
|
|
|
memcpy(str->data + str->len, buffer, buflen + 1);
|
|
|
|
str->len += buflen;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-04-25 05:19:27 +02:00
|
|
|
/*------------------------
|
|
|
|
* appendStringInfoChar
|
|
|
|
* Append a single byte to str.
|
|
|
|
* Like appendStringInfo(str, "%c", ch) but much faster.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
appendStringInfoChar(StringInfo str, char ch)
|
|
|
|
{
|
1998-01-06 19:53:02 +01:00
|
|
|
Assert(str != NULL);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-04-25 05:19:27 +02:00
|
|
|
/* Make more room if needed */
|
|
|
|
enlargeStringInfo(str, 1);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-04-25 05:19:27 +02:00
|
|
|
/* OK, append the character */
|
|
|
|
str->data[str->len] = ch;
|
|
|
|
str->len++;
|
|
|
|
str->data[str->len] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* appendBinaryStringInfo
|
|
|
|
*
|
|
|
|
* Append arbitrary binary data to a StringInfo, allocating more space
|
|
|
|
* if necessary.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
|
|
|
|
{
|
|
|
|
Assert(str != NULL);
|
|
|
|
|
|
|
|
/* Make more room if needed */
|
|
|
|
enlargeStringInfo(str, datalen);
|
|
|
|
|
|
|
|
/* 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...
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1999-04-25 05:19:27 +02:00
|
|
|
str->data[str->len] = '\0';
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|